Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .optimize-cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
"images/blog/appwrite-decoded-khushboo/khushboo-tech-interviews.png": "c54715b658aa52f4c7139e7a1398b9a0e0cb55bcc3aa3dd9101f6164e0bd3379",
"images/blog/appwrite-decoded-khushboo/khushboo-with-eldad.png": "b358b6a53d2c5de662b7ddf66aeeb6886478d98c5585a5e2f7068422986cba60",
"images/blog/appwrite-decoded/cover-sara.png": "03ef95d81d475dde4caae31c0b442271c8ae904f8655013a2dfe2f8878b97e44",
"images/blog/appwrite-generate/cover.png": "01770d4d6124b317a5103ced1d69b791ef0ce1f1e3a47e4b5072a5fd33c4953d",
"images/blog/appwrite-homepage-redesign/cover-image.png": "bc09d91c421f5967c8986eeaae6f7f001380bee686cd3371fd63a8392484647e",
"images/blog/appwrite-homepage-redesign/iterations-top-part.png": "713613e719366db8d271ab58815ce5f6db476c0b6a764ce53b4884ddd483f66c",
"images/blog/appwrite-homepage-redesign/new-homepage.png": "e58cdf775e1f23ab71e205e0a9d1f6a8573d6e55d673b1a6190be6a79e4e43f0",
Expand Down
74 changes: 74 additions & 0 deletions src/routes/blog/post/appwrite-generate/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
layout: post
title: "Introducing generate command in the Appwrite CLI: Create a type-safe SDK from your schema"
description: Generate a type-safe SDK for your Appwrite project with the new generate command in the Appwrite CLI. It reads your database schema and creates typed helpers for querying and mutating rows with autocomplete.
date: 2026-02-06
cover: /images/blog/appwrite-generate/cover.png
timeToRead: 5
author: chirag-aggarwal
category: announcement
featured: false
callToAction: true
draft: false
---

Every database-driven app eventually ends up with the same glue code: types, table wrappers, and helper functions that make your schema feel safe to use in the editor.

It starts small. Then your schema changes. A column gets renamed, a new required field appears, and suddenly the "simple" query you wrote last week is a runtime bug waiting to happen.

To eliminate that drift, we're introducing the new `appwrite generate` command in the **Appwrite CLI**, which creates a **type-safe SDK tailored to your Appwrite project**.

It reads your database schema and generates typed helpers, so you can interact with your tables using auto-completed methods with type checking built in.

# One command. A project-aware SDK.

Run the following command in your project directory:

```sh
appwrite generate
```

The CLI automatically detects your project's language and generates your SDK into a `generated/appwrite/` directory.

# Built for teams that ship fast

The `appwrite generate` command is designed to keep your codebase and your schema in lockstep:

- **Less boilerplate:** Stop hand-writing wrappers and types for every table.
- **Fewer runtime surprises:** Schema changes show up as type errors instead of production bugs.
- **Faster onboarding:** New teammates can discover what's available straight from the SDK.
- **Confident refactors:** Regenerate after schema updates and let the compiler tell you what needs attention.

# Usage

After generating the SDK, import it into your project and configure constants:

```js
import { databases } from "./generated/appwrite/index.js";
```

Configure your SDK constants by setting the values in `./generated/appwrite/constants.ts`.

Then use the generated helpers to interact with your tables:

```js
const mydb = databases.use("test-db");
const customers = mydb.use("customers");

// Create a row
await customers.create({
name: "Walter O' Brian",
email: "walter@example.com",
plan: "enterprise"
});
```

Instead of juggling stringly-typed shapes, your editor can now guide you with autocomplete and validation based on the actual schema in your Appwrite project.

# Available now

The `appwrite generate` command is available today in the Appwrite CLI.

To get started, head over to the [documentation](/docs/tooling/command-line/generate) and try it out in your next project.

