From b47b4e92c7d11ba73f7bad9172962d059ad8b9cf Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Fri, 18 Jul 2025 23:57:58 +0100 Subject: [PATCH 01/13] update collection to table --- .../+page.markdoc | 22 ++++----- .../+page.markdoc | 20 ++++---- .../blog/post/ai-crystal-ball/+page.markdoc | 32 ++++++------- .../+page.markdoc | 6 +-- .../post/announcing-bulk-api/+page.markdoc | 2 +- .../post/announcing-csv-imports/+page.markdoc | 14 +++--- .../+page.markdoc | 2 +- .../announcing-database-upsert/+page.markdoc | 2 +- .../+page.markdoc | 12 ++--- .../+page.markdoc | 10 ++-- .../+page.markdoc | 4 +- .../+page.markdoc | 46 +++++++++---------- .../best-pagination-technique/+page.markdoc | 16 +++---- .../+page.markdoc | 26 +++++------ .../+page.markdoc | 14 +++--- .../building-init-giveaway-app/+page.markdoc | 26 +++++------ .../+page.markdoc | 4 +- .../ci-cd-examples-in-appwrite/+page.markdoc | 20 ++++---- .../customer-stories-smartbee/+page.markdoc | 10 ++-- .../post/customer-stories-undo/+page.markdoc | 2 +- .../developer-tools-appwrite/+page.markdoc | 2 +- .../+page.markdoc | 2 +- .../hacktoberfest-ideas-2024/+page.markdoc | 4 +- .../+page.markdoc | 22 ++++----- .../+page.markdoc | 32 ++++++------- .../+page.markdoc | 10 ++-- .../post/improve-devex-dev-keys/+page.markdoc | 12 ++--- .../+page.markdoc | 6 +-- .../+page.markdoc | 14 +++--- .../+page.markdoc | 4 +- .../+page.markdoc | 22 ++++----- .../post/offline-first-journal/+page.markdoc | 28 +++++------ .../+page.markdoc | 4 +- .../+page.markdoc | 10 ++-- .../product-update-jan-2025/+page.markdoc | 28 +++++------ .../product-update-september/+page.markdoc | 10 ++-- .../+page.markdoc | 4 +- .../+page.markdoc | 4 +- .../+page.markdoc | 38 +++++++-------- .../+page.markdoc | 2 +- .../+page.markdoc | 20 ++++---- .../understand-data-queries/+page.markdoc | 8 ++-- .../+page.markdoc | 2 +- 43 files changed, 289 insertions(+), 289 deletions(-) diff --git a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc index 00fadd93bc..2d45fcba5b 100644 --- a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc +++ b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc @@ -29,7 +29,7 @@ Appwrite Functions can be executed by various types of events, which allows you ## Global environment variables -Aside from environment variables at the function level, Appwrite also allows you to environment variables at the project level so that they can be shared across multiple functions in a single project. +Aside from environment variables at the function level, Appwrite also allows you to environment variables at the project level so that they can be shared across multiple functions in a single project. ## Permissions system @@ -51,7 +51,7 @@ Once your function is set up, we can try some examples: ## Example 1: AI Chatbot using GPT-3.5 -The first example is a simple chatbot function that accepts a prompt in the request body and returns an answer in the response from the ChatGPT API. +The first example is a simple chatbot function that accepts a prompt in the request body and returns an answer in the response from the ChatGPT API. To do this, we must first add the `go-openai` dependency to our project’s `mod` file. @@ -138,7 +138,7 @@ You can then deploy this function using the `appwrite deploy function` command. ## Example 2: HTML Resume -The second example is an online HTML-based resume that you can deliver online through the function. +The second example is an online HTML-based resume that you can deliver online through the function. For this, the first thing we do is create a `static` directory in the function folder and add a file, `resume.html` with the contents of our resume. You can [copy our template](https://github.com/appwrite-community/go-function-examples/blob/main/functions/go-resume/static/resume.html) if you’d like. @@ -178,7 +178,7 @@ You can then deploy this function using the `appwrite deploy function` command. ## Example 3: URL Shortener -The third example is a personal URL shortener that stores your shortened URL path and long URL in an Appwrite Database and redirects the consumer to the appropriate long URL on pinging the shortened URL. +The third example is a personal URL shortener that stores your shortened URL path and long URL in an Appwrite Database and redirects the consumer to the appropriate long URL on pinging the shortened URL. To build this function, create a `services` directory in the function folder and add a file `setup.go`. Here, we will add the necessary functions to initialize our Appwrite database. @@ -199,8 +199,8 @@ func DoesDatabaseExist(dbs databases.Databases, dbId string) bool { return true } -func DoesCollectionExist(dbs databases.Databases, dbId string, collId string) bool { - _, err := dbs.GetCollection(dbId, collId) +func DoesTableExist(dbs databases.Databases, dbId string, collId string) bool { + _, err := dbs.GetTable(dbId, collId) if err != nil { return false } @@ -224,13 +224,13 @@ func InitialiseDatabase(Context openruntimes.Context, dbs databases.Databases, d ) } - doesCollExist := DoesCollectionExist(dbs, dbId, collId) + doesCollExist := DoesTableExist(dbs, dbId, collId) if !doesCollExist { - dbs.CreateCollection( + dbs.CreateTable( dbId, collId, "URLs", - dbs.WithCreateCollectionPermissions([]string{permission.Read("any")}), + dbs.WithCreateTablePermissions([]string{permission.Read("any")}), ) } @@ -279,7 +279,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { databases := appwrite.NewDatabases(client) dbId := "urlDatabase" - collId := "urlCollection" + collId := "urlTable" services.InitialiseDatabase(Context, *databases, dbId, collId) @@ -345,7 +345,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { You can then deploy this function using the `appwrite deploy function` command. -After deployment, go to the Settings tab on the Function page in your Appwrite project and enable the following scopes for the dynamic API key: `databases.read`, `databases.write`, `collections.read`, `collections.write`, `attributes.read`, `attributes.write`, `documents.read`, `documents.write`, +After deployment, go to the Settings tab on the Function page in your Appwrite project and enable the following scopes for the dynamic API key: `databases.read`, `databases.write`, `tables.read`, `tables.write`, `attributes.read`, `attributes.write`, `documents.read`, `documents.write`, # More resources diff --git a/src/routes/blog/post/add-a-search-function-to-your-app/+page.markdoc b/src/routes/blog/post/add-a-search-function-to-your-app/+page.markdoc index a68bc9264d..d131964bbc 100644 --- a/src/routes/blog/post/add-a-search-function-to-your-app/+page.markdoc +++ b/src/routes/blog/post/add-a-search-function-to-your-app/+page.markdoc @@ -16,14 +16,14 @@ One such integration you can implement using Appwrite Functions is **Searching** # Setting up the Template -Meilisearch is a flexible and powerful user-focused search engine that can be added to any website or application. The purpose of this function template is to sync documents in an Appwrite database collection to a Meilisearch index. Using this function template, users can explore, search, and retrieve information from the connected database collection. Through this template, documents from the Appwrite collection are systematically indexed within Meilisearch. +Meilisearch is a flexible and powerful user-focused search engine that can be added to any website or application. The purpose of this function template is to sync documents in an Appwrite database table to a Meilisearch index. Using this function template, users can explore, search, and retrieve information from the connected database table. Through this template, documents from the Appwrite table are systematically indexed within Meilisearch. To use the function, you need the following set of keys: - `APPWRITE_KEY` - API Key to talk to Appwrite backend APIs.To generate API Keys you can follow the documentation [here](https://appwrite.io/docs/getting-started-for-server#apiKey) - `APPWRITE_ENDPOINT` - To get the Appwrite endpoint, you need to go to [Appwrite](https://cloud.appwrite.io/) and find it under “Settings” -- `APPWRITE_DATABASE_ID` - The ID of the Appwrite database that contains the collection to sync. You can find the documentation [here](https://appwrite.io/docs/databases). -- `APPWRITE_COLLECTION_ID` - The ID of the collection in the Appwrite database to sync. +- `APPWRITE_DATABASE_ID` - The ID of the Appwrite database that contains the table to sync. You can find the documentation [here](https://appwrite.io/docs/databases). +- `APPWRITE_TABLE_ID` - The ID of the table in the Appwrite database to sync. To use Meilisearch, you can either self-host it using the command 👇 @@ -31,7 +31,7 @@ To use Meilisearch, you can either self-host it using the command 👇 curl -L [https://install.meilisearch.com](https://install.meilisearch.com/) | sh ``` -Or use [Meilisearch Cloud](https://www.meilisearch.com/cloud). For this example, we will assume that you are using Meilisearch Cloud. +Or use [Meilisearch Cloud](https://www.meilisearch.com/cloud). For this example, we will assume that you are using Meilisearch Cloud. Here’s the keys you need: @@ -40,7 +40,7 @@ Here’s the keys you need: ![Overview Meilisearch](/images/blog/add-a-search-function-to-your-app/functions.png) -- `MEILISEARCH_ADMIN_API_KEY` - This is the admin API key for Meilisearch. You will find it in the Meilisearch Console under “API Key”. +- `MEILISEARCH_ADMIN_API_KEY` - This is the admin API key for Meilisearch. You will find it in the Meilisearch Console under “API Key”. - `MEILISEARCH_SEARCH_API_KEY` - This is the API Key for Meilisearch search operations. To get this, you need you create a new index from the Meilisearch Console. Once created you will find it under `Overview` as `Default Search API Key` @@ -51,11 +51,11 @@ Here’s the keys you need: ![Keys](/images/blog/add-a-search-function-to-your-app/connect.png) - `MEILISEARCH_INDEX_NAME` - Name of the Meilisearch index to which the documents will be synchronized. For e.g, in the above picture, the Index name is `Newindex`. You can also find it under `Settings` as `Index Name`. - + ## Preparing the Function -The function template syncs documents in an Appwrite database collection to a Meilisearch index. It should get you up and running, but you will need to add real data to build a useful search index. +The function template syncs documents in an Appwrite database table to a Meilisearch index. It should get you up and running, but you will need to add real data to build a useful search index. If you want to see the source code, you can find it on our [templates GitHub repository](https://github.com/appwrite/templates/tree/main/node/sync-with-meilisearch). Now, let’s navigate to our functions page on **[Appwrite](https://cloud.appwrite.io/)**. From there, we will select the **Templates** tab, search for and select the **Sync with Meilisearch** function template. @@ -63,7 +63,7 @@ If you want to see the source code, you can find it on our [templates GitHub re ![templates](/images/blog/add-a-search-function-to-your-app/templates.png) -The function requires `APPWRITE_API_KEY`, `APPWRITE_DATABASE_ID`, `APPWRITE_COLLECTION_ID` , `MEILISEARCH_ENDPOINT`, `MEILISEARCH_ADMIN_API_KEY`, `MEILISEARCH_SEARCH_API_KEY`, `MEILISEARCH_INDEX_NAME`. Once you have added them you can proceed to the Connect step. +The function requires `APPWRITE_API_KEY`, `APPWRITE_DATABASE_ID`, `APPWRITE_TABLE_ID` , `MEILISEARCH_ENDPOINT`, `MEILISEARCH_ADMIN_API_KEY`, `MEILISEARCH_SEARCH_API_KEY`, `MEILISEARCH_INDEX_NAME`. Once you have added them you can proceed to the Connect step. Select **Create a new repository** (this will generate a GitHub repository for you with the function), and leave the production branch and root settings as default to create this function. @@ -84,13 +84,13 @@ Visit the **Domains** tab on the function page and copy the domain URL to test We’ve added search functionality to our app and opened up many possibilities to improve the experience of our app’s users. How can the *template* be extended ? -- Using events to automatically index new collections +- Using events to automatically index new tables - Using weights and other meilisearch features to optimise search such as excluding certain fields from indexing Some examples are: 1. **Real-time Data Exploration:** It can be used to provide real-time search capabilities for datasets and data streams, allowing users to explore and analyze data in real-time. -2. **Content Management Systems:** The function template can be integrated into content management systems (CMS) to facilitate efficient content retrieval for editors and site visitors. +2. **Content Management Systems:** The function template can be integrated into content management systems (CMS) to facilitate efficient content retrieval for editors and site visitors. Be sure to check out the other available Function Templates. We’ve created multiple that could be of use in your projects. You can find the [templates GitHub repository here](https://github.com/appwrite/templates). diff --git a/src/routes/blog/post/ai-crystal-ball/+page.markdoc b/src/routes/blog/post/ai-crystal-ball/+page.markdoc index 1b049862b1..0ca789bff9 100644 --- a/src/routes/blog/post/ai-crystal-ball/+page.markdoc +++ b/src/routes/blog/post/ai-crystal-ball/+page.markdoc @@ -20,7 +20,7 @@ In order to build this application, we have a few prerequisites. We must set up - OpenAI API key - GitHub OAuth app - Appwrite OAuth adapter for GitHub -- Appwrite collections to store GitHub data and destinies +- Appwrite tables to store GitHub data and destinies ## OpenAI @@ -59,11 +59,11 @@ To implement GitHub OAuth, we must visit the **Auth** page on the Appwrite proje ## Appwrite Database -We must create a database with the ID `crystalball` and two collections with the IDs `githubData` and `destiny` in the Appwrite project with the following details: +We must create a database with the ID `crystalball` and two tables with the IDs `githubData` and `destiny` in the Appwrite project with the following details: -#### The `githubData` collection +#### The `githubData` table -Create the collection and add the following attributes: +Create the table and add the following attributes: | Key | Type | Size | Required | Array | | --- | --- | --- | --- | --- | @@ -72,22 +72,22 @@ Create the collection and add the following attributes: | following | Integer | - | Yes | - | | username | String | 255 | Yes | - | -Visit the collection settings, enable **Document security,** and set the following (collection-level) **Permissions**: +Visit the table settings, enable **Document security,** and set the following (table-level) **Permissions**: | Role | Create | Read | Update | Delete | | --- | --- | --- | --- | --- | | Users | Yes | - | - | - | -#### The `destiny` collection +#### The `destiny` table -Create the collection and add the following attributes: +Create the table and add the following attributes: | Key | Type | Size | Required | | --- | --- | --- | --- | | destiny | String | 25000 | Yes | | username | String | 255 | Yes | -Visit the collection settings, enable **Document security,** and set the following (collection-level) **Permissions**: +Visit the table settings, enable **Document security,** and set the following (table-level) **Permissions**: | Role | Create | Read | Update | Delete | | --- | --- | --- | --- | --- | @@ -123,8 +123,8 @@ Lastly, we must create a `.env` file at the root of the directory and add the fo PUBLIC_APPWRITE_ENDPOINT= PUBLIC_APPWRITE_PROJECT_ID= PUBLIC_APPWRITE_DATABASE_ID= -PUBLIC_APPWRITE_COLLECTION_ID_GITHUBDATA= -PUBLIC_APPWRITE_COLLECTION_ID_DESTINY= +PUBLIC_APPWRITE_TABLE_ID_GITHUBDATA= +PUBLIC_APPWRITE_TABLE_ID_DESTINY= SECRET_OPENAI_API_KEY= ``` @@ -269,14 +269,14 @@ import { databases } from './appwrite'; import { env } from '$env/dynamic/public'; const databaseId = env.PUBLIC_APPWRITE_DATABASE_ID; -const githubDataCollectionId = env.PUBLIC_APPWRITE_COLLECTION_ID_GITHUBDATA; +const githubDataTableId = env.PUBLIC_APPWRITE_TABLE_ID_GITHUBDATA; export const db = { getUserData: async(documentId) => { try{ return await databases.getDocument( databaseId, - githubDataCollectionId, + githubDataTableId, documentId ); } catch(err){ @@ -287,7 +287,7 @@ export const db = { addUserData: async(userId, username, followers, following, languages) => { return await databases.createDocument( databaseId, - githubDataCollectionId, + githubDataTableId, userId, { username, @@ -497,7 +497,7 @@ Lastly, to share our destiny with the rest of the world, we must create an addit . . . -const destinyCollectionId = env.PUBLIC_APPWRITE_COLLECTION_ID_DESTINY; +const destinyTableId = env.PUBLIC_APPWRITE_TABLE_ID_DESTINY; export const db = {** . @@ -506,7 +506,7 @@ export const db = {** addDestiny: async(username, destiny) => { return await databases.createDocument( databaseId, - destinyCollectionId, + destinyTableId, ID.unique(), { username, @@ -519,7 +519,7 @@ export const db = {** try{ return await databases.getDocument( databaseId, - destinyCollectionId, + destinyTableId, documentId ); } catch(err){ diff --git a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc index 1e390ea762..eb3583c6ae 100644 --- a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc +++ b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post title: "Announcing Auto-increment support: Built-in numeric sequencing for your documents" -description: Get reliable, sequential ordering across your collections with fast, indexed auto-increment IDs. +description: Get reliable, sequential ordering across your tables with fast, indexed auto-increment IDs. date: 2025-07-15 cover: /images/blog/announcing-auto-increment-support/cover.png timeToRead: 5 @@ -10,7 +10,7 @@ category: announcement featured: false --- -Managing ordered data can often be complex and error-prone, especially when it requires manual counters or timestamp-based sorting, which can introduce inconsistencies and unpredictability. +Managing ordered data can often be complex and error-prone, especially when it requires manual counters or timestamp-based sorting, which can introduce inconsistencies and unpredictability. To tackle this issue, we're introducing **Auto-increment support.** @@ -50,7 +50,7 @@ const databases = new Databases(client); databases.listDocuments( '', - '', + '', [ Query.orderAsc('$sequence'), ] diff --git a/src/routes/blog/post/announcing-bulk-api/+page.markdoc b/src/routes/blog/post/announcing-bulk-api/+page.markdoc index 25f6f9800a..502f2bfccc 100644 --- a/src/routes/blog/post/announcing-bulk-api/+page.markdoc +++ b/src/routes/blog/post/announcing-bulk-api/+page.markdoc @@ -56,7 +56,7 @@ const databases = new sdk.Databases(client); const result = await databases.createDocuments( '', - '', + '', [ { $id: sdk.ID.unique(), diff --git a/src/routes/blog/post/announcing-csv-imports/+page.markdoc b/src/routes/blog/post/announcing-csv-imports/+page.markdoc index c6651e2b09..3bf927713c 100644 --- a/src/routes/blog/post/announcing-csv-imports/+page.markdoc +++ b/src/routes/blog/post/announcing-csv-imports/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post title: "Announcing CSV Import: Bring in large datasets to Appwrite with ease" -description: Learn how to import documents into your Appwrite collections using a simple CSV file, a new feature built on top of Appwrite's migration APIs. +description: Learn how to import documents into your Appwrite tables using a simple CSV file, a new feature built on top of Appwrite's migration APIs. date: 2025-07-01 # update this cover later, once available! cover: /images/blog/announcing-csv-imports/cover.png @@ -13,26 +13,26 @@ featured: false We're introducing a new way to populate your Appwrite databases: **document imports from CSV files**. -Built on top of Appwrite's migration APIs, this feature makes it easy to bring in large datasets, seed collections, or migrate structured data using only a CSV file. +Built on top of Appwrite's migration APIs, this feature makes it easy to bring in large datasets, seed tables, or migrate structured data using only a CSV file. The CSV document import is useful for migrating user data from external systems, importing inventory records, seeding test environments, or onboarding structured content such as FAQs. # How it works -To get started, create a collection and define its attributes in the Appwrite Console. Your CSV file should follow a standard format: +To get started, create a table and define its attributes in the Appwrite Console. Your CSV file should follow a standard format: -- The first row must be a header containing attribute names that match your collection +- The first row must be a header containing attribute names that match your table - Each subsequent row represents a document, with values separated by commas {% info title="Good to know" %} You can optionally include the `$id` column to assign custom document IDs. {% /info %} -![Collections screen](/images/blog/announcing-csv-imports/csv-import.png) +![Tables screen](/images/blog/announcing-csv-imports/csv-import.png) All required attributes must be present in the CSV, and Appwrite will validate each row before importing it. -For example, if your collection contains attributes like `title`, `author`, `year`, and `available`, a valid CSV file would look like this: +For example, if your table contains attributes like `title`, `author`, `year`, and `available`, a valid CSV file would look like this: ```text $id,title,author,year,available @@ -47,7 +47,7 @@ v42cj0quxp,Pride and Prejudice,Jane Austen,1813,true ## Uploading your CSV file You can upload a new file during import or select an existing one from your project's storage bucket. -The Console provides a guided interface to help you select the CSV and link it to your target collection. Once uploaded, the import process begins immediately. +The Console provides a guided interface to help you select the CSV and link it to your target table. Once uploaded, the import process begins immediately. ## Designed for scale diff --git a/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc b/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc index 2abdf79f04..0cf9c04935 100644 --- a/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc +++ b/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc @@ -49,7 +49,7 @@ Any action that modifies data in your database, including: - Updating documents with `updateDocument`. - Deleting documents with `deleteDocument`. -Most operations are counted based on the number of documents affected. For example, if you fetch a collection of 50 documents with a single API call, this counts as 50 read operations, not as a single operation. However, if your query returns no documents, it will count as a single operation. +Most operations are counted based on the number of documents affected. For example, if you fetch a table of 50 documents with a single API call, this counts as 50 read operations, not as a single operation. However, if your query returns no documents, it will count as a single operation. # Your usage diff --git a/src/routes/blog/post/announcing-database-upsert/+page.markdoc b/src/routes/blog/post/announcing-database-upsert/+page.markdoc index c40714ea7e..57dbecc204 100644 --- a/src/routes/blog/post/announcing-database-upsert/+page.markdoc +++ b/src/routes/blog/post/announcing-database-upsert/+page.markdoc @@ -46,7 +46,7 @@ const databases = new Databases(client); const result = await databases.upsertDocument( '', - '', + '', '', { 'status': 'succeeded', diff --git a/src/routes/blog/post/announcing-roles-for-enhanced-collaboration-and-security/+page.markdoc b/src/routes/blog/post/announcing-roles-for-enhanced-collaboration-and-security/+page.markdoc index 3dd42ff76a..98534cce4e 100644 --- a/src/routes/blog/post/announcing-roles-for-enhanced-collaboration-and-security/+page.markdoc +++ b/src/routes/blog/post/announcing-roles-for-enhanced-collaboration-and-security/+page.markdoc @@ -10,11 +10,11 @@ category: product, announcement featured: false --- -We’re excited to announce a new feature available in the Pro and Scale plans: **Roles**. This enhancement is designed to bring granular permissions to the Appwrite Console, improving both team collaboration and security across your projects. +We’re excited to announce a new feature available in the Pro and Scale plans: **Roles**. This enhancement is designed to bring granular permissions to the Appwrite Console, improving both team collaboration and security across your projects. # The benefit of multiple roles -Previously, you could only invite team members to your organization with one role that gave equal access to all members, regardless of their function. Needless to say, this is not an ideal situation, especially as your team expands, bringing more complexities in managing permissions. With Roles, you can now assign specific permissions to each member of your team, ensuring everyone has the right level of access to their responsibilities. This update provides more control over who can access, modify, and manage different parts of your organization’s projects, making it a key addition to growing teams and larger projects. Managing access to your Appwrite Console has never been easier. +Previously, you could only invite team members to your organization with one role that gave equal access to all members, regardless of their function. Needless to say, this is not an ideal situation, especially as your team expands, bringing more complexities in managing permissions. With Roles, you can now assign specific permissions to each member of your team, ensuring everyone has the right level of access to their responsibilities. This update provides more control over who can access, modify, and manage different parts of your organization’s projects, making it a key addition to growing teams and larger projects. Managing access to your Appwrite Console has never been easier. # Overview of the new Roles in Appwrite @@ -24,17 +24,17 @@ Before this feature update, you only had one role: But now, alongside the existing owner role, we’ve added four new roles that you can assign to your team members: - **Developer**: Developers have access to all development resources but cannot manage the team or billing settings, making this ideal for members focusing solely on coding and technical tasks. -- **Editor**: Editors can modify most resources but cannot alter key backend elements such as collections, buckets, and topics. This is perfect for team members who handle content updates or file uploads without needing to adjust infrastructure. +- **Editor**: Editors can modify most resources but cannot alter key backend elements such as tables, buckets, and topics. This is perfect for team members who handle content updates or file uploads without needing to adjust infrastructure. - **Analyst**: Analysts have read-only access to all resources, ideal for team members who need to view data, analytics, or reports without making changes. - **Billing**: This role is strictly for billing-related actions, with access limited to billing details only, keeping financial data secure without touching other areas of your projects. # Invite more members for free -The new feature is now available on both the Pro and Scale plans. To celebrate the new feature, until the end of the year, you can invite members with the new roles to your Pro teams for free! This is the perfect opportunity to explore the new feature and see how it enhances your team's workflow. -Starting in the new year, member seats will be priced at $15 per month as part of our standard pricing. +The new feature is now available on both the Pro and Scale plans. To celebrate the new feature, until the end of the year, you can invite members with the new roles to your Pro teams for free! This is the perfect opportunity to explore the new feature and see how it enhances your team's workflow. +Starting in the new year, member seats will be priced at $15 per month as part of our standard pricing. # How to add new members with roles -To add new members with a specific Role to your organization, go to your organization overview and click `Invite` on the right. +To add new members with a specific Role to your organization, go to your organization overview and click `Invite` on the right. ![Console invite](/images/blog/new-roles/console2.png) diff --git a/src/routes/blog/post/announcing-type-generation-feature/+page.markdoc b/src/routes/blog/post/announcing-type-generation-feature/+page.markdoc index 88f52bc15e..b92eb7749f 100644 --- a/src/routes/blog/post/announcing-type-generation-feature/+page.markdoc +++ b/src/routes/blog/post/announcing-type-generation-feature/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post title: "Introducing Type generation: Automate your type definitions with Appwrite" -description: "Automatically generate types from your collections with support for multiple languages." +description: "Automatically generate types from your tables with support for multiple languages." date: 2025-06-24 cover: /images/blog/type-generation-feature/cover.png timeToRead: 4 @@ -9,7 +9,7 @@ author: chirag-aggarwal category: announcement --- -We're excited to announce Appwrite’s newest CLI feature, **Type generation**. Designed specifically to enhance your developer experience. Type generation automates the creation of type definitions directly from your database collections, seamlessly integrating with your preferred programming language. +We're excited to announce Appwrite’s newest CLI feature, **Type generation**. Designed specifically to enhance your developer experience. Type generation automates the creation of type definitions directly from your database tables, seamlessly integrating with your preferred programming language. # Say goodbye to manual mapping @@ -21,12 +21,12 @@ Whether you work with PHP, Swift, Dart, TypeScript, JavaScript, Java, or Kotlin, # Simplified workflow, immediate benefits -Using Type generation is straightforward. +Using Type generation is straightforward. -First, ensure you have the [Appwrite CLI](/docs/tooling/command-line/installation#getting-started) installed and your project is [initialised](/docs/tooling/command-line/installation#initialization). Then, run the following command in your terminal to pull collections from your Appwrite project: +First, ensure you have the [Appwrite CLI](/docs/tooling/command-line/installation#getting-started) installed and your project is [initialised](/docs/tooling/command-line/installation#initialization). Then, run the following command in your terminal to pull tables from your Appwrite project: ```bash -appwrite pull collections +appwrite pull tables ``` To generate types, you can use the Appwrite CLI command: diff --git a/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc b/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc index 192a138472..437ce25f03 100644 --- a/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc +++ b/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc @@ -203,7 +203,7 @@ The contains operator is a great addition to the existing text search operators ```js db.listDocuments( '', - '', + '', [ Query.contains('content', ['happy', 'love']), ] @@ -215,7 +215,7 @@ To use the OR operator pass Query.or([...]) to the queries array and provide at ```js db.listDocuments( '', - '', + '', [ Query.or([ Query.contains('name','ivy'), diff --git a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc index d13c304418..c21c1ae499 100644 --- a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc +++ b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post title: "Get started with Appwrite Realtime for Flutter" -description: Learn how to build a Flutter app using Appwrite's powerful Realtime API. +description: Learn how to build a Flutter app using Appwrite's powerful Realtime API. cover: /images/blog/appwrite-realtime-with-flutter/cover.png timeToRead: 6 date: 2024-09-02 @@ -26,13 +26,13 @@ On the databases page, click on the **Create database** button. In the dialog that pops up, enter a name and database ID, and click **Create to create the database and show the database page**. Make sure to note down the database ID next to the database name as we will need that later in our code. -Once on the database page, click on the **Create collection** button. +Once on the database page, click on the **Create table** button. -![Create collection](/images/blog/appwrite-realtime-with-flutter/2.png) +![Create table](/images/blog/appwrite-realtime-with-flutter/2.png) -In the dialog that pops up, set the collection name to **Items** and click on the **Create** button to create the collection, and you will be redirected to the new collection's page. +In the dialog that pops up, set the table name to **Items** and click on the **Create** button to create the table, and you will be redirected to the new table's page. -Switch to the Attributes tab and create the following attribute. Also note down the **Collection ID** from the top of the page next to the collection name. +Switch to the Attributes tab and create the following attribute. Also note down the **Table ID** from the top of the page next to the table name. - Type: String - Attribute Key: name @@ -42,8 +42,8 @@ Switch to the Attributes tab and create the following attribute. Also note down - Array: false ![Create String](/images/blog/appwrite-realtime-with-flutter/3.png) - -Switch to the Settings tab and scroll down to **Permissions** to configure the permissions for the collection. Add the **Any** role and check create, read, update, and delete so that anyone can read and write. + +Switch to the Settings tab and scroll down to **Permissions** to configure the permissions for the table. Add the **Any** role and check create, read, update, and delete so that anyone can read and write. ![Set permissions](/images/blog/appwrite-realtime-with-flutter/4.png) @@ -83,7 +83,7 @@ By registering a new platform, you are allowing your app to communicate with the # Home page -We will start by creating a simple stateful widget that will list all the items from our items collection and allow adding new items and deleting existing items. Our home page will also connect to Appwrite's Realtime service and display changes in the collection of items by updating the UI as they happen. So, let's create our **HomePage** widget. Modify the code in **lib/main.dart** as follows: +We will start by creating a simple stateful widget that will list all the items from our items table and allow adding new items and deleting existing items. Our home page will also connect to Appwrite's Realtime service and display changes in the table of items by updating the UI as they happen. So, let's create our **HomePage** widget. Modify the code in **lib/main.dart** as follows: ```dart import 'package:flutter/material.dart'; @@ -171,7 +171,7 @@ class _HomePageState extends State { ``` -In the **initState** function of the HomePage, we will create and initialize our Appwrite client, as well as subscribe to real-time changes in documents in our **items** collection. +In the **initState** function of the HomePage, we will create and initialize our Appwrite client, as well as subscribe to real-time changes in documents in our **items** table. ```dart RealtimeSubscription? subscription; @@ -193,13 +193,13 @@ dispose(){ } ``` -Now, let us set up different variables and functions to load the initial data, listen to changes in the collection documents, and update the UI to reflect the changes in real time. +Now, let us set up different variables and functions to load the initial data, listen to changes in the table documents, and update the UI to reflect the changes in real time. -First, initialize our database ID and items collection ID and set up a function to load initial data when the application first starts. For that, we will also set up an Appwrite database service. +First, initialize our database ID and items table ID and set up a function to load initial data when the application first starts. For that, we will also set up an Appwrite database service. ```dart final database = 'default'; // your database id - final itemsCollection = 'items'; // your collection id + final itemsTable = 'items'; // your table id late final Databases databases; @override @@ -215,7 +215,7 @@ First, initialize our database ID and items collection ID and set up a function try { final res = await databases.listDocuments( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, ); setState(() { items = @@ -227,14 +227,14 @@ First, initialize our database ID and items collection ID and set up a function } ``` -Now, we will set up our subscribe function, which will listen to changes to documents in our items collection. +Now, we will set up our subscribe function, which will listen to changes to documents in our items table. ```dart void subscribe() { final realtime = Realtime(client); subscription = realtime.subscribe([ - 'documents' // subscribe to all documents in every database and collection + 'documents' // subscribe to all documents in every database and table ]); // listen to changes @@ -263,7 +263,7 @@ Finally, let's modify our `_addItem` function to add items to Appwrite's databas try { await databases.createDocument( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, documentId: ID.unique(), data: {'name': name}, ); @@ -283,7 +283,7 @@ Let us also modify our `ListTile` widget to add a delete button that will allo onPressed: () async { await databases.deleteDocument( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, documentId: item['\$id'], ); }, @@ -329,7 +329,7 @@ class _HomePageState extends State { RealtimeSubscription? subscription; late final Client client; final database = 'default'; // your database id - final itemsCollection = 'items'; // your collection id + final itemsTable = 'items'; // your table id late final Databases databases; @override @@ -345,7 +345,7 @@ class _HomePageState extends State { try { final res = await databases.listDocuments( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, ); setState(() { items = @@ -360,7 +360,7 @@ class _HomePageState extends State { final realtime = Realtime(client); subscription = realtime.subscribe([ - 'documents' // subscribe to all documents in every database and collection + 'documents' // subscribe to all documents in every database and table ]); // listen to changes @@ -401,7 +401,7 @@ class _HomePageState extends State { onPressed: () async { await databases.deleteDocument( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, documentId: item['\$id'], ); }, @@ -448,7 +448,7 @@ class _HomePageState extends State { try { await databases.createDocument( databaseId: database, - collectionId: itemsCollection, + tableId: itemsTable, documentId: ID.unique(), data: {'name': name}, ); @@ -462,7 +462,7 @@ class _HomePageState extends State { # Conclusion -I hope you enjoyed learning and building Flutter applications with Appwrite Realtime service. +I hope you enjoyed learning and building Flutter applications with Appwrite Realtime service. If you have any questions, feel free to ask on our [Discord server](https://appwrite.io/discord). You can also share your apps built Flutter and Appwrite Realtime on [Built with Appwrite](https://builtwith.appwrite.io/), and we'll feature it on our socials! diff --git a/src/routes/blog/post/best-pagination-technique/+page.markdoc b/src/routes/blog/post/best-pagination-technique/+page.markdoc index 58fe8b283d..47538965bd 100644 --- a/src/routes/blog/post/best-pagination-technique/+page.markdoc +++ b/src/routes/blog/post/best-pagination-technique/+page.markdoc @@ -81,9 +81,9 @@ This is a really rare condition and only occurs if the row's ID that you are abo [Appwrite](https://appwrite.io/) is an open-source backend-as-a-service that abstracts all the complexity involved in building a modern application by providing you with a set of REST APIs for your core backend needs. Appwrite handles user authentication and authorization, databases, file storage, cloud functions, webhooks, messaging, and more. You can extend Appwrite using your favorite backend language if anything is missing. -Appwrite Database lets you store any text-based data that needs to be shared across your users. Appwrite's database allows you to create multiple collections (tables) and store multiple documents (rows) in it. Each collection has attributes (columns) configured to give your dataset a proper schema. You can also configure indexes to make your search queries more performant. When reading your data, you can use powerful queries, filter them, sort them, limit the number of results, and paginate over them. +Appwrite Database lets you store any text-based data that needs to be shared across your users. Appwrite's database allows you to create multiple tables (tables) and store multiple documents (rows) in it. Each table has attributes (columns) configured to give your dataset a proper schema. You can also configure indexes to make your search queries more performant. When reading your data, you can use powerful queries, filter them, sort them, limit the number of results, and paginate over them. -Appwrite's pagination supports both offset and cursor pagination. Let's imagine you have a collection with ID `articles`. You can get documents from this collection with either offset or cursor pagination: +Appwrite's pagination supports both offset and cursor pagination. Let's imagine you have a table with ID `articles`. You can get documents from this table with either offset or cursor pagination: ```jsx // Setup @@ -98,7 +98,7 @@ const databases = new Databases(client); // Offset pagination databases.listDocuments( 'main', // Database ID - 'articles', // Collection ID + 'articles', // Table ID [ Query.limit(10), // Limit, total documents in the response Query.offset(500), // Offset, amount of documents to skip @@ -110,7 +110,7 @@ databases.listDocuments( // Cursor pagination databases.listDocuments( 'main', // Database ID - 'articles', // Collection ID + 'articles', // Table ID [ Query.limit(10), // Limit, total documents in the response Query.cursorAfter('61d6eb2281fce3650c2c', // ID of document I want to paginate after @@ -129,7 +129,7 @@ We’ve frequently mentioned the term "performance" in this article without prov > You can find complete source code in the [GitHub repository.](https://github.com/appwrite) -First, you set up Appwrite, register a user, create a project and create a collection called `posts` with read permission set to `any`. To learn more about this process, visit the [Appwrite docs](https://appwrite.io/docs). You should now have Appwrite ready to go. +First, you set up Appwrite, register a user, create a project and create a table called `posts` with read permission set to `any`. To learn more about this process, visit the [Appwrite docs](https://appwrite.io/docs). You should now have Appwrite ready to go. Use the following script to load data into our MariaDB database and prepare for the benchmark. We could use Appwrite SDK, but talking directly to MariaDB offers more optional write queries for large datasets. @@ -161,7 +161,7 @@ for(let i = 0; i < 100; i++) { index++; } - const query = `INSERT INTO _project_${config.projectId}_collection_posts (_uid, _read, _write) VALUES ${queryValues.join(", ")}`; + const query = `INSERT INTO _project_${config.projectId}_table_posts (_uid, _read, _write) VALUES ${queryValues.join(", ")}`; promises.push(connection.execute(query)); } @@ -198,7 +198,7 @@ export default function () { const offset = Query.offset(__ENV.OFFSET); const limit = 10; - http.get(`${config.endpoint}/databases/main/collections/posts/documents?queries[]=${offset}&queries[]=${limit}`, { + http.get(`${config.endpoint}/databases/main/tables/posts/documents?queries[]=${offset}&queries[]=${limit}`, { headers: { 'content-type': 'application/json', 'X-Appwrite-Project': config.projectId @@ -266,7 +266,7 @@ export default function () { const cursor = Query.cursorAfter(__ENV.CURSOR); const limit = 10; - http.get(`${config.endpoint}/databases/main/collections/posts/documents?queries[]=${offset}&queries[]=${limit}`, { + http.get(`${config.endpoint}/databases/main/tables/posts/documents?queries[]=${offset}&queries[]=${limit}`, { headers: { 'content-type': 'application/json', 'X-Appwrite-Project': config.projectId diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index 71f9a6983d..95b1383700 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -61,7 +61,7 @@ Our application needs to communicate with [Appwrite](https://cloud.appwrite.io/? PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1 PUBLIC_APPWRITE_PROJECT_ID=your-project-id PUBLIC_APPWRITE_DATABASE_ID=expense-db -PUBLIC_APPWRITE_COLLECTION_ID=expenses +PUBLIC_APPWRITE_TABLE_ID=expenses ``` The `PUBLIC_` prefix makes these variables available to our client-side code in Svelte. You'll need to replace `your-project-id` with your actual Appwrite project ID, which we'll create in the next step. @@ -72,9 +72,9 @@ Before we continue with the frontend implementation, we need to configure our Ap 1. Create a new project 2. Open the **Databases** tab from the sidebar and create a database with the ID "expense-db" -3. In your new database, create a collection with the ID "expenses" +3. In your new database, create a table with the ID "expenses" -The expenses collection needs several attributes to store the expense data effectively. Open the **Attributes** tab of your new collection and add the following attributes: +The expenses table needs several attributes to store the expense data effectively. Open the **Attributes** tab of your new table and add the following attributes: ```md - `userId` (String, required) @@ -89,7 +89,7 @@ The expenses collection needs several attributes to store the expense data effec Notice that the `category` attribute is an enumerated type with a set of predefined values. This structured approach helps us organize and filter expenses effectively. We have both a `date` attribute and a `createdAt` attribute because when an expense is created is not necessarily the same as when it occurred. -To ensure that users can only access their own expenses, Open the collection's **Settings** tab and scroll to **Permissions**. Click **Add role**, select **Users** and check **Create** permission. +To ensure that users can only access their own expenses, Open the table's **Settings** tab and scroll to **Permissions**. Click **Add role**, select **Users** and check **Create** permission. Next, enable **Document Security** to allow users to access their documents. We'll ensure this by giving users the **Read** permission when creating documents in our code. @@ -165,7 +165,7 @@ import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT_ID, PUBLIC_APPWRITE_DATABASE_ID, - PUBLIC_APPWRITE_COLLECTION_ID + PUBLIC_APPWRITE_TABLE_ID } from '$env/static/public' const client = new Client() @@ -175,15 +175,15 @@ client.setEndpoint(PUBLIC_APPWRITE_ENDPOINT).setProject(PUBLIC_APPWRITE_PROJECT_ export const account = new Account(client) export const databases = new Databases(client) -// Collection IDs from environment variables -export const EXPENSES_COLLECTION_ID = PUBLIC_APPWRITE_COLLECTION_ID +// Table IDs from environment variables +export const EXPENSES_TABLE_ID = PUBLIC_APPWRITE_TABLE_ID export const DATABASE_ID = PUBLIC_APPWRITE_DATABASE_ID ``` This configuration file initializes our connection to Appwrite. The `Client` class creates a new Appwrite client instance, which we configure with our endpoint and project ID from our environment variables. We then create instances of the `Databases` and `Account` services, which we'll use throughout our application for database operations and user authentication. -Finally, we export the collection IDs from our environment variables so that we can use them in other parts of our application. +Finally, we export the table IDs from our environment variables so that we can use them in other parts of our application. ## Managing authentication state @@ -525,7 +525,7 @@ We'll start with our imports and state management: - + @@ -83,14 +83,14 @@ document.querySelector('button').addEventListener('click', async () => { for (let i = 0; i < 200; i++) { const promise = database.createDocument( 'testDb', // Your database ID - 'testCollection', // Your collection ID + 'testTable', // Your table ID Appwrite.ID.unique(), { number: i + i } ); promises.push(promise); console.log('Request initiated:', i+1); } - + await Promise.all(promises); }); ``` diff --git a/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc b/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc index 20b81e8686..d2bd6b3612 100644 --- a/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc +++ b/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc @@ -94,7 +94,7 @@ MongoDB database is well-known for its JSON document structure. This approach al While MongoDB shines the most in storing unstructured data, nowadays, it provides all the capabilities developers expect from a relational database. If you don’t like SQL queries, MongoDB is a great choice. -With MongoDB, integration becomes simpler, since you don’t need to define structure of collections or documents. After preparing a client, you can directly start writing and querying data. +With MongoDB, integration becomes simpler, since you don’t need to define structure of tables or documents. After preparing a client, you can directly start writing and querying data. ```jsx import { MongoClient, ServerApiVersion } from 'mongodb'; @@ -119,7 +119,7 @@ export default async ({ req, res, log, error }) => { const location = `Street ${Math.round(Math.random() * 1000)}, Earth`; // Random address const capacity = 10 + Math.round(Math.random() * 10) * 10; // Random number: 10,20,30,...,90,100 - await client.db("main").collection("warehouses").insertOne({ + await client.db("main").table("warehouses").insertOne({ location, capacity }); @@ -127,7 +127,7 @@ export default async ({ req, res, log, error }) => { // Query data const page = 1; const limit = 100; - const cursor = client.db("main").collection("warehouses") + const cursor = client.db("main").table("warehouses") .find().limit(limit).skip((page - 1) * limit); const docs = []; diff --git a/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc b/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc index 5c42ddcf6e..4351349414 100644 --- a/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc +++ b/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc @@ -9,15 +9,15 @@ author: binyamin-yawitz category: product, announcement featured: false --- -We're excited to announce the new Appwrite CLI. This iteration focuses on local development and an enhanced CI/CD experience. Now, you can test changes to your functions locally, and easily apply changes to your Appwrite collection. +We're excited to announce the new Appwrite CLI. This iteration focuses on local development and an enhanced CI/CD experience. Now, you can test changes to your functions locally, and easily apply changes to your Appwrite table. Let’s dive into the updates to the new Appwrite CLI and how it will improve your building experience. # Understanding past limitations -Appwrite developers use the current generation of Appwrite CLI to initialize functions and collections and deploy those resources. +Appwrite developers use the current generation of Appwrite CLI to initialize functions and tables and deploy those resources. -When deploying collections, the only option is to override and delete all the collection's existing data, which is not the use case for most scenarios. +When deploying tables, the only option is to override and delete all the table's existing data, which is not the use case for most scenarios. The only way to test an Appwrite function is to continue deploying the function changes to the Appwrite instance, which can be aggravating for small changes. @@ -89,7 +89,7 @@ Appwrite CLI is now in listening mode. Try changing your code and seeing how the GitOps is a common way of tracking and migrating database changes. The latest Appwrite CLI generation includes a few features to help you migrate your database changes easily. -When running `appwrite push collection`, the CLI will compare your local `appwrite.json` collection definition against the currently deployed remote collection and will present you with a detailed table awaiting your decision, for example: +When running `appwrite push table`, the CLI will compare your local `appwrite.json` table definition against the currently deployed remote table and will present you with a detailed table awaiting your decision, for example: ``` Key │ Action │ Reason @@ -109,15 +109,15 @@ In this example, we can see that because we've renamed the attribute `times` to To help with the decision, you can notice two warnings: deleting or recreating a field will cause data loss. -It's important to know that the data loss will affect only the recreated/deleted attribute and not the whole collection. +It's important to know that the data loss will affect only the recreated/deleted attribute and not the whole table. -As you can read in the next section, when pushing collections in CI/CD pipelines, you'll need to add the `--force` flag. +As you can read in the next section, when pushing tables in CI/CD pipelines, you'll need to add the `--force` flag. # CI/CD Adapting CI/CD pipelines ensures robust deployments. To support this, we have rewritten many parts of our CLI to fully accommodate non-interactive actions for all deployment-related commands. -You can add the `--force` flag to any command that may ask you questions, such as `appwrite push collections,` to pre-answer all of them with `YES.` Additionally, you can use the `--all` flag to push/pull all services' available resources. +You can add the `--force` flag to any command that may ask you questions, such as `appwrite push tables,` to pre-answer all of them with `YES.` Additionally, you can use the `--all` flag to push/pull all services' available resources. Till this generation, Appwrite CLI supported non-interactive login for API-key-based authorization only, as follows: diff --git a/src/routes/blog/post/introducing-new-database-operators/+page.markdoc b/src/routes/blog/post/introducing-new-database-operators/+page.markdoc index 6250bc2f87..854eea72a8 100644 --- a/src/routes/blog/post/introducing-new-database-operators/+page.markdoc +++ b/src/routes/blog/post/introducing-new-database-operators/+page.markdoc @@ -25,7 +25,7 @@ The contains operator is a great addition to the existing text search operators db.listDocuments( '', - '', + '', [ Query.contains('content', ['happy', 'love']), ] @@ -48,7 +48,7 @@ To use the OR operator pass `Query.or([...])` to the queries array and provide a ```js db.listDocuments( '', - '', + '', [ Query.or([ Query.contains('name','ivy'), diff --git a/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc b/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc index d7834708be..73dfe986e3 100644 --- a/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc +++ b/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc @@ -11,7 +11,7 @@ featured: false --- -Teams and Labels allow us to categorize and group users together, allowing us to set permissions to resources at the Team and label level instead of at the individual user level. Grouping users together makes managing permissions to documents, files and functions much more efficient this way. +Teams and Labels allow us to categorize and group users together, allowing us to set permissions to resources at the Team and label level instead of at the individual user level. Grouping users together makes managing permissions to documents, files and functions much more efficient this way. ![Labels vs Teams](/images/blog/manage-user-permissions-with-labels-and-teams/labels3.png) @@ -26,7 +26,7 @@ So let’s dive into the next section and see how Teams and Labels work and the ## Teams Vs Labels -Teams and labels accomplish much of the same thing, however there are some technical and fundamental differences between the two. While deciding which one to use will be based on your preferences and specific needs, I’ll point out the key differences and try to guide you in the right direction by providing an example of when one may be preferred over the other. +Teams and labels accomplish much of the same thing, however there are some technical and fundamental differences between the two. While deciding which one to use will be based on your preferences and specific needs, I’ll point out the key differences and try to guide you in the right direction by providing an example of when one may be preferred over the other. ### Teams @@ -34,9 +34,9 @@ Teams are designed to group users together, allowing for shared access to resour ![Labels vs Teams](/images/blog/manage-user-permissions-with-labels-and-teams/labels6.png) -One of the key differences between Teams and Labels is that Teams have the ability to set roles within a Team and assign permissions to those roles. This means all users in a Team will inherit permissions from the Team such as read access to all messages in the chat room, but will also inherit permissions from their role as well if they have been assigned one, such as moderator or admin. +One of the key differences between Teams and Labels is that Teams have the ability to set roles within a Team and assign permissions to those roles. This means all users in a Team will inherit permissions from the Team such as read access to all messages in the chat room, but will also inherit permissions from their role as well if they have been assigned one, such as moderator or admin. -This allows for granular control over what each Team member can do based on their role within the Team. +This allows for granular control over what each Team member can do based on their role within the Team. ### Labels @@ -46,8 +46,8 @@ Labels are essentially custom tags that you can assign to a user. They act as cu Just like Teams, we can grant permissions to specific Labels. Labels are attached to individual user accounts and are used to categorize users on a one-to-one basis. Labels can be used in a similar manner to Teams but are a more lightweight and flexible way to manage users and permissions. -This would make Labels a great option for managing which users can view restricted content behind a paywall like a course on Udemy or an e-book on a digital library platform. In this example you would simply attach a label that is unique to a user after they pay to access a product, and from that point on, the label would grant the user permission. If this access was subscription-based and the user stopped paying, we could simply remove the label from the user, and their access would be revoked since they no longer carry the label that gives them access. - +This would make Labels a great option for managing which users can view restricted content behind a paywall like a course on Udemy or an e-book on a digital library platform. In this example you would simply attach a label that is unique to a user after they pay to access a product, and from that point on, the label would grant the user permission. If this access was subscription-based and the user stopped paying, we could simply remove the label from the user, and their access would be revoked since they no longer carry the label that gives them access. + ### Summary - Labels are great for tagging users and assigning permissions based on those tags, while Teams are for grouping users together and allowing role-based management within a Team. @@ -60,7 +60,7 @@ This would make Labels a great option for managing which users can view restrict Here’s the process of granting users permission to resources through Teams and labels. Be sure to pay attention to step 3 in the process. There’s a slight difference in how users connect to Teams Vs. labels. -1. Create a Team or Label +1. Create a Team or Label 2. Assign permissions to that Team or Label 3. **Team**: Add users to the Team / **Label**: Add a Label to the user 4. Users now inherit permissions from the Team they are on or the Labels they have been given. @@ -69,17 +69,17 @@ Did you catch the difference between Labels and Teams in step #3? With Teams, we ## Managing Teams & Labels from the Console -When getting started with Teams and Labels, it could be helpful to set things up from the console manually so you can better visualize how things work. +When getting started with Teams and Labels, it could be helpful to set things up from the console manually so you can better visualize how things work. ## Teams -Let's start with creating a new Team, adding members, and assigning roles to those members of the Team. +Let's start with creating a new Team, adding members, and assigning roles to those members of the Team. 1 - To create a Team, you can go to the “Auth” tab from your console and select “Teams”. From here, you can click on “Create Team” and complete the process of creating by giving your new Team a name -2 - Once your Team is created, you can add a Member to the Team by selecting the “Members” tab and clicking “Create Membership”. Here you will enter the user's email address (name can be left blank) and assign a role to the member. Roles are optional, so you can leave this part blank. +2 - Once your Team is created, you can add a Member to the Team by selecting the “Members” tab and clicking “Create Membership”. Here you will enter the user's email address (name can be left blank) and assign a role to the member. Roles are optional, so you can leave this part blank. -That’s it for creating a Team and adding members from the appwrite console. Now you can assign document, storage, and function permissions to your Teams. As an example, for collection level permissions, you can go to the “settings'' tab in a collection, and in the “permissions” section, choose “Select Teams'' to give permissions to an entire Team or “Custom permissions” if you want to assign permission to only users with a particular role within the Team. +That’s it for creating a Team and adding members from the appwrite console. Now you can assign document, storage, and function permissions to your Teams. As an example, for table level permissions, you can go to the “settings'' tab in a table, and in the “permissions” section, choose “Select Teams'' to give permissions to an entire Team or “Custom permissions” if you want to assign permission to only users with a particular role within the Team. ## Labels diff --git a/src/routes/blog/post/offline-first-journal/+page.markdoc b/src/routes/blog/post/offline-first-journal/+page.markdoc index 4b237aabd0..350304e945 100644 --- a/src/routes/blog/post/offline-first-journal/+page.markdoc +++ b/src/routes/blog/post/offline-first-journal/+page.markdoc @@ -42,7 +42,7 @@ Our tech stack for this app will be: ## Configure your Appwrite project -First, [create an Appwrite Cloud account](https://cloud.appwrite.io/) if you haven’t already. Once your project is ready, go to the **Settings** page and copy your project ID and API endpoint for further usage. Next, go to the **Databases** page from the left sidebar, create a new database with the ID `journals`, and then a collection with the ID `entries` (save both IDs for further usage). +First, [create an Appwrite Cloud account](https://cloud.appwrite.io/) if you haven’t already. Once your project is ready, go to the **Settings** page and copy your project ID and API endpoint for further usage. Next, go to the **Databases** page from the left sidebar, create a new database with the ID `journals`, and then a table with the ID `entries` (save both IDs for further usage). Next, head to the **Attributes** tab and add the following: @@ -56,7 +56,7 @@ Next, head to the **Attributes** tab and add the following: > **Note:** The `deleted` attribute is necessary to add because RxDB does not hard delete any data, only soft deletes to prevent data loss in offline scenarios. -Then, head to the **Settings** tab of your collection, scroll down to the **Permissions** section, and add the following: +Then, head to the **Settings** tab of your table, scroll down to the **Permissions** section, and add the following: | Role | Create | Read | Update | Delete | | --- | --- | --- | --- | --- | @@ -64,7 +64,7 @@ Then, head to the **Settings** tab of your collection, scroll down to the **Perm ## Prepare the app logic -Once our Appwrite project is set up, let’s start building our app. +Once our Appwrite project is set up, let’s start building our app. ### Create a SvelteKit app @@ -103,7 +103,7 @@ In the root directory of your app, create a `.env` file and add the information PUBLIC_APPWRITE_ENDPOINT=your-appwrite-cloud-endpoint PUBLIC_APPWRITE_PROJECT_ID=your-project-id PUBLIC_APPWRITE_DATABASE_ID=your-database-id -PUBLIC_APPWRITE_COLLECTION_ID=your-collection-id +PUBLIC_APPWRITE_TABLE_ID=your-table-id ``` Next, in the `src/lib` subdirectory, create a file `appwrite.js` and add the following code: @@ -114,14 +114,14 @@ import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT_ID, PUBLIC_APPWRITE_DATABASE_ID, - PUBLIC_APPWRITE_COLLECTION_ID + PUBLIC_APPWRITE_TABLE_ID } from '$env/static/public'; export const appwriteConfig = { endpoint: PUBLIC_APPWRITE_ENDPOINT, projectId: PUBLIC_APPWRITE_PROJECT_ID, databaseId: PUBLIC_APPWRITE_DATABASE_ID, - collectionId: PUBLIC_APPWRITE_COLLECTION_ID + tableId: PUBLIC_APPWRITE_TABLE_ID }; export const client = new Client() @@ -156,7 +156,7 @@ addRxPlugin(RxDBQueryBuilderPlugin); addRxPlugin(RxDBUpdatePlugin); ``` -The RxDB imports include core RxDB functionalities to create databases and collections and to add plugins, the query builder plugin for complex read queries, the update plugin for updating data, the Dexie.js storage plugin to use IndexedDB as the local database, and the Appwrite replication plugin to manage data replication in the external Appwrite database. +The RxDB imports include core RxDB functionalities to create databases and tables and to add plugins, the query builder plugin for complex read queries, the update plugin for updating data, the Dexie.js storage plugin to use IndexedDB as the local database, and the Appwrite replication plugin to manage data replication in the external Appwrite database. ### Create a local database @@ -190,7 +190,7 @@ const journalSchema = { }; ``` -Then, we create the database and collection using the Dexie.js plugin by adding the following code just after the schema: +Then, we create the database and table using the Dexie.js plugin by adding the following code just after the schema: ```js let dbPromise = null; @@ -207,9 +207,9 @@ export const getDB = async () => { const db = await dbPromise; - // Add collections - await db.addCollections({ - entries: { // Name must match the collection ID from Appwrite + // Add tables + await db.addTables({ + entries: { // Name must match the table ID from Appwrite schema: journalSchema } }); @@ -237,9 +237,9 @@ const setupReplication = async (db) => { replicationIdentifier: 'journals-replication', client, databaseId: appwriteConfig.databaseId, - collectionId: appwriteConfig.collectionId, + tableId: appwriteConfig.tableId, deletedField: 'deleted', - collection: db.entries, + table: db.entries, pull: { batchSize: 25 // Can be updated }, @@ -347,7 +347,7 @@ This will pre-load all journal entries before the page renders. Then, open the ` ```html @@ -95,7 +95,7 @@ document.querySelector('button').addEventListener('click', async () => { }); ``` -If you open the HTML page in your browser and click on the `Add documents` button, you will notice numerous errors in the console with the HTTP code `429`, as Appwrite's rate limits allow one client to create 120 requests per minute for this API endpoint. +If you open the HTML page in your browser and click on the `Add rows` button, you will notice numerous errors in the console with the HTTP code `429`, as Appwrite's rate limits allow one client to create 120 requests per minute for this API endpoint. ## Step 3: Create dev key @@ -114,7 +114,7 @@ const client = new Appwrite.Client() ## Step 4: Test the app -Reopen the HTML page in your browser. Clicking the `Add documents` button will allow all 200 requests to execute successfully. +Reopen the HTML page in your browser. Clicking the `Add rows` button will allow all 200 requests to execute successfully. # Next steps diff --git a/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc b/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc index d2bd6b3612..d73ec0f906 100644 --- a/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc +++ b/src/routes/blog/post/integrate-sql-nosql-vector-graph-or-any-database-into-your-appwrite-project/+page.markdoc @@ -94,7 +94,7 @@ MongoDB database is well-known for its JSON document structure. This approach al While MongoDB shines the most in storing unstructured data, nowadays, it provides all the capabilities developers expect from a relational database. If you don’t like SQL queries, MongoDB is a great choice. -With MongoDB, integration becomes simpler, since you don’t need to define structure of tables or documents. After preparing a client, you can directly start writing and querying data. +With MongoDB, integration becomes simpler, since you don’t need to define structure of collections or documents. After preparing a client, you can directly start writing and querying data. ```jsx import { MongoClient, ServerApiVersion } from 'mongodb'; diff --git a/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc b/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc index 73dfe986e3..1d5cb3aa31 100644 --- a/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc +++ b/src/routes/blog/post/manage-user-permissions-with-labels-and-teams/+page.markdoc @@ -11,11 +11,11 @@ featured: false --- -Teams and Labels allow us to categorize and group users together, allowing us to set permissions to resources at the Team and label level instead of at the individual user level. Grouping users together makes managing permissions to documents, files and functions much more efficient this way. +Teams and Labels allow us to categorize and group users together, allowing us to set permissions to resources at the Team and label level instead of at the individual user level. Grouping users together makes managing permissions to rows, files and functions much more efficient this way. ![Labels vs Teams](/images/blog/manage-user-permissions-with-labels-and-teams/labels3.png) -To think of this in real-world terms, imagine for a second we were building the next social media application. Teams can be used to create admins and moderators, and these admins and moderators would have permission to delete and flag posts that don’t meet community guidelines. The owner at the document level would have the ability to update and delete this post, but anyone who is on the moderator Team would also have the ability to delete the post, something that is normally restricted to only the owner of the post. We can also change which users have these permissions at any point by adding and removing users and updating the group-level permissions. +To think of this in real-world terms, imagine for a second we were building the next social media application. Teams can be used to create admins and moderators, and these admins and moderators would have permission to delete and flag posts that don’t meet community guidelines. The owner at the row level would have the ability to update and delete this post, but anyone who is on the moderator Team would also have the ability to delete the post, something that is normally restricted to only the owner of the post. We can also change which users have these permissions at any point by adding and removing users and updating the group-level permissions. Another example we can take a look at would be a streaming service like Amazon Video. How do we give users access to a movie or show they paid for? This is where Teams and Labels make our lives easier. By simply adding Labels to users we could decide which users have access to specific resources like movies or shows in our application. @@ -79,7 +79,7 @@ Let's start with creating a new Team, adding members, and assigning roles to tho 2 - Once your Team is created, you can add a Member to the Team by selecting the “Members” tab and clicking “Create Membership”. Here you will enter the user's email address (name can be left blank) and assign a role to the member. Roles are optional, so you can leave this part blank. -That’s it for creating a Team and adding members from the appwrite console. Now you can assign document, storage, and function permissions to your Teams. As an example, for table level permissions, you can go to the “settings'' tab in a table, and in the “permissions” section, choose “Select Teams'' to give permissions to an entire Team or “Custom permissions” if you want to assign permission to only users with a particular role within the Team. +That’s it for creating a Team and adding members from the appwrite console. Now you can assign row, storage, and function permissions to your Teams. As an example, for table level permissions, you can go to the “settings'' tab in a table, and in the “permissions” section, choose “Select Teams'' to give permissions to an entire Team or “Custom permissions” if you want to assign permission to only users with a particular role within the Team. ## Labels diff --git a/src/routes/blog/post/messaging-explained/+page.markdoc b/src/routes/blog/post/messaging-explained/+page.markdoc index 7cda0dd445..9eb2daeb0c 100644 --- a/src/routes/blog/post/messaging-explained/+page.markdoc +++ b/src/routes/blog/post/messaging-explained/+page.markdoc @@ -13,7 +13,7 @@ Recently, Appwrite launched its newest product, [Appwrite Messaging](https://app # Unified messaging platform -To give you a quick refresher, Messaging covers three communication channels under one unified API, allowing you to send email, SMS, and push notifications from your Appwrite project. It connects with a variety of third-party providers, such as Vonage, Twilio, Mailgun, and more, to deliver your messages. Our [documentation](https://appwrite.io/docs/products/messaging) provides a full overview of providers. +To give you a quick refresher, Messaging covers three communication channels under one unified API, allowing you to send email, SMS, and push notifications from your Appwrite project. It connects with a variety of third-party providers, such as Vonage, Twilio, Mailgun, and more, to deliver your messages. Our [documentation](https://appwrite.io/docs/products/messaging) provides a full overview of providers. ![Messaging features](/images/blog/messaging-explained/features.gif) @@ -36,7 +36,7 @@ In Appwrite Messaging, you can use topics to deliver messages to groups of users ## Targets -Targets are different ways a user can be reached. For example, a user might have two emails, a phone number, and a phone and tablet installed with your app. This means the user has five different targets where you can deliver messages. +Targets are different ways a user can be reached. For example, a user might have two emails, a phone number, and a phone and tablet installed with your app. This means the user has five different targets where you can deliver messages. You can send a message directly to a set of targets or add them as subscribers to a topic. For example, if you want to send a payment reminder to a user manually, you could choose to send it just to a specific target. If you want to send out your monthly newsletter, you could have a topic many targets can subscribe to and then send the message to the topic instead. @@ -81,16 +81,16 @@ You can also watch the [product tour](https://www.youtube.com/watch?v=QdDgPeuBZ1 # How Messaging works -Now that we have learned about the three core concepts of Appwrite Messaging, let us dive deeper into how the product works. Each time you send or schedule a push notification, email, or SMS text, it's recorded in Appwrite as a **message** is displayed in the **Messages** tab. However, there is a lot more that goes on under the hood. +Now that we have learned about the three core concepts of Appwrite Messaging, let us dive deeper into how the product works. Each time you send or schedule a push notification, email, or SMS text, it's recorded in Appwrite as a **message** is displayed in the **Messages** tab. However, there is a lot more that goes on under the hood. Here's a step-by-step breakdown of how Appwrite Messaging works: 1. Validate input on API request - The process starts when the Appwrite API is called to create a message, which validates the input. -2. Create message document - - A document containing details about the message, including recipients and content, is created on the internal database. -3. Create schedule document - - A schedule document is created on the internal database, specifying when the message should be sent. This document is necessary for the message scheduler. +2. Create message row + - A row containing details about the message, including recipients and content, is created on the internal database. +3. Create schedule row + - A schedule row is created on the internal database, specifying when the message should be sent. This row is necessary for the message scheduler. 4. Queue the message via the message scheduler - Every minute, the scheduler checks the internal database for scheduled messages. - For each scheduled message, it checks if the message should be sent at that time. diff --git a/src/routes/blog/post/open-source-firebase-alternative/+page.markdoc b/src/routes/blog/post/open-source-firebase-alternative/+page.markdoc index faafc8d753..ba28dda26e 100644 --- a/src/routes/blog/post/open-source-firebase-alternative/+page.markdoc +++ b/src/routes/blog/post/open-source-firebase-alternative/+page.markdoc @@ -60,7 +60,7 @@ Both Appwrite and Firebase provide databases that can be used depending on the n ## Storage -Storage allows you to manage files in your project. It can store images, videos, documents, and other project files. Storage is a crucial requirement for every application, and here's what Appwrite and Firebase have to offer: +Storage allows you to manage files in your project. It can store images, videos, rows, and other project files. Storage is a crucial requirement for every application, and here's what Appwrite and Firebase have to offer: *Similarities:* diff --git a/src/routes/blog/post/serverless-functions-best-practices/+page.markdoc b/src/routes/blog/post/serverless-functions-best-practices/+page.markdoc index c45aa89c7e..9089113237 100644 --- a/src/routes/blog/post/serverless-functions-best-practices/+page.markdoc +++ b/src/routes/blog/post/serverless-functions-best-practices/+page.markdoc @@ -131,7 +131,7 @@ Large deployment packages slow down the function initialization process and incr Ensure only authorized users can execute your functions. Appwrite provides built-in authentication and authorization features that you can leverage to secure your functions. This is important for protecting sensitive data and preventing your functions from being misused or easily exploited. -You must ensure that authorization is enforced on your serverless functions and not solely on the client side. Client-side authorization can be bypassed, leading to security vulnerabilities. Appwrite Databases and Storage services can be configured to enforce access control rules. For example, you can restrict read and write access to documents by navigating to your database table settings in the Appwrite Console and setting the appropriate permissions. It looks like this: +You must ensure that authorization is enforced on your serverless functions and not solely on the client side. Client-side authorization can be bypassed, leading to security vulnerabilities. Appwrite Databases and Storage services can be configured to enforce access control rules. For example, you can restrict read and write access to rows by navigating to your database table settings in the Appwrite Console and setting the appropriate permissions. It looks like this: ![Functions-authorization](/images/blog/serverless-functions/3.png) diff --git a/src/routes/blog/post/simplify-your-data-management-with-relationships/+page.markdoc b/src/routes/blog/post/simplify-your-data-management-with-relationships/+page.markdoc index 575c62b2db..4d11c1fd8a 100644 --- a/src/routes/blog/post/simplify-your-data-management-with-relationships/+page.markdoc +++ b/src/routes/blog/post/simplify-your-data-management-with-relationships/+page.markdoc @@ -156,21 +156,21 @@ Managing related data can still be challenging, especially when deleting data. T ## Restrict -If you select the restrict option, you won't be able to delete a parent document if it has any related child documents. This option is helpful if you want to ensure that data integrity is maintained and that you don't accidentally delete data that is still relevant. +If you select the restrict option, you won't be able to delete a parent row if it has any related child rows. This option is helpful if you want to ensure that data integrity is maintained and that you don't accidentally delete data that is still relevant. ## Cascade -If you choose cascade, deleting a parent document will also delete all related child documents. This option can be helpful if you want to remove all data associated with a particular parent record, such as when you want to delete a user and all their associated data. +If you choose cascade, deleting a parent row will also delete all related child rows. This option can be helpful if you want to remove all data associated with a particular parent record, such as when you want to delete a user and all their associated data. ## Set Null -Finally, the set null option means that deleting a parent document will remove the relationship to the parent document for all of its related children. This can be useful if you want to retain the child's records but simply remove the relationship. +Finally, the set null option means that deleting a parent row will remove the relationship to the parent row for all of its related children. This can be useful if you want to retain the child's records but simply remove the relationship. Each of these options has its own use cases, and the choice ultimately depends on your specific application requirements. By providing these different options, Appwrite allows you to manage related data in a flexible and intuitive way, making it easier for you to build complex applications without worrying about data management. # Other Benefits -In addition to simplifying your table management, database relationships also provide several other benefits. First, they can help to ensure data consistency and integrity by enforcing referential constraints between related tables. This means that you can prevent orphaned documents or other data inconsistencies that might arise if you were to manage the relationships between tables manually. Additionally, using relationships can also improve the performance of your requests and reduce the amount of code you need to write, since you can retrieve related data in a single request rather than having to fetch it separately. +In addition to simplifying your table management, database relationships also provide several other benefits. First, they can help to ensure data consistency and integrity by enforcing referential constraints between related tables. This means that you can prevent orphaned rows or other data inconsistencies that might arise if you were to manage the relationships between tables manually. Additionally, using relationships can also improve the performance of your requests and reduce the amount of code you need to write, since you can retrieve related data in a single request rather than having to fetch it separately. Overall, database relationships are a powerful tool that simplifies your table management and saves you time and effort. By easily linking your tables and retrieving related data, you can focus on developing your application's core features. Check out the [docs](/docs/databases-relationships) for more information. We encourage you to give it a try today and see how it can benefit your development process. diff --git a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc index 4e0a91b90a..b8e8842e65 100644 --- a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc +++ b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc @@ -11,9 +11,9 @@ category: tutorial Some systems need to reflect the order in which actions happen. A ticketing system, for example, should assign "Ticket #41" before "Ticket #42". But in a user interface, it often makes sense to display the latest tickets first, so "Ticket #42" may appear above #41. -Relying on timestamps to get this right is often not enough. Two documents can be created almost simultaneously, and the sort order might vary. What is needed is a consistent, backend-assigned number that increases with each insert and cannot be modified or skipped. +Relying on timestamps to get this right is often not enough. Two rows can be created almost simultaneously, and the sort order might vary. What is needed is a consistent, backend-assigned number that increases with each insert and cannot be modified or skipped. -Appwrite's new `$sequence` column provides exactly this. Every time a document is added to a table, the system assigns it a unique, auto-incrementing integer. This value reflects the insert history of the table and can be used for sorting, display, filtering, and pagination. +Appwrite's new `$sequence` column provides exactly this. Every time a row is added to a table, the system assigns it a unique, auto-incrementing integer. This value reflects the insert history of the table and can be used for sorting, display, filtering, and pagination. In this tutorial, we will build a simple web-based support ticket tracker using plain HTML and JavaScript. Each submitted ticket will be stored in Appwrite with a title and description, and each will receive a `$sequence` number automatically. We will use that number to display and order the tickets. @@ -33,7 +33,7 @@ Inside your project: - Create a new database named "Support DB" - Inside that database, create a new table named "Tickets" -## Add document columns +## Add row columns In the **Tickets** table, define the following columns: @@ -46,7 +46,7 @@ Confirm the schema once all columns are added. ## Set permissions for testing -For now, allow anyone to create and read documents: +For now, allow anyone to create and read rows: - In the table's **Settings**, under **Permissions** - Add `role:any` to **Create** and **Read** @@ -256,7 +256,7 @@ form.addEventListener('submit', async (e) => { ``` -This code creates a new document in your table when the form is submitted. It uses `'unique()'` to generate a unique ID. After submission, the form is reset and the list of tickets is reloaded to show the new entry. +This code creates a new row in your table when the form is submitted. It uses `'unique()'` to generate a unique ID. After submission, the form is reset and the list of tickets is reloaded to show the new entry. {% /section %} @@ -276,16 +276,16 @@ async function loadTickets() { ticketList.innerHTML = '' - if (response.documents.length === 0) { + if (response.rows.length === 0) { emptyState.style.display = 'block' ticketCount.textContent = '0 tickets' } else { emptyState.style.display = 'none' - ticketCount.textContent = `${response.documents.length} ticket${ - response.documents.length === 1 ? '' : 's' + ticketCount.textContent = `${response.rows.length} ticket${ + response.rows.length === 1 ? '' : 's' }` - response.documents.forEach((ticket, index) => { + response.rows.forEach((ticket, index) => { const ticketElement = document.createElement('div') ticketElement.className = 'card u-padding-24' ticketElement.innerHTML = ` @@ -325,8 +325,8 @@ You now have a working support ticket tracker that looks like this: ![Support tracker demo](/images/blog/track-document-order-with-sequence/support-tracker-demo.png) -- Each submitted ticket is stored as a document in Appwrite -- Every document receives a `$sequence` number, guaranteed to be unique and increasing +- Each submitted ticket is stored as a row in Appwrite +- Every row receives a `$sequence` number, guaranteed to be unique and increasing - The interface displays each ticket using that number - The ticket list is reliably sorted by creation order diff --git a/src/routes/blog/post/understand-data-queries/+page.markdoc b/src/routes/blog/post/understand-data-queries/+page.markdoc index ffe3fab41b..23580e90ad 100644 --- a/src/routes/blog/post/understand-data-queries/+page.markdoc +++ b/src/routes/blog/post/understand-data-queries/+page.markdoc @@ -67,7 +67,7 @@ To remove records from a table, you use deletion queries. While powerful, they s A lot of developers today don’t perform raw SQL queries but prefer to use an ORM such as Prima or a managed database provider such as Appwrite. While these tools enable the same end goal, a managed service can provide an easy-to-use wrapper and helper methods that make these queries easier to write and don’t require you to have a deep knowledge of SQL syntax. Appwrite offers the aforementioned data queries as a part of our Database product, which you can discover in our [product documentation](/docs/products/databases). -One of the data retrieval APIs the Appwrite Database offers is a list documents API to get multiple documents from any table. The endpoint also allows you to filter, sort, and paginate results, for which Appwrite provides a common set of syntax to build queries, which you can build manually or using our SDKs. With our latest release, we’re adding support for database operators such as `OR`, `AND`, and `CONTAINS` to allow further flexibility. +One of the data retrieval APIs the Appwrite Database offers is a list rows API to get multiple rows from any table. The endpoint also allows you to filter, sort, and paginate results, for which Appwrite provides a common set of syntax to build queries, which you can build manually or using our SDKs. With our latest release, we’re adding support for database operators such as `OR`, `AND`, and `CONTAINS` to allow further flexibility. - `AND` operation: This operator allows nesting queries in an AND condition. - `OR` operation: This operator allows nesting queries in an OR condition. From a4fae8c8c978bbfceb3e29e84af60bb0baa115ab Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Mon, 21 Jul 2025 21:26:19 +0100 Subject: [PATCH 05/13] Update Document to Row --- .../+page.markdoc | 4 +-- .../blog/post/ai-crystal-ball/+page.markdoc | 12 +++---- .../+page.markdoc | 2 +- .../post/announcing-bulk-api/+page.markdoc | 14 ++++---- .../+page.markdoc | 8 ++--- .../announcing-database-upsert/+page.markdoc | 4 +-- .../post/announcing-go-support/+page.markdoc | 14 ++++---- .../+page.markdoc | 4 +-- .../+page.markdoc | 12 +++---- .../best-pagination-technique/+page.markdoc | 4 +-- .../+page.markdoc | 10 +++--- .../+page.markdoc | 32 +++++++++---------- .../building-init-giveaway-app/+page.markdoc | 4 +-- src/routes/blog/post/cors-error/+page.markdoc | 2 +- .../+page.markdoc | 4 +-- .../+page.markdoc | 16 +++++----- .../post/improve-devex-dev-keys/+page.markdoc | 2 +- .../+page.markdoc | 4 +-- .../+page.markdoc | 6 ++-- .../understand-data-queries/+page.markdoc | 6 ++-- 20 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc index 000d8bcb08..42f60bfe45 100644 --- a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc +++ b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc @@ -294,7 +294,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { }, Context.Res.WithStatusCode(400)) } - _, err = databases.CreateDocument( + _, err = databases.CreateRow( dbId, collId, requestBody.ShortId, @@ -326,7 +326,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { shortId := path[1:] - row, err := databases.GetDocument(dbId, collId, shortId) + row, err := databases.GetRow(dbId, collId, shortId) if err != nil { Context.Error(err) diff --git a/src/routes/blog/post/ai-crystal-ball/+page.markdoc b/src/routes/blog/post/ai-crystal-ball/+page.markdoc index c0e24fe6d9..d7b54f8eff 100644 --- a/src/routes/blog/post/ai-crystal-ball/+page.markdoc +++ b/src/routes/blog/post/ai-crystal-ball/+page.markdoc @@ -72,7 +72,7 @@ Create the table and add the following columns: | following | Integer | - | Yes | - | | username | String | 255 | Yes | - | -Visit the table settings, enable **Document security,** and set the following (table-level) **Permissions**: +Visit the table settings, enable **Row security,** and set the following (table-level) **Permissions**: | Role | Create | Read | Update | Delete | | --- | --- | --- | --- | --- | @@ -87,7 +87,7 @@ Create the table and add the following columns: | destiny | String | 25000 | Yes | | username | String | 255 | Yes | -Visit the table settings, enable **Document security,** and set the following (table-level) **Permissions**: +Visit the table settings, enable **Row security,** and set the following (table-level) **Permissions**: | Role | Create | Read | Update | Delete | | --- | --- | --- | --- | --- | @@ -274,7 +274,7 @@ const githubDataTableId = env.PUBLIC_APPWRITE_TABLE_ID_GITHUBDATA; export const db = { getUserData: async(rowId) => { try{ - return await databases.getDocument( + return await databases.getRow( databaseId, githubDataTableId, rowId @@ -285,7 +285,7 @@ export const db = { }, addUserData: async(userId, username, followers, following, languages) => { - return await databases.createDocument( + return await databases.createRow( databaseId, githubDataTableId, userId, @@ -504,7 +504,7 @@ export const db = {** . . addDestiny: async(username, destiny) => { - return await databases.createDocument( + return await databases.createRow( databaseId, destinyTableId, ID.unique(), @@ -517,7 +517,7 @@ export const db = {** getDestiny: async(rowId) => { try{ - return await databases.getDocument( + return await databases.getRow( databaseId, destinyTableId, rowId diff --git a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc index ae9b6f97bf..cf61c54aab 100644 --- a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc +++ b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc @@ -48,7 +48,7 @@ const client = new Client() const databases = new Databases(client); -databases.listDocuments( +databases.listRows( '', '', [ diff --git a/src/routes/blog/post/announcing-bulk-api/+page.markdoc b/src/routes/blog/post/announcing-bulk-api/+page.markdoc index bec7c93194..e834c7b42b 100644 --- a/src/routes/blog/post/announcing-bulk-api/+page.markdoc +++ b/src/routes/blog/post/announcing-bulk-api/+page.markdoc @@ -36,10 +36,10 @@ Bulk operations can only be performed via the server-side SDKs. The client-side Utilizing the Bulk API is straightforward. You can use it to: -- Create multiple rows in a single request using the `createDocuments` method -- Update multiple rows in a single request using the `updateDocuments` method -- Delete multiple rows in a single request using the `deleteDocuments` method -- Upsert multiple rows in a single request using the `upsertDocuments` method +- Create multiple rows in a single request using the `createRows` method +- Update multiple rows in a single request using the `updateRows` method +- Delete multiple rows in a single request using the `deleteRows` method +- Upsert multiple rows in a single request using the `upsertRows` method Here is a code example for creating multiple rows in a single request: @@ -54,17 +54,17 @@ const client = new sdk.Client() const databases = new sdk.Databases(client); -const result = await databases.createDocuments( +const result = await databases.createRows( '', '', [ { $id: sdk.ID.unique(), - name: 'Document 1', + name: 'Row 1', }, { $id: sdk.ID.unique(), - name: 'Document 2', + name: 'Row 2', } ] ); diff --git a/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc b/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc index 6fa39a6626..d4ab2b896f 100644 --- a/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc +++ b/src/routes/blog/post/announcing-database-reads-and-writes-pricing/+page.markdoc @@ -40,14 +40,14 @@ Database operations in Appwrite are categorized into two types: ## Read operations Any action that retrieves data from your database, including: -- Fetching rows with `getDocument` or `listDocuments`. +- Fetching rows with `getRow` or `listRows`. ## Write operations Any action that modifies data in your database, including: -- Creating rows with `createDocument`. -- Updating rows with `updateDocument`. -- Deleting rows with `deleteDocument`. +- Creating rows with `createRow`. +- Updating rows with `updateRow`. +- Deleting rows with `deleteRow`. Most operations are counted based on the number of rows affected. For example, if you fetch a table of 50 rows with a single API call, this counts as 50 read operations, not as a single operation. However, if your query returns no rows, it will count as a single operation. diff --git a/src/routes/blog/post/announcing-database-upsert/+page.markdoc b/src/routes/blog/post/announcing-database-upsert/+page.markdoc index f1c88d8860..972b585668 100644 --- a/src/routes/blog/post/announcing-database-upsert/+page.markdoc +++ b/src/routes/blog/post/announcing-database-upsert/+page.markdoc @@ -44,7 +44,7 @@ const client = new Client() const databases = new Databases(client); -const result = await databases.upsertDocument( +const result = await databases.upsertRow( '', '', '', @@ -67,4 +67,4 @@ This feature simplifies your database interactions, enhancing efficiency, reduci - [Read the documentation to get started](/docs/products/databases/rows) - [Announcing Bulk API: Handle heavy data workloads with ease](/blog/post/announcing-bulk-api) - [Build a personal CRM with SvelteKit and Appwrite Databases](/blog/post/build-personal-crm-sveltekit) -- [Announcing: Document imports from CSV files](/blog/post/announcing-csv-imports) +- [Announcing: Row imports from CSV files](/blog/post/announcing-csv-imports) diff --git a/src/routes/blog/post/announcing-go-support/+page.markdoc b/src/routes/blog/post/announcing-go-support/+page.markdoc index 9506a8d75b..f7da034792 100644 --- a/src/routes/blog/post/announcing-go-support/+page.markdoc +++ b/src/routes/blog/post/announcing-go-support/+page.markdoc @@ -230,14 +230,14 @@ import ( ) type Profile struct { - *models.Document + *models.Row Name string `json:"name"` Verified bool `json:"verified"` } type ProfileList struct { - *models.DocumentList - Documents []Profile `json:"rows"` + *models.RowList + Rows []Profile `json:"rows"` } func Main(Context openruntimes.Context) openruntimes.Response { @@ -249,7 +249,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { databases := appwrite.NewDatabases(client) - response, err := databases.ListDocuments("main", "profiles") + response, err := databases.ListRows("main", "profiles") if err != nil { Context.Error(err) return Context.Res.Text("Internal error" Context.Res.WithStatusCode(500)) @@ -262,11 +262,11 @@ func Main(Context openruntimes.Context) openruntimes.Response { return Context.Res.Text("Internal error", Context.Res.WithStatusCode(500)) } - for _, profile := range profiles.Documents { + for _, profile := range profiles.Rows { Context.Log(profile.Id, profile.Name, profile.Verified) } - return Context.Res.Json(profiles.Documents) + return Context.Res.Json(profiles.Rows) } ``` @@ -285,4 +285,4 @@ Hopefully, by this point, you’re excited to start building with Go. Here are a Ready to get your hands on the new Go runtime and Go SDK? We’ve created a few resources to help you get your first Go project off the ground and leverage Golang’s speed and performance in your apps. Check them out: - [Join the Appwrite Community on Discord](https://appwrite.io/discord) -- [More about Init](https://file+.vscode-resource.vscode-cdn.net/Users/ebenezerdon/Documents/ed-repos/ed-technical-articles/appwrite/link_to_init) +- [More about Init](https://appwrite.io/init) diff --git a/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc b/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc index 437ce25f03..ae0dbff372 100644 --- a/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc +++ b/src/routes/blog/post/appwrite-1.5-now-available-on-cloud/+page.markdoc @@ -201,7 +201,7 @@ New Database operators `contains` and `or`, providing greater control and flexib The contains operator is a great addition to the existing text search operators such as startsWith & endsWith, and can be used in combination with these two. ```js -db.listDocuments( +db.listRows( '', '', [ @@ -213,7 +213,7 @@ db.listDocuments( To use the OR operator pass Query.or([...]) to the queries array and provide at least two queries within the nested array. ```js -db.listDocuments( +db.listRows( '', '', [ diff --git a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc index 81cd9c88c6..d236f32abe 100644 --- a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc +++ b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc @@ -213,7 +213,7 @@ First, initialize our database ID and items table ID and set up a function to lo loadItems() async { try { - final res = await databases.listDocuments( + final res = await databases.listRows( databaseId: database, tableId: itemsTable, ); @@ -261,7 +261,7 @@ Finally, let's modify our `_addItem` function to add items to Appwrite's databas ```dart void _addItem(String name) async { try { - await databases.createDocument( + await databases.createRow( databaseId: database, tableId: itemsTable, rowId: ID.unique(), @@ -281,7 +281,7 @@ Let us also modify our `ListTile` widget to add a delete button that will allo trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () async { - await databases.deleteDocument( + await databases.deleteRow( databaseId: database, tableId: itemsTable, rowId: item['\$id'], @@ -343,7 +343,7 @@ class _HomePageState extends State { loadItems() async { try { - final res = await databases.listDocuments( + final res = await databases.listRows( databaseId: database, tableId: itemsTable, ); @@ -399,7 +399,7 @@ class _HomePageState extends State { trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () async { - await databases.deleteDocument( + await databases.deleteRow( databaseId: database, tableId: itemsTable, rowId: item['\$id'], @@ -446,7 +446,7 @@ class _HomePageState extends State { void _addItem(String name) async { try { - await databases.createDocument( + await databases.createRow( databaseId: database, tableId: itemsTable, rowId: ID.unique(), diff --git a/src/routes/blog/post/best-pagination-technique/+page.markdoc b/src/routes/blog/post/best-pagination-technique/+page.markdoc index 05fd0d2a9a..56a051221c 100644 --- a/src/routes/blog/post/best-pagination-technique/+page.markdoc +++ b/src/routes/blog/post/best-pagination-technique/+page.markdoc @@ -96,7 +96,7 @@ client const databases = new Databases(client); // Offset pagination -databases.listDocuments( +databases.listRows( 'main', // Database ID 'articles', // Table ID [ @@ -108,7 +108,7 @@ databases.listDocuments( }); // Cursor pagination -databases.listDocuments( +databases.listRows( 'main', // Database ID 'articles', // Table ID [ diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index c2eb3e0665..2c0f082249 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -91,7 +91,7 @@ Notice that the `category` column is an enumerated type with a set of predefined To ensure that users can only access their own expenses, Open the table's **Settings** tab and scroll to **Permissions**. Click **Add role**, select **Users** and check **Create** permission. -Next, enable **Document Security** to allow users to access their rows. We'll ensure this by giving users the **Read** permission when creating rows in our code. +Next, enable **Row Security** to allow users to access their rows. We'll ensure this by giving users the **Read** permission when creating rows in our code. ![permissions-row-security](/images/blog/build-fullstack-svelte-appwrite/permissions-row-security.png) @@ -588,7 +588,7 @@ onMount(async () => { async function fetchExpenses() { try { loading = true - const response = await databases.listDocuments(DATABASE_ID, EXPENSES_TABLE_ID, [ + const response = await databases.listRows(DATABASE_ID, EXPENSES_TABLE_ID, [ Query.orderDesc('$createdAt') ]) expenses = response.rows @@ -636,12 +636,12 @@ async function handleSubmit() { } if (editingExpense) { - await databases.updateDocument(DATABASE_ID, EXPENSES_TABLE_ID, editingExpense.$id, { + await databases.updateRow(DATABASE_ID, EXPENSES_TABLE_ID, editingExpense.$id, { ...expenseData, updatedAt: now }) } else { - await databases.createDocument( + await databases.createRow( DATABASE_ID, EXPENSES_TABLE_ID, 'unique()', @@ -674,7 +674,7 @@ Finally, let's add utility functions for managing expenses: ```js async function deleteExpense(id) { try { - await databases.deleteDocument(DATABASE_ID, EXPENSES_TABLE_ID, id) + await databases.deleteRow(DATABASE_ID, EXPENSES_TABLE_ID, id) await fetchExpenses() } catch (e) { error = 'Failed to delete expense' diff --git a/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc b/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc index e34cf754f5..9cb83976fb 100644 --- a/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc +++ b/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc @@ -95,7 +95,7 @@ const databaseId = env.APPWRITE_DATABASE_ID; const tableId = env.APPWRITE_TABLE_ID; // Add or update contacts -async function upsertDocuments(contacts) { +async function upsertRows(contacts) { try { const rows = contacts.map((contact) => ({ $id: contact.$id || ID.unique(), @@ -104,7 +104,7 @@ async function upsertDocuments(contacts) { phone: contact.phone, notes: contact.notes })); - return await databases.upsertDocuments(databaseId, tableId, rows); + return await databases.upsertRows(databaseId, tableId, rows); } catch (error) { console.error('Error upserting rows:', error); throw new Error('Failed to upsert rows'); @@ -112,9 +112,9 @@ async function upsertDocuments(contacts) { } // Delete a single contact -async function deleteDocument(id) { +async function deleteRow(id) { try { - return await databases.deleteDocument(databaseId, tableId, id); + return await databases.deleteRow(databaseId, tableId, id); } catch (error) { console.error('Error deleting row:', error); throw new Error('Failed to delete row'); @@ -122,9 +122,9 @@ async function deleteDocument(id) { } // Delete all contacts -async function deleteDocuments() { +async function deleteRows() { try { - return await databases.deleteDocuments(databaseId, tableId, []); + return await databases.deleteRows(databaseId, tableId, []); } catch (error) { console.error('Error deleting rows:', error); throw new Error('Failed to delete rows'); @@ -132,9 +132,9 @@ async function deleteDocuments() { } // List contacts -async function listDocuments() { +async function listRows() { try { - return await databases.listDocuments(databaseId, tableId); + return await databases.listRows(databaseId, tableId); } catch (error) { console.error('Error fetching rows:', error); throw new Error('Failed to fetch rows'); @@ -142,10 +142,10 @@ async function listDocuments() { } export const db = { - upsertDocuments, - deleteDocument, - deleteDocuments, - listDocuments + upsertRows, + deleteRow, + deleteRows, + listRows }; ``` @@ -170,7 +170,7 @@ import { env } from '$env/dynamic/private'; // GET - List all contacts export async function GET() { try { - const response = await db.listDocuments(); + const response = await db.listRows(); return json(response.rows); } catch (error) { console.error('Error fetching contacts:', error); @@ -183,7 +183,7 @@ export async function POST({ request }) { try { const { contacts } = await request.json(); - const response = await db.upsertDocuments(contacts); + const response = await db.upsertRows(contacts); return json(response); } catch (error) { console.error('Error upserting contacts:', error); @@ -199,10 +199,10 @@ export async function DELETE({ request }) { let response; if (id) { // Single contact ID provided - delete a single row - response = await db.deleteDocument(id); + response = await db.deleteRow(id); } else { // No ID provided - delete all rows - response = await db.deleteDocuments(); + response = await db.deleteRows(); } return json(response); } catch (error) { diff --git a/src/routes/blog/post/building-init-giveaway-app/+page.markdoc b/src/routes/blog/post/building-init-giveaway-app/+page.markdoc index aed88a2a48..3f82c479c7 100644 --- a/src/routes/blog/post/building-init-giveaway-app/+page.markdoc +++ b/src/routes/blog/post/building-init-giveaway-app/+page.markdoc @@ -187,7 +187,7 @@ import { TABLE_NAME, DATABASE_NAME } from './constants'; export const db = { list: async () => { - var entries = await database.listDocuments(DATABASE_NAME, TABLE_NAME, [ + var entries = await database.listRows(DATABASE_NAME, TABLE_NAME, [ Query.limit(500), Query.select(['discordName']) ]); @@ -203,7 +203,7 @@ export const db = { add: async (discordName, email) => { try { - await database.createDocument(DATABASE_NAME, TABLE_NAME, ID.unique(), { + await database.createRow(DATABASE_NAME, TABLE_NAME, ID.unique(), { discordName: discordName, email: email }); diff --git a/src/routes/blog/post/cors-error/+page.markdoc b/src/routes/blog/post/cors-error/+page.markdoc index d04c26350e..76d38bc362 100644 --- a/src/routes/blog/post/cors-error/+page.markdoc +++ b/src/routes/blog/post/cors-error/+page.markdoc @@ -61,7 +61,7 @@ So if you find this is why you were getting a CORS error, you have a few ways of ## 3 - Incorrect ID on request -This one happens because of an improperly configured request, such as a typo when specifying a project ID. For example, when using the `listDocuments` method, +This one happens because of an improperly configured request, such as a typo when specifying a project ID. For example, when using the `listRows` method, if the project ID is set incorrectly when the client is initialized, you will receive a CORS error. Without diving into the details about how CORS works, the problem occurs when the browser tries to check if the origin is allowed. diff --git a/src/routes/blog/post/how-to-build-your-digital-event-tickets/+page.markdoc b/src/routes/blog/post/how-to-build-your-digital-event-tickets/+page.markdoc index 96eec375eb..c240eb3fb1 100644 --- a/src/routes/blog/post/how-to-build-your-digital-event-tickets/+page.markdoc +++ b/src/routes/blog/post/how-to-build-your-digital-event-tickets/+page.markdoc @@ -112,7 +112,7 @@ import parse from 'node-html-parser'; import type { TicketData, ContributionsMatrix } from '../../constants'; export async function getContributions(id: string): Promise { - const { gh_user, contributions } = (await appwriteInit.database.getDocument( + const { gh_user, contributions } = (await appwriteInit.database.getRow( APPWRITE_DB_INIT_ID, APPWRITE_COL_INIT_ID, id @@ -132,7 +132,7 @@ export async function getContributions(id: string): Promise', '', [Query.equal('author', 'Michael Scott')], ) ``` -By fetching all the rows you need in one go and applying filters, you reduce the number of requests and improve performance. However, as we'll see in the next section, you should use the `listDocuments` method carefully to avoid fetching unnecessary data, else you might end up with a large dataset that could slow down your application. +By fetching all the rows you need in one go and applying filters, you reduce the number of requests and improve performance. However, as we'll see in the next section, you should use the `listRows` method carefully to avoid fetching unnecessary data, else you might end up with a large dataset that could slow down your application. ## Optimize pagination and filtering @@ -41,7 +41,7 @@ For applications with large datasets (e.g., e-commerce platforms with thousands For example, if you're loading products from a database, instead of fetching all products, fetch them in batches using pagination. ```javascript -const firstPage = await databases.listDocuments( +const firstPage = await databases.listRows( '', '', [ @@ -51,7 +51,7 @@ const firstPage = await databases.listDocuments( ], ) -const secondPage = await databases.listDocuments( +const secondPage = await databases.listRows( '', '', [ @@ -82,7 +82,7 @@ const unsubscribe = client.subscribe('files', (response) => { In addition to handling real-time updates, Appwrite's Realtime API can help decide when further requests are needed. Instead of continuously fetching data to check for updates, you can create a versioning system. -1. **Versioning Document**: Create a row with a single column, `version`, to track updates. +1. **Versioning Row**: Create a row with a single column, `version`, to track updates. 2. **Subscribe to Changes**: Use the Realtime API to monitor changes in this row. If the `version` field updates, it signals that the data has changed and needs re-fetching. Appwrite's Realtime API supports multiple channels, such as `files`, `account`, and specific `tables`, ensuring updates from any part of your app. To learn more about the Realtime API, refer to the [Appwrite Realtime documentation](https://appwrite.io/docs/realtime). diff --git a/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc b/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc index 0abad120df..67144cd854 100644 --- a/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc +++ b/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc @@ -81,7 +81,7 @@ const database = new Appwrite.Databases(client); document.querySelector('button').addEventListener('click', async () => { const promises = []; for (let i = 0; i < 200; i++) { - const promise = database.createDocument( + const promise = database.createRow( 'testDb', // Your database ID 'testTable', // Your table ID Appwrite.ID.unique(), diff --git a/src/routes/blog/post/introducing-new-database-operators/+page.markdoc b/src/routes/blog/post/introducing-new-database-operators/+page.markdoc index f4e714a630..04ead7c352 100644 --- a/src/routes/blog/post/introducing-new-database-operators/+page.markdoc +++ b/src/routes/blog/post/introducing-new-database-operators/+page.markdoc @@ -23,7 +23,7 @@ The contains operator is a great addition to the existing text search operators ```js -db.listDocuments( +db.listRows( '', '', [ @@ -46,7 +46,7 @@ The logical OR operator allows us to nest queries in an OR condition. This gives To use the OR operator pass `Query.or([...])` to the queries array and provide at least two queries within the nested array. ```js -db.listDocuments( +db.listRows( '', '', [ diff --git a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc index b8e8842e65..78a74030a8 100644 --- a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc +++ b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc @@ -222,7 +222,7 @@ const tableId = '' Replace the placeholders with your actual values from the Appwrite console. -This code sets up the SDK so that you can call `databases.createDocument()` and `databases.listDocuments()` in the rest of the script. +This code sets up the SDK so that you can call `databases.createRow()` and `databases.listRows()` in the rest of the script. {% /section %} @@ -242,7 +242,7 @@ form.addEventListener('submit', async (e) => { if (!title || !body) return try { - await databases.createDocument(databaseId, tableId, 'unique()', { + await databases.createRow(databaseId, tableId, 'unique()', { title, body, }) @@ -267,7 +267,7 @@ Now add a function that retrieves tickets and shows them in order, newest first: ```javascript async function loadTickets() { try { - const response = await databases.listDocuments(databaseId, tableId, [ + const response = await databases.listRows(databaseId, tableId, [ Appwrite.Query.orderDesc('$sequence'), ]) const ticketList = document.getElementById('ticket-list') diff --git a/src/routes/blog/post/understand-data-queries/+page.markdoc b/src/routes/blog/post/understand-data-queries/+page.markdoc index 23580e90ad..c6d88c186c 100644 --- a/src/routes/blog/post/understand-data-queries/+page.markdoc +++ b/src/routes/blog/post/understand-data-queries/+page.markdoc @@ -83,7 +83,7 @@ const client = new Client() const databases = new Databases(client); // OR operator example -const movieData1 = databases.listDocuments( +const movieData1 = databases.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.or([ @@ -93,7 +93,7 @@ const movieData1 = databases.listDocuments( ); // AND operator example -const movieData2 = databases.listDocuments( +const movieData2 = databases.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.and([ @@ -103,7 +103,7 @@ const movieData2 = databases.listDocuments( ); // CONTAINS operator example -const movieData3 = databases.listDocuments( +const movieData3 = databases.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.contains('director', ["Christopher Nolan"]) From 3d608f7873e9c5663aa6b99f192b311eec14f3f2 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Mon, 21 Jul 2025 21:31:28 +0100 Subject: [PATCH 06/13] update DOCUMENT to ROW --- src/routes/blog/post/announcing-database-upsert/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/blog/post/announcing-database-upsert/+page.markdoc b/src/routes/blog/post/announcing-database-upsert/+page.markdoc index 972b585668..ac43438628 100644 --- a/src/routes/blog/post/announcing-database-upsert/+page.markdoc +++ b/src/routes/blog/post/announcing-database-upsert/+page.markdoc @@ -47,7 +47,7 @@ const databases = new Databases(client); const result = await databases.upsertRow( '', '', - '', + '', { 'status': 'succeeded', 'amount': 4999, From 5be7bd2dd3986ce2584d769a402169debf0b57b8 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Wed, 20 Aug 2025 17:33:28 +0100 Subject: [PATCH 07/13] update Databases to TablesDB --- .../+page.markdoc | 8 +++---- .../blog/post/ai-crystal-ball/+page.markdoc | 14 +++++------ .../+page.markdoc | 14 +++++------ .../+page.markdoc | 6 ++--- .../post/announcing-bulk-api/+page.markdoc | 4 ++-- .../announcing-database-upsert/+page.markdoc | 6 ++--- .../post/announcing-go-support/+page.markdoc | 4 ++-- .../+page.markdoc | 20 ++++++++-------- .../best-pagination-technique/+page.markdoc | 8 +++---- .../+page.markdoc | 12 +++++----- .../+page.markdoc | 12 +++++----- .../building-init-giveaway-app/+page.markdoc | 10 ++++---- .../+page.markdoc | 6 ++--- .../post/improve-devex-dev-keys/+page.markdoc | 4 ++-- .../+page.markdoc | 4 ++-- .../+page.markdoc | 8 +++---- .../understand-data-queries/+page.markdoc | 10 ++++---- .../blog/post/what-is-golang/+page.markdoc | 24 +++++++++---------- 18 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc index 42f60bfe45..e769f23a3e 100644 --- a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc +++ b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc @@ -276,12 +276,12 @@ func Main(Context openruntimes.Context) openruntimes.Response { appwrite.WithKey(Context.Req.Headers["x-appwrite-key"]), ) - databases := appwrite.NewDatabases(client) + tablesDB := appwrite.NewTablesDB(client) dbId := "urlDatabase" collId := "urlTable" - services.InitialiseDatabase(Context, *databases, dbId, collId) + services.InitialiseDatabase(Context, *tablesDB, dbId, collId) if Context.Req.Method == "POST" { var requestBody RequestBody @@ -294,7 +294,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { }, Context.Res.WithStatusCode(400)) } - _, err = databases.CreateRow( + _, err = tablesDB.CreateRow( dbId, collId, requestBody.ShortId, @@ -326,7 +326,7 @@ func Main(Context openruntimes.Context) openruntimes.Response { shortId := path[1:] - row, err := databases.GetRow(dbId, collId, shortId) + row, err := tablesDB.GetRow(dbId, collId, shortId) if err != nil { Context.Error(err) diff --git a/src/routes/blog/post/ai-crystal-ball/+page.markdoc b/src/routes/blog/post/ai-crystal-ball/+page.markdoc index d7b54f8eff..af60c13e32 100644 --- a/src/routes/blog/post/ai-crystal-ball/+page.markdoc +++ b/src/routes/blog/post/ai-crystal-ball/+page.markdoc @@ -131,7 +131,7 @@ SECRET_OPENAI_API_KEY= After the environment variables are created, we can set up the Appwrite SDK by creating a file `./src/lib/appwrite.js` and adding the following: ```js -import { Client, Account, Databases } from 'appwrite'; +import { Client, Account, TablesDB } from 'appwrite'; import { env } from '$env/dynamic/public'; const client = new Client() @@ -139,7 +139,7 @@ const client = new Client() .setProject(env.PUBLIC_APPWRITE_PROJECT_ID); export const account = new Account(client); -export const databases = new Databases(client); +export const tablesDB = new TablesDB(client); ``` Also, since this app is created without SSR, we will go to the `./src/routes` directory and creates a file `+layout.js` to add the following: @@ -265,7 +265,7 @@ At this point, we also want to create our Database library using the Appwrite SD ```js import { Permission, Role, ID } from 'appwrite'; -import { databases } from './appwrite'; +import { tablesDB } from './appwrite'; import { env } from '$env/dynamic/public'; const databaseId = env.PUBLIC_APPWRITE_DATABASE_ID; @@ -274,7 +274,7 @@ const githubDataTableId = env.PUBLIC_APPWRITE_TABLE_ID_GITHUBDATA; export const db = { getUserData: async(rowId) => { try{ - return await databases.getRow( + return await tablesDB.getRow( databaseId, githubDataTableId, rowId @@ -285,7 +285,7 @@ export const db = { }, addUserData: async(userId, username, followers, following, languages) => { - return await databases.createRow( + return await tablesDB.createRow( databaseId, githubDataTableId, userId, @@ -504,7 +504,7 @@ export const db = {** . . addDestiny: async(username, destiny) => { - return await databases.createRow( + return await tablesDB.createRow( databaseId, destinyTableId, ID.unique(), @@ -517,7 +517,7 @@ export const db = {** getDestiny: async(rowId) => { try{ - return await databases.getRow( + return await tablesDB.getRow( databaseId, destinyTableId, rowId diff --git a/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc b/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc index ed1a0b7d8d..2a941cbb43 100644 --- a/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc +++ b/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc @@ -10,7 +10,7 @@ category: announcement featured: false --- -In high-concurrency systems like social apps, games, and usage-tracked services, even updating a single number such as a like, retry count, or quota, can lead to consistency issues. When multiple clients try to update the same value simultaneously, it’s easy to end up with conflicting writes, lost updates, or inaccurate data. +In high-concurrency systems like social apps, games, and usage-tracked services, even updating a single number such as a like, retry count, or quota, can lead to consistency issues. When multiple clients try to update the same value simultaneously, it’s easy to end up with conflicting writes, lost updates, or inaccurate data. Most setups require you to fetch the document, change the number on the client, and then write it back. This process is slow, error-prone, and wastes bandwidth, especially when you're only trying to change a single field. @@ -45,15 +45,15 @@ Use the `incrementDocumentAttribute` and `decrementDocumentAttribute` methods to ## Increment a field {% #increment-field %} ```client-web -import { Client, Databases } from "appwrite"; +import { Client, TablesDB } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint .setProject(''); // Your project ID -const databases = new Databases(client); +const tablesDB = new TablesDB(client); -const result = await databases.incrementDocumentAttribute( +const result = await tablesDB.incrementDocumentAttribute( '', '', '', @@ -65,15 +65,15 @@ const result = await databases.incrementDocumentAttribute( ## Decrement a field {% #decrement-field %} ```client-web -import { Client, Databases } from "appwrite"; +import { Client, TablesDB } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint .setProject(''); // Your project ID -const databases = new Databases(client); +const tablesDB = new TablesDB(client); -const result = await databases.decrementDocumentAttribute( +const result = await tablesDB.decrementDocumentAttribute( '', '', '', diff --git a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc index cf61c54aab..772fb2cd5b 100644 --- a/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc +++ b/src/routes/blog/post/announcing-auto-increment-support/+page.markdoc @@ -40,15 +40,15 @@ Integrating Auto-increment support into your Appwrite Databases makes your backe For numeric ordering based on insertion order, you can use the `$sequence` field, which Appwrite automatically adds to all rows. This field increments with each new insert. ```client-web -import { Client, Databases, Query } from "appwrite"; +import { Client, TablesDB, Query } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -const databases = new Databases(client); +const tablesDB = new TablesDB(client); -databases.listRows( +tablesDB.listRows( '', '', [ diff --git a/src/routes/blog/post/announcing-bulk-api/+page.markdoc b/src/routes/blog/post/announcing-bulk-api/+page.markdoc index e834c7b42b..f969f8ecdc 100644 --- a/src/routes/blog/post/announcing-bulk-api/+page.markdoc +++ b/src/routes/blog/post/announcing-bulk-api/+page.markdoc @@ -52,9 +52,9 @@ const client = new sdk.Client() .setProject('') .setKey(''); -const databases = new sdk.Databases(client); +const tablesDB = new sdk.TablesDB(client); -const result = await databases.createRows( +const result = await tablesDB.createRows( '', '', [ diff --git a/src/routes/blog/post/announcing-database-upsert/+page.markdoc b/src/routes/blog/post/announcing-database-upsert/+page.markdoc index ac43438628..7743a8877f 100644 --- a/src/routes/blog/post/announcing-database-upsert/+page.markdoc +++ b/src/routes/blog/post/announcing-database-upsert/+page.markdoc @@ -36,15 +36,15 @@ This brings you immediate benefits such as: Implementing Upsert is straightforward and intuitive: ```javascript -import { Client, Databases } from "appwrite"; +import { Client, TablesDB } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -const databases = new Databases(client); +const tablesDB = new TablesDB(client); -const result = await databases.upsertRow( +const result = await tablesDB.upsertRow( '', '', '', diff --git a/src/routes/blog/post/announcing-go-support/+page.markdoc b/src/routes/blog/post/announcing-go-support/+page.markdoc index f7da034792..bfc29fa6b8 100644 --- a/src/routes/blog/post/announcing-go-support/+page.markdoc +++ b/src/routes/blog/post/announcing-go-support/+page.markdoc @@ -247,9 +247,9 @@ func Main(Context openruntimes.Context) openruntimes.Response { appwrite.WithKey(Context.Req.Headers["x-appwrite-key"]), ) - databases := appwrite.NewDatabases(client) + tablesDB := appwrite.NewTablesDB(client) - response, err := databases.ListRows("main", "profiles") + response, err := tablesDB.ListRows("main", "profiles") if err != nil { Context.Error(err) return Context.Res.Text("Internal error" Context.Res.WithStatusCode(500)) diff --git a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc index d236f32abe..1aa06399fe 100644 --- a/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc +++ b/src/routes/blog/post/appwrite-realtime-for-flutter/+page.markdoc @@ -200,20 +200,20 @@ First, initialize our database ID and items table ID and set up a function to lo ```dart final database = 'default'; // your database id final itemsTable = 'items'; // your table id - late final Databases databases; + late final TablesDB tablesDB; @override initState() { super.initState(); client = Client().setProject('delete'); // your project id - databases = Databases(client); + tablesDB = TablesDB(client); loadItems(); subscribe(); } loadItems() async { try { - final res = await databases.listRows( + final res = await tablesDB.listRows( databaseId: database, tableId: itemsTable, ); @@ -261,7 +261,7 @@ Finally, let's modify our `_addItem` function to add items to Appwrite's databas ```dart void _addItem(String name) async { try { - await databases.createRow( + await tablesDB.createRow( databaseId: database, tableId: itemsTable, rowId: ID.unique(), @@ -281,7 +281,7 @@ Let us also modify our `ListTile` widget to add a delete button that will allo trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () async { - await databases.deleteRow( + await tablesDB.deleteRow( databaseId: database, tableId: itemsTable, rowId: item['\$id'], @@ -330,20 +330,20 @@ class _HomePageState extends State { late final Client client; final database = 'default'; // your database id final itemsTable = 'items'; // your table id - late final Databases databases; + late final TablesDB tablesDB; @override initState() { super.initState(); client = Client().setProject('delete'); // your project id - databases = Databases(client); + tablesDB = TablesDB(client); loadItems(); subscribe(); } loadItems() async { try { - final res = await databases.listRows( + final res = await tablesDB.listRows( databaseId: database, tableId: itemsTable, ); @@ -399,7 +399,7 @@ class _HomePageState extends State { trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () async { - await databases.deleteRow( + await tablesDB.deleteRow( databaseId: database, tableId: itemsTable, rowId: item['\$id'], @@ -446,7 +446,7 @@ class _HomePageState extends State { void _addItem(String name) async { try { - await databases.createRow( + await tablesDB.createRow( databaseId: database, tableId: itemsTable, rowId: ID.unique(), diff --git a/src/routes/blog/post/best-pagination-technique/+page.markdoc b/src/routes/blog/post/best-pagination-technique/+page.markdoc index 56a051221c..d3fdaba085 100644 --- a/src/routes/blog/post/best-pagination-technique/+page.markdoc +++ b/src/routes/blog/post/best-pagination-technique/+page.markdoc @@ -87,16 +87,16 @@ Appwrite's pagination supports both offset and cursor pagination. Let's imagine ```jsx // Setup -import { Appwrite, Databases, Query } from "appwrite"; +import { Appwrite, TablesDB, Query } from "appwrite"; const client = new Appwrite(); client .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint .setProject('articles-demo'); // Your project ID -const databases = new Databases(client); +const tablesDB = new TablesDB(client); // Offset pagination -databases.listRows( +tablesDB.listRows( 'main', // Database ID 'articles', // Table ID [ @@ -108,7 +108,7 @@ databases.listRows( }); // Cursor pagination -databases.listRows( +tablesDB.listRows( 'main', // Database ID 'articles', // Table ID [ diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index 2c0f082249..cff73dac65 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -160,7 +160,7 @@ This template provides the basic structure for our application. The `data-svelte Let's set up our connection to Appwrite. If you haven't already, create a new file in the `src/lib` directory named `appwrite.js`. We'll use this file to configure the Appwrite client and provide access to our database and account services. ```js -import { Client, Account, Databases } from 'appwrite' +import { Client, Account, TablesDB } from 'appwrite' import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT_ID, @@ -173,7 +173,7 @@ const client = new Client() client.setEndpoint(PUBLIC_APPWRITE_ENDPOINT).setProject(PUBLIC_APPWRITE_PROJECT_ID) export const account = new Account(client) -export const databases = new Databases(client) +export const tablesDB = new TablesDB(client) // Table IDs from environment variables export const EXPENSES_TABLE_ID = PUBLIC_APPWRITE_TABLE_ID @@ -588,7 +588,7 @@ onMount(async () => { async function fetchExpenses() { try { loading = true - const response = await databases.listRows(DATABASE_ID, EXPENSES_TABLE_ID, [ + const response = await tablesDB.listRows(DATABASE_ID, EXPENSES_TABLE_ID, [ Query.orderDesc('$createdAt') ]) expenses = response.rows @@ -636,12 +636,12 @@ async function handleSubmit() { } if (editingExpense) { - await databases.updateRow(DATABASE_ID, EXPENSES_TABLE_ID, editingExpense.$id, { + await tablesDB.updateRow(DATABASE_ID, EXPENSES_TABLE_ID, editingExpense.$id, { ...expenseData, updatedAt: now }) } else { - await databases.createRow( + await tablesDB.createRow( DATABASE_ID, EXPENSES_TABLE_ID, 'unique()', @@ -674,7 +674,7 @@ Finally, let's add utility functions for managing expenses: ```js async function deleteExpense(id) { try { - await databases.deleteRow(DATABASE_ID, EXPENSES_TABLE_ID, id) + await tablesDB.deleteRow(DATABASE_ID, EXPENSES_TABLE_ID, id) await fetchExpenses() } catch (e) { error = 'Failed to delete expense' diff --git a/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc b/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc index 9cb83976fb..253baacb95 100644 --- a/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc +++ b/src/routes/blog/post/build-personal-crm-sveltekit/+page.markdoc @@ -81,7 +81,7 @@ Next, in the `src/lib` subdirectory, create a file `appwrite.js` and add the fol ```js // src/lib/appwrite.js -import { Client, Databases, ID } from 'node-appwrite'; +import { Client, TablesDB, ID } from 'node-appwrite'; import { env } from '$env/dynamic/private'; const client = new Client() @@ -89,7 +89,7 @@ const client = new Client() .setProject(env.APPWRITE_PROJECT_ID) .setKey(env.APPWRITE_API_KEY); -const databases = new Databases(client); +const tablesDB = new TablesDB(client); const databaseId = env.APPWRITE_DATABASE_ID; const tableId = env.APPWRITE_TABLE_ID; @@ -104,7 +104,7 @@ async function upsertRows(contacts) { phone: contact.phone, notes: contact.notes })); - return await databases.upsertRows(databaseId, tableId, rows); + return await tablesDB.upsertRows(databaseId, tableId, rows); } catch (error) { console.error('Error upserting rows:', error); throw new Error('Failed to upsert rows'); @@ -114,7 +114,7 @@ async function upsertRows(contacts) { // Delete a single contact async function deleteRow(id) { try { - return await databases.deleteRow(databaseId, tableId, id); + return await tablesDB.deleteRow(databaseId, tableId, id); } catch (error) { console.error('Error deleting row:', error); throw new Error('Failed to delete row'); @@ -124,7 +124,7 @@ async function deleteRow(id) { // Delete all contacts async function deleteRows() { try { - return await databases.deleteRows(databaseId, tableId, []); + return await tablesDB.deleteRows(databaseId, tableId, []); } catch (error) { console.error('Error deleting rows:', error); throw new Error('Failed to delete rows'); @@ -134,7 +134,7 @@ async function deleteRows() { // List contacts async function listRows() { try { - return await databases.listRows(databaseId, tableId); + return await tablesDB.listRows(databaseId, tableId); } catch (error) { console.error('Error fetching rows:', error); throw new Error('Failed to fetch rows'); diff --git a/src/routes/blog/post/building-init-giveaway-app/+page.markdoc b/src/routes/blog/post/building-init-giveaway-app/+page.markdoc index 3f82c479c7..16ed879489 100644 --- a/src/routes/blog/post/building-init-giveaway-app/+page.markdoc +++ b/src/routes/blog/post/building-init-giveaway-app/+page.markdoc @@ -102,7 +102,7 @@ After the constants were added, we could now set up the Appwrite SDK. ```js // ./src/lib/appwrite.js -import { Account, Client, Databases } from 'appwrite'; +import { Account, Client, TablesDB } from 'appwrite'; import { APPWRITE_ENDPOINT, APPWRITE_PROJECT } from './constants'; export const client = new Client(); @@ -111,7 +111,7 @@ client.setEndpoint(APPWRITE_ENDPOINT).setProject(APPWRITE_PROJECT); export const account = new Account(client); -export const database = new Databases(client); +export const tablesDB = new TablesDB(client); ``` Once this is done, we could move forward to create the main application. @@ -182,12 +182,12 @@ To add or get information from the database, we created a database library in th // ./src/lib/database.js import { Query, ID } from 'appwrite'; -import { database } from './appwrite'; +import { tablesDB } from './appwrite'; import { TABLE_NAME, DATABASE_NAME } from './constants'; export const db = { list: async () => { - var entries = await database.listRows(DATABASE_NAME, TABLE_NAME, [ + var entries = await tablesDB.listRows(DATABASE_NAME, TABLE_NAME, [ Query.limit(500), Query.select(['discordName']) ]); @@ -203,7 +203,7 @@ export const db = { add: async (discordName, email) => { try { - await database.createRow(DATABASE_NAME, TABLE_NAME, ID.unique(), { + await tablesDB.createRow(DATABASE_NAME, TABLE_NAME, ID.unique(), { discordName: discordName, email: email }); diff --git a/src/routes/blog/post/how-to-optimize-your-appwrite-project/+page.markdoc b/src/routes/blog/post/how-to-optimize-your-appwrite-project/+page.markdoc index 2c1ec18aaf..453830e616 100644 --- a/src/routes/blog/post/how-to-optimize-your-appwrite-project/+page.markdoc +++ b/src/routes/blog/post/how-to-optimize-your-appwrite-project/+page.markdoc @@ -25,7 +25,7 @@ In Appwrite, fetching multiple rows from a database is made easy with the [listR For example, in a content management system where you need to load blog posts written by a particular author, rather than making individual requests for each row, use Appwrite's `listRows` method with a filter: ```javascript -const blogPosts = await databases.listRows( +const blogPosts = await tablesDB.listRows( '', '', [Query.equal('author', 'Michael Scott')], @@ -41,7 +41,7 @@ For applications with large datasets (e.g., e-commerce platforms with thousands For example, if you're loading products from a database, instead of fetching all products, fetch them in batches using pagination. ```javascript -const firstPage = await databases.listRows( +const firstPage = await tablesDB.listRows( '', '', [ @@ -51,7 +51,7 @@ const firstPage = await databases.listRows( ], ) -const secondPage = await databases.listRows( +const secondPage = await tablesDB.listRows( '', '', [ diff --git a/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc b/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc index 67144cd854..033b771d92 100644 --- a/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc +++ b/src/routes/blog/post/improve-devex-dev-keys/+page.markdoc @@ -76,12 +76,12 @@ const client = new Appwrite.Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint .setProject(''); // Your project ID -const database = new Appwrite.Databases(client); +const tablesDB = new Appwrite.TablesDB(client); document.querySelector('button').addEventListener('click', async () => { const promises = []; for (let i = 0; i < 200; i++) { - const promise = database.createRow( + const promise = tablesDB.createRow( 'testDb', // Your database ID 'testTable', // Your table ID Appwrite.ID.unique(), diff --git a/src/routes/blog/post/introducing-functions-ecosystem/+page.markdoc b/src/routes/blog/post/introducing-functions-ecosystem/+page.markdoc index 55b1553c2d..6ea64a3429 100644 --- a/src/routes/blog/post/introducing-functions-ecosystem/+page.markdoc +++ b/src/routes/blog/post/introducing-functions-ecosystem/+page.markdoc @@ -32,7 +32,7 @@ To combat this, we've introduced automatically generated, short-lived API keys f Here's how you can use them: ```jsx -import { Client, Databases } from 'node-appwrite'; +import { Client, TablesDB } from 'node-appwrite'; export default async ({ req, res }) => { const client = new Client() @@ -40,7 +40,7 @@ export default async ({ req, res }) => { .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID) .setKey(req.headers['x-appwrite-key']); - const databases = new Databases(client); + const tablesDB = new TablesDB(client); // Your function logic here diff --git a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc index 78a74030a8..5fd3aa1322 100644 --- a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc +++ b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc @@ -213,7 +213,7 @@ client .setEndpoint('') .setProject('') -const databases = new Appwrite.Databases(client) +const tablesDB = new Appwrite.TablesDB(client) const databaseId = '' const tableId = '' @@ -222,7 +222,7 @@ const tableId = '' Replace the placeholders with your actual values from the Appwrite console. -This code sets up the SDK so that you can call `databases.createRow()` and `databases.listRows()` in the rest of the script. +This code sets up the SDK so that you can call `tablesDB.createRow()` and `tablesDB.listRows()` in the rest of the script. {% /section %} @@ -242,7 +242,7 @@ form.addEventListener('submit', async (e) => { if (!title || !body) return try { - await databases.createRow(databaseId, tableId, 'unique()', { + await tablesDB.createRow(databaseId, tableId, 'unique()', { title, body, }) @@ -267,7 +267,7 @@ Now add a function that retrieves tickets and shows them in order, newest first: ```javascript async function loadTickets() { try { - const response = await databases.listRows(databaseId, tableId, [ + const response = await tablesDB.listRows(databaseId, tableId, [ Appwrite.Query.orderDesc('$sequence'), ]) const ticketList = document.getElementById('ticket-list') diff --git a/src/routes/blog/post/understand-data-queries/+page.markdoc b/src/routes/blog/post/understand-data-queries/+page.markdoc index c6d88c186c..9a9039d5c8 100644 --- a/src/routes/blog/post/understand-data-queries/+page.markdoc +++ b/src/routes/blog/post/understand-data-queries/+page.markdoc @@ -74,16 +74,16 @@ One of the data retrieval APIs the Appwrite Database offers is a list rows API t - `CONTAINS` operation: The contains operator allows filtering by values that are contained in an array. ```client-web -import { Client, Databases, Query } from "appwrite"; +import { Client, TablesDB, Query } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -const databases = new Databases(client); +const tablesDB = new TablesDB(client); // OR operator example -const movieData1 = databases.listRows( +const movieData1 = tablesDB.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.or([ @@ -93,7 +93,7 @@ const movieData1 = databases.listRows( ); // AND operator example -const movieData2 = databases.listRows( +const movieData2 = tablesDB.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.and([ @@ -103,7 +103,7 @@ const movieData2 = databases.listRows( ); // CONTAINS operator example -const movieData3 = databases.listRows( +const movieData3 = tablesDB.listRows( '[DATABASE_ID]', '[TABLE_ID]', Query.contains('director', ["Christopher Nolan"]) diff --git a/src/routes/blog/post/what-is-golang/+page.markdoc b/src/routes/blog/post/what-is-golang/+page.markdoc index a7e2f4afc0..3a6835295e 100644 --- a/src/routes/blog/post/what-is-golang/+page.markdoc +++ b/src/routes/blog/post/what-is-golang/+page.markdoc @@ -9,15 +9,15 @@ author: aditya-oberai category: product featured: false --- -Appwrite has just announced support for Go SDK and Function runtime in version 1.6. The Go programming language (also known as Golang) is popular for its concurrency model, speed, and simple URL-based dependency management. +Appwrite has just announced support for Go SDK and Function runtime in version 1.6. The Go programming language (also known as Golang) is popular for its concurrency model, speed, and simple URL-based dependency management. With Appwrite’s new Go runtime, you can take advantage of Go’s speed to handle complex tasks like calculations, statistics, or file transformations more efficiently. -This blog is going to go over Go strengths, limitations, and how you can potentially leverage it in your projects, whether you’re already a Go developer or a JS/Python developer looking to write faster applications. +This blog is going to go over Go strengths, limitations, and how you can potentially leverage it in your projects, whether you’re already a Go developer or a JS/Python developer looking to write faster applications. # What is the Go programming language? -Go, or Golang, is a statically typed programming language developed by Google. It's designed for simplicity, reliability, and efficiency, making it ideal for both beginners and experienced developers. +Go, or Golang, is a statically typed programming language developed by Google. It's designed for simplicity, reliability, and efficiency, making it ideal for both beginners and experienced developers. The language was designed by Robert Griesemer, Rob Pike, and Ken Thompson, who aimed to address some of the common criticisms of other languages used at Google, such as C++ and Java, particularly in terms of compilation time and ease of use. @@ -141,9 +141,9 @@ func main() { appwriteClient := client.NewClient() appwriteClient.SetProject("") appwriteClient.SetKey(“”) -appwriteDatabases := databases.NewDatabases(appwriteClient) +appwriteTablesDB := databases.NewTablesDB(appwriteClient) -response, err := appwriteDatabases.Create("unique()", "Pokemon") +response, err := appwriteTablesDB.Create("unique()", "Pokemon") if err != nil { fmt.Println(err) @@ -232,10 +232,10 @@ func main() { ## Uber -Uber uses Go for its high-performance, scalable backend services. The concurrency model of Go allows Uber to handle millions of ride requests simultaneously. Go's efficiency helps reduce latency and improve the overall user experience. More specifically, [they mention](https://www.uber.com/en-CZ/blog/go-geofence-highest-query-per-second-service/) high developer accessibility and reliability: +Uber uses Go for its high-performance, scalable backend services. The concurrency model of Go allows Uber to handle millions of ride requests simultaneously. Go's efficiency helps reduce latency and improve the overall user experience. More specifically, [they mention](https://www.uber.com/en-CZ/blog/go-geofence-highest-query-per-second-service/) high developer accessibility and reliability: > “Go typically takes just a few days for a C++, Java or Node.js developer to learn, and the code is easy to maintain. This service has had 99.99% uptime since inception. Importantly, we haven’t seen any issues with Go’s runtime.” -> +> ## Dropbox @@ -246,18 +246,18 @@ Dropbox migrated its performance-critical components from Python to Go, which si SoundCloud uses Go to build internal services that require high concurrency and performance. Go's simplicity and ease of maintenance also help their developers to iterate quickly and deploy updates smoothly. Here’s what [developers at SoundCloud say about Golang](https://developers.soundcloud.com/blog/go-at-soundcloud): > Static typing and fast compilation enable us to do near-realtime static analysis and unit testing during development. It also means that building, testing and rolling out Go applications through our deployment system is as fast as it gets. -> +> ## Monzo Monzo, a UK digital bank, started using Golang for its microservices architecture before eventually moving its entire backend infrastructure over to Go. Monzo’s systems engineer, Matt Heath, [praised Go for its simplicity and speed](https://www.infoq.com/news/2017/03/monzo-bank-golang/): > Go is a perfect language for creating microservice architectures, and the concurrency features, and the language in general, has allowed the easy creation of small and simple networked services at Monzo that are focused around the 'single responsibility principle'. -> +> # Learning Go programming language -Go is pretty simple to learn, especially if you’ve already worked with JavaScript, Python, or C++. Go’s [learning hub](https://go.dev/learn/) offers a wide variety of resources, from guided courses to video tutorials and example-led lessons. +Go is pretty simple to learn, especially if you’ve already worked with JavaScript, Python, or C++. Go’s [learning hub](https://go.dev/learn/) offers a wide variety of resources, from guided courses to video tutorials and example-led lessons. One of the best ways to learn Go is to follow their guided learning journeys. They offer dedicated video and written tutorials for [web developers](https://gowebexamples.com/) and [complete beginners](https://www.youtube.com/watch?v=Q0sKAMal4WQ). @@ -265,9 +265,9 @@ You can get help and support from the large Go developer community, specifically # Conclusion -Golang is a great choice for web app development due to its performance and concurrency capabilities. +Golang is a great choice for web app development due to its performance and concurrency capabilities. -If you're building a high-traffic, performance-intensive app that needs to be reliable and maintainable, Appwrite’s new Go SDK + Function runtime can help you leverage Go’s speed and simplicity. +If you're building a high-traffic, performance-intensive app that needs to be reliable and maintainable, Appwrite’s new Go SDK + Function runtime can help you leverage Go’s speed and simplicity. Here are some more resources to get you started with Go and Appwrite Go SDK: From a35a05eb9abaaece836b69da2f87a6abcb9c34b3 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Wed, 20 Aug 2025 19:35:38 +0100 Subject: [PATCH 08/13] Replace Databases with TablesDB in examples --- .../+page.markdoc | 10 +++++----- .../post/build-fullstack-svelte-appwrite/+page.markdoc | 2 +- src/routes/blog/post/what-is-golang/+page.markdoc | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc index e769f23a3e..0d2eae44df 100644 --- a/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc +++ b/src/routes/blog/post/3-things-you-can-build-with-go-runtime/+page.markdoc @@ -186,12 +186,12 @@ To build this function, create a `services` directory in the function folder and package services import ( - "github.com/appwrite/sdk-for-go/databases" + "github.com/appwrite/sdk-for-go/tablesdb" "github.com/appwrite/sdk-for-go/permission" "github.com/open-runtimes/types-for-go/v4/openruntimes" ) -func DoesDatabaseExist(dbs databases.Databases, dbId string) bool { +func DoesDatabaseExist(dbs tablesdb.TablesDB, dbId string) bool { _, err := dbs.Get(dbId) if err != nil { return false @@ -199,7 +199,7 @@ func DoesDatabaseExist(dbs databases.Databases, dbId string) bool { return true } -func DoesTableExist(dbs databases.Databases, dbId string, collId string) bool { +func DoesTableExist(dbs tablesdb.TablesDB, dbId string, collId string) bool { _, err := dbs.GetTable(dbId, collId) if err != nil { return false @@ -207,7 +207,7 @@ func DoesTableExist(dbs databases.Databases, dbId string, collId string) bool { return true } -func DoesColumnExist(dbs databases.Databases, dbId string, collId string, attribId string) bool { +func DoesColumnExist(dbs tablesdb.TablesDB, dbId string, collId string, attribId string) bool { _, err := dbs.GetColumn(dbId, collId, attribId) if err != nil { return false @@ -215,7 +215,7 @@ func DoesColumnExist(dbs databases.Databases, dbId string, collId string, attrib return true } -func InitialiseDatabase(Context openruntimes.Context, dbs databases.Databases, dbId string, collId string) { +func InitialiseDatabase(Context openruntimes.Context, dbs tablesdb.TablesDB, dbId string, collId string) { doesDbExist := DoesDatabaseExist(dbs, dbId) if !doesDbExist { dbs.Create( diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index cff73dac65..e53ef145b3 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -181,7 +181,7 @@ export const DATABASE_ID = PUBLIC_APPWRITE_DATABASE_ID ``` -This configuration file initializes our connection to Appwrite. The `Client` class creates a new Appwrite client instance, which we configure with our endpoint and project ID from our environment variables. We then create instances of the `Databases` and `Account` services, which we'll use throughout our application for database operations and user authentication. +This configuration file initializes our connection to Appwrite. The `Client` class creates a new Appwrite client instance, which we configure with our endpoint and project ID from our environment variables. We then create instances of the `TablesDB` and `Account` services, which we'll use throughout our application for database operations and user authentication. Finally, we export the table IDs from our environment variables so that we can use them in other parts of our application. diff --git a/src/routes/blog/post/what-is-golang/+page.markdoc b/src/routes/blog/post/what-is-golang/+page.markdoc index 3a6835295e..78ded3e543 100644 --- a/src/routes/blog/post/what-is-golang/+page.markdoc +++ b/src/routes/blog/post/what-is-golang/+page.markdoc @@ -134,14 +134,14 @@ package main import ( "fmt" "github.com/appwrite/sdk-for-go/client" -"github.com/appwrite/sdk-for-go/databases" +"github.com/appwrite/sdk-for-go/tablesdb" ) func main() { appwriteClient := client.NewClient() appwriteClient.SetProject("") appwriteClient.SetKey(“”) -appwriteTablesDB := databases.NewTablesDB(appwriteClient) +appwriteTablesDB := tablesdb.NewTablesDB(appwriteClient) response, err := appwriteTablesDB.Create("unique()", "Pokemon") From 0ff9b6f4984af7ab870ce7587a51388ab1c302a1 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Wed, 20 Aug 2025 19:53:26 +0100 Subject: [PATCH 09/13] update terminologies --- .../+page.markdoc | 20 +++++++++---------- .../+page.markdoc | 2 +- .../+page.markdoc | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc b/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc index 2a941cbb43..62d7e8791e 100644 --- a/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc +++ b/src/routes/blog/post/announcing-atomic-numeric-operations/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post title: "Announcing Atomic numeric operations: Safe, server-side increments and decrements" -description: Safely update numeric fields like counters, stock levels, or credits without fetching or rewriting the document. +description: Safely update numeric fields like counters, stock levels, or credits without fetching or rewriting the row. date: 2025-08-04 cover: /images/blog/announcing-atomic-numeric-operations/cover.png timeToRead: 5 @@ -12,17 +12,17 @@ featured: false In high-concurrency systems like social apps, games, and usage-tracked services, even updating a single number such as a like, retry count, or quota, can lead to consistency issues. When multiple clients try to update the same value simultaneously, it’s easy to end up with conflicting writes, lost updates, or inaccurate data. -Most setups require you to fetch the document, change the number on the client, and then write it back. This process is slow, error-prone, and wastes bandwidth, especially when you're only trying to change a single field. +Most setups require you to fetch the row, change the number on the client, and then write it back. This process is slow, error-prone, and wastes bandwidth, especially when you're only trying to change a single field. To change this, we introduce **Atomic numeric operations** in Appwrite. -A new feature that lets you increment or decrement numeric fields directly on the server, without fetching the full document. It’s fast, safe, bandwidth-efficient, and concurrency-friendly. +A new feature that lets you increment or decrement numeric fields directly on the server, without fetching the full row. It's fast, safe, bandwidth-efficient, and concurrency-friendly. # Race-free numeric updates -Before this feature, updating a number meant fetching the entire document, modifying it on the client, and writing it back, a process prone to race conditions, unnecessary bandwidth use, and extra logic to handle edge cases. +Before this feature, updating a number meant fetching the entire row, modifying it on the client, and writing it back, a process prone to race conditions, unnecessary bandwidth use, and extra logic to handle edge cases. -With **Atomic numeric operations,** you simply send a delta (like `+1` or `-3`), and Appwrite applies the update atomically on the server. No full document reads, no conflicts, no custom logic. Just consistent, permission-aware updates that work reliably under load. +With **Atomic numeric operations,** you simply send a delta (like `+1` or `-3`), and Appwrite applies the update atomically on the server. No full row reads, no conflicts, no custom logic. Just consistent, permission-aware updates that work reliably under load. # Built for real-time, multi-user systems @@ -55,7 +55,7 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.incrementDocumentAttribute( '', - '', + '', '', 'likes', // attribute 1 // value @@ -75,7 +75,7 @@ const tablesDB = new TablesDB(client); const result = await tablesDB.decrementDocumentAttribute( '', - '', + '', '', 'credits', // attribute 5 // value @@ -86,17 +86,17 @@ const result = await tablesDB.decrementDocumentAttribute( This feature solves a common problem with a clean, built-in approach. You don’t need to write custom logic to handle concurrency, retries, or limits. It’s a simple API call that replaces a lot of complex edge-case handling. And it just works. -- **Atomic by default:** Every delta is applied in a single server-side write. The document is locked during the update, so there’s no room for race conditions or overlapping writes, even under heavy concurrency. +- **Atomic by default:** Every delta is applied in a single server-side write. The row is locked during the update, so there's no room for race conditions or overlapping writes, even under heavy concurrency. - **Supports both increments and decrements:** You're not limited to just adding `+1`. You can apply any positive or negative delta, whether you're increasing API credits or reducing stock levels after a purchase. - **Built-in constraints:** You can define optional `min` and `max`bounds on the value. If the update would push the value outside that range, it’s rejected. Great for enforcing limits like “stock can’t go below zero” or “credits can't exceed a cap.” -- **Respects permissions:** This works just like any other Appwrite document update. If the user doesn’t have permission to modify the document, the update doesn’t go through. No exceptions. +- **Respects permissions:** This works just like any other Appwrite row update. If the user doesn't have permission to modify the row, the update doesn't go through. No exceptions. Atomic numeric operations are live for both **Appwrite Cloud** and **Self-Hosted** environments. -This is a core building block for modern, concurrent-safe applications and it’s now built into Appwrite’s document system. +This is a core building block for modern, concurrent-safe applications and it's now built into Appwrite's row system. # More resources diff --git a/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc b/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc index df5dba1e11..663faeee96 100644 --- a/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc +++ b/src/routes/blog/post/introducing-new-appwrite-cli/+page.markdoc @@ -89,7 +89,7 @@ Appwrite CLI is now in listening mode. Try changing your code and seeing how the GitOps is a common way of tracking and migrating database changes. The latest Appwrite CLI generation includes a few features to help you migrate your database changes easily. -When running `appwrite push collection`, the CLI will compare your local `appwrite.config.json` collection definition against the currently deployed remote collection and will present you with a detailed table awaiting your decision, for example: +When running `appwrite push table`, the CLI will compare your local `appwrite.config.json` table definition against the currently deployed remote table and will present you with a detailed table awaiting your decision, for example: ``` Key │ Action │ Reason diff --git a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc index 5fd3aa1322..392eedb8f3 100644 --- a/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc +++ b/src/routes/blog/post/track-document-order-with-sequence/+page.markdoc @@ -1,7 +1,7 @@ --- layout: post -title: Using $sequence to track document order in Appwrite -description: Learn how to use Appwrite's $sequence column to track document order in your database. +title: Using $sequence to track row order in Appwrite +description: Learn how to use Appwrite's $sequence column to track row order in your database. date: 2025-07-16 cover: /images/blog/track-document-order-with-sequence/cover.png timeToRead: 6 From 8ea37138744e433c5c12d74442e11966828ab65f Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Tue, 9 Sep 2025 00:41:10 +0100 Subject: [PATCH 10/13] Update src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../blog/post/build-fullstack-svelte-appwrite/+page.markdoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index 5842d60009..3fb9b9644e 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -682,7 +682,11 @@ Finally, let's add utility functions for managing expenses: ```js async function deleteExpense(id) { try { - await tablesDB.deleteRow(DATABASE_ID, EXPENSES_TABLE_ID, id) + await tablesDB.deleteRow({ + databaseId: DATABASE_ID, + tableId: EXPENSES_TABLE_ID, + rowId: id, + }) await fetchExpenses() } catch (e) { error = 'Failed to delete expense' From 3e00a201dfbe977971b80ecc2a0f71449ad74478 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Tue, 9 Sep 2025 00:41:28 +0100 Subject: [PATCH 11/13] Update src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../post/build-fullstack-svelte-appwrite/+page.markdoc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index 3fb9b9644e..ad67aeb385 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -644,9 +644,11 @@ async function handleSubmit() { } if (editingExpense) { - await tablesDB.updateRow(DATABASE_ID, EXPENSES_TABLE_ID, editingExpense.$id, { - ...expenseData, - updatedAt: now + await tablesDB.updateRow({ + databaseId: DATABASE_ID, + tableId: EXPENSES_TABLE_ID, + rowId: editingExpense.$id, + data: { ...expenseData, updatedAt: now }, }) } else { await tablesDB.createRow( From ed59e2eddfc62d6c0fd332fcfb397fd3b3f7be53 Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Tue, 9 Sep 2025 00:41:51 +0100 Subject: [PATCH 12/13] Update src/routes/blog/post/understand-data-queries/+page.markdoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../blog/post/understand-data-queries/+page.markdoc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/routes/blog/post/understand-data-queries/+page.markdoc b/src/routes/blog/post/understand-data-queries/+page.markdoc index 9a9039d5c8..56ef469adb 100644 --- a/src/routes/blog/post/understand-data-queries/+page.markdoc +++ b/src/routes/blog/post/understand-data-queries/+page.markdoc @@ -103,12 +103,11 @@ const movieData2 = tablesDB.listRows( ); // CONTAINS operator example -const movieData3 = tablesDB.listRows( - '[DATABASE_ID]', - '[TABLE_ID]', - Query.contains('director', ["Christopher Nolan"]) -); -``` +const movieData3 = tablesDB.listRows({ + databaseId: '[DATABASE_ID]', + tableId: '[TABLE_ID]', + queries: [Query.contains('director', ['Christopher Nolan'])], +}); Mastering the art of data querying is a continuous process. As a developer, your aim should be to write efficient, secure, and maintainable queries. Remember, the power of a database is harnessed through the effectiveness of its queries. From e62eb3650cc60d10ea4c5e7cfc229146b94045dd Mon Sep 17 00:00:00 2001 From: Ebenezer Don Date: Tue, 9 Sep 2025 00:47:02 +0100 Subject: [PATCH 13/13] Update src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../post/build-fullstack-svelte-appwrite/+page.markdoc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc index ad67aeb385..875906978e 100644 --- a/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc +++ b/src/routes/blog/post/build-fullstack-svelte-appwrite/+page.markdoc @@ -596,9 +596,11 @@ onMount(async () => { async function fetchExpenses() { try { loading = true - const response = await tablesDB.listRows(DATABASE_ID, EXPENSES_TABLE_ID, [ - Query.orderDesc('$createdAt') - ]) + const response = await tablesDB.listRows({ + databaseId: DATABASE_ID, + tableId: EXPENSES_TABLE_ID, + queries: [Query.orderDesc('$createdAt')], + }) expenses = response.rows calculateStats() } catch (e) {