As always, we'd love to see what you build with it.
4 changes: 4 additions & 0 deletions src/routes/docs/tooling/command-line/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
{
label: 'Non interactive',
href: '/docs/tooling/command-line/non-interactive'
},
{
label: 'Generate SDK',
href: '/docs/tooling/command-line/generate'
}
]
},
Expand Down
3 changes: 3 additions & 0 deletions src/routes/docs/tooling/command-line/commands/+page.markdoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Below is a list of the available commands in the Appwrite CLI. You can get more
* `types [options] <output-directory>`
* The types command generates type definitions based on your Appwrite database schema. Learn more about [type generation](/docs/products/databases/type-generation).
---
* `generate`
* The generate command creates a type-safe SDK tailored to your project. It detects your project's language and generates typed helpers based on your database schema. Learn more about [SDK generation](/docs/tooling/command-line/generate).
---
{% /table %}

## Account commands {% #account-commands %}
Expand Down
164 changes: 164 additions & 0 deletions src/routes/docs/tooling/command-line/generate/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
layout: article
title: Generate SDK
description: Generate a type-safe SDK for your Appwrite project using the Command-Line Tool (CLI). Automatically create typed helpers based on your database schema.
---

{% partial file="cli-disclaimer.md" /%}

The `generate` command creates a type-safe SDK tailored to your Appwrite project. It reads your database schema and generates typed helpers, so you can interact with your tables using auto-completed methods, resulting in a better developer experience.

# Generate SDK {% #generate-sdk %}

Run the following command in your project directory:

```sh
appwrite generate
```

The CLI automatically detects your project's language and generates the SDK to a `generated/appwrite/` directory.

# Options {% #options %}

{% table %}
* Option
* Description
---
* `-o, --output <directory>`
* Output directory for generated files (default: `"generated"`)
---
* `-l, --language <language>`
* Target language for SDK generation (supported: `typescript`)
---
* `--server <mode>`
* Override server-side generation (`auto`|`true`|`false`) (default: `"auto"`)
---
* `-h, --help`
* Display help for command
---
{% /table %}

# Generated files {% #generated-files %}

The generated SDK includes the following files:

{% table %}
* File
* Description
---
* `types.ts`
* Type definitions based on your database schema.
---
* `databases.ts`
* Typed database helpers for querying and mutating rows.
---
* `index.ts`
* Entry point that exports all generated helpers.
---
* `constants.ts`
* Configuration constants such as your project endpoint and project ID. Update these values before using the SDK.
---
{% /table %}

# Usage {% #usage %}

After generating the SDK, import it into your project:

```js
import { databases } from "./generated/appwrite/index.js";
```

Configure your SDK constants by setting the values in `./generated/appwrite/constants.ts`.

Use the generated helpers to interact with your tables:

```js
const customers = databases.use("main").use("customers");

const customer = await customers.create({
name: "Walter O' Brian",
email: "walter@example.com"
});
```

Comment on lines +75 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and check its basic properties
ls -la src/routes/docs/tooling/command-line/generate/+page.markdoc 2>&1 || echo "File not found"
wc -l src/routes/docs/tooling/command-line/generate/+page.markdoc 2>&1 || echo "Cannot count lines"

Repository: appwrite/website

Length of output: 232


🏁 Script executed:

# Check the specific lines mentioned (75-83, 79, 103, 139, 156)
if [ -f "src/routes/docs/tooling/command-line/generate/+page.markdoc" ]; then
  echo "=== Lines 75-83 ==="
  sed -n '75,83p' src/routes/docs/tooling/command-line/generate/+page.markdoc | cat -A
  echo ""
  echo "=== Line 79 ==="
  sed -n '79p' src/routes/docs/tooling/command-line/generate/+page.markdoc | cat -A
  echo ""
  echo "=== Line 103 ==="
  sed -n '103p' src/routes/docs/tooling/command-line/generate/+page.markdoc | cat -A
  echo ""
  echo "=== Line 139 ==="
  sed -n '139p' src/routes/docs/tooling/command-line/generate/+page.markdoc | cat -A
  echo ""
  echo "=== Line 156 ==="
  sed -n '156p' src/routes/docs/tooling/command-line/generate/+page.markdoc | cat -A
fi

Repository: appwrite/website

Length of output: 538


🏁 Script executed:

# Check for curly/smart quotes and O'Brien spelling variations
if [ -f "src/routes/docs/tooling/command-line/generate/+page.markdoc" ]; then
  echo "=== Checking for smart quotes (curly apostrophes) ==="
  # Using hexdump to detect non-ASCII characters
  grep -n "O" src/routes/docs/tooling/command-line/generate/+page.markdoc | head -20
  echo ""
  echo "=== Lines containing 'O' followed by apostrophe variants ==="
  # Check for both ASCII apostrophe (') and curly quote (')
  grep -En "O.{1,2}[Bb]ri" src/routes/docs/tooling/command-line/generate/+page.markdoc
fi

Repository: appwrite/website

Length of output: 917


🏁 Script executed:

# Detailed character inspection for apostrophe types
if [ -f "src/routes/docs/tooling/command-line/generate/+page.markdoc" ]; then
  python3 << 'PYEOF'
import re

with open("src/routes/docs/tooling/command-line/generate/+page.markdoc", "r", encoding="utf-8") as f:
    lines = f.readlines()

print("=== Checking for 'O'Brien' or 'O' Brian' variants ===")
for i, line in enumerate(lines, 1):
    if re.search(r"O['''].*[Bb]rian", line):
        # Show the line with character codes for apostrophe
        apostrophe_match = re.search(r"O([''']).*[Bb]rian", line)
        if apostrophe_match:
            apos_char = apostrophe_match.group(1)
            apos_code = ord(apos_char)
            apos_name = "ASCII apostrophe (U+0027)" if apos_code == 0x0027 else f"Unicode {hex(apos_code)}"
            print(f"Line {i}: {line.strip()}")
            print(f"  Apostrophe type: {apos_name}")
PYEOF
fi

Repository: appwrite/website

Length of output: 617


Spelling: "O' Brian" → "O'Brien" (remove space after apostrophe).

The example name appears to reference the character Walter O'Brien. The surname has a spacing error in all five occurrences (lines 79, 103, 130, 139, 156)—it should be "O'Brien" without a space between the apostrophe and "Brien". The apostrophe characters are correctly using ASCII straight quotes, so no encoding issue exists.

🤖 Prompt for AI Agents
In `@src/routes/docs/tooling/command-line/generate/`+page.markdoc around lines 75
- 83, Update the example name strings to remove the space after the apostrophe
so the surname is "O'Brien" (not "O' Brian") in every occurrence; locate the
example usages around the customers example and calls to customers.create / any
other sample literals in this file and replace "Walter O' Brian" (and any other
"O' Brian" occurrences at lines noted) with "Walter O'Brien" to fix the
spelling.

The generated helpers provide auto-completion and type checking based on your database schema, reducing errors and improving developer experience.

# Examples {% #examples %}

The generated SDK supports all common database operations. Below are examples across different use cases.

## Get a row {% #get-row %}

```js
const customer = await customers.get("customer-id-123");
```

## List rows with queries {% #list-rows %}

The `list` method accepts a typed query builder that provides auto-completion for your table's columns.

```js
const results = await customers.list({
queries: (q) => [
q.equal("name", "Walter O' Brian"),
q.orderDesc("$createdAt"),
q.limit(10)
]
});
```

## Update a row {% #update-row %}

```js
await customers.update("customer-id-123", {
email: "walter@scorpion.com"
});
```

## Delete a row {% #delete-row %}

```js
await customers.delete("customer-id-123");
```

## Bulk operations {% #bulk-operations %}

Create, update, or delete multiple rows at once.

```js
await customers.createMany([
{ name: "Walter O' Brian", email: "walter@example.com" },
{ name: "Paige Dineen", email: "paige@example.com" }
]);
```

```js
await customers.updateMany(
{ email: "updated@example.com" },
{
queries: (q) => [q.equal("name", "Walter O' Brian")]
}
);
```

```js
await customers.deleteMany({
queries: (q) => [q.equal("name", "Paige Dineen")]
});
```

## Permissions {% #permissions %}

Set row-level permissions when creating or updating rows.

```js
await customers.create(
{ name: "Walter O' Brian", email: "walter@example.com" },
{
permissions: (permission, role) => [
permission.read(role.any()),
permission.write(role.user("user-id-123"))
]
}
);
```
Binary file added static/images/blog/appwrite-generate/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.