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
2 changes: 1 addition & 1 deletion src/partials/auth-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ You can change the session limit in the **Security** tab of the Auth Service in

Security is very important to protect users' data and privacy.
Appwrite uses a [permissions model](/docs/advanced/platform/permissions) coupled with user sessions to ensure users need correct permissions to access resources.
With all Appwrite services, including databases and storage, access is granted at the collection, bucket, document, or file level.
With all Appwrite services, including databases and storage, access is granted at the table, bucket, row, or file level.
These permissions are enforced for client SDKs and server SDKs when using JWT, but are ignored when using a server SDK with an API key.

# Password history {% #password-history %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ A backend that ships all seven under one model is the difference between a weeke
[Appwrite Cloud](https://cloud.appwrite.io) is shaped for this exact list.

- [Auth](/docs/products/auth) handles email and password, OAuth, magic URL, email and phone OTP, MFA, sessions, and [Teams](/docs/products/auth/teams) for the multi-user ideas.
- [Databases](/docs/products/databases) cover tables, typed columns, rows, relationships, queries, transactions, and per-document permissions.
- [Databases](/docs/products/databases) cover tables, typed columns, rows, relationships, queries, transactions, and row-level permissions.
- [Storage](/docs/products/storage) gives you buckets with size and MIME limits, antivirus, encryption, image transformations, and signed URLs.
- [Functions](/docs/products/functions) cover server-side logic in Node, Python, Go, PHP, Dart, Ruby, Deno, Rust, and more, with execution logs, env vars, CRON triggers, and event triggers.
- [Sites](/docs/products/sites) hosts the frontend with custom domains, env vars, rollbacks, and build logs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ faqs:
- question: "How does the Go runtime compare to Node.js or Python in Appwrite Functions?"
answer: "In Appwrite's internal benchmarks, the Go runtime had up to 3x faster cold starts and roughly 5x lower memory usage than several interpreted runtimes including Node.js, Deno, Ruby, and Python. Build times can be slower because Go is compiled, but the runtime performance gains usually pay off for production workloads."
- question: "Can I trigger Go Appwrite Functions from events?"
answer: "Yes. Like every Appwrite Function, a Go function can be triggered by HTTP requests, CRON schedules, or events emitted by Appwrite products (user creation, document changes, file uploads, etc.). The event payload is delivered to your handler so you can route on it."
answer: "Yes. Like every Appwrite Function, a Go function can be triggered by HTTP requests, CRON schedules, or events emitted by Appwrite products (user creation, row changes, file uploads, etc.). The event payload is delivered to your handler so you can route on it."
- question: "How do I deploy a Go Appwrite Function via CI/CD?"
answer: "Connect your GitHub repository to your function in the Appwrite console and pick a branch. Every push to that branch triggers a new build and deployment automatically. You can also deploy from the Appwrite CLI by running `appwrite push functions` from your local project."
- question: "Can I develop Appwrite Go functions locally before deploying?"
Expand All @@ -38,11 +38,11 @@ Our Go runtime (just like our other runtimes) has been developed by our team and

## Event-driven nature

Appwrite Functions can be executed by various types of events, which allows you to integrate them into your applications in many different ways. These events include all HTTP actions (to consume like a REST API), CRON schedules (to run them on set time periods), and any events across the various Appwrite products in your project (for example, user creation, document deletion, or file upload).
Appwrite Functions can be executed by various types of events, which allows you to integrate them into your applications in many different ways. These events include all HTTP actions (to consume like a REST API), CRON schedules (to run them on set time periods), and any events across the various Appwrite products in your project (for example, user creation, row deletion, or file upload).

## 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

Expand All @@ -64,7 +64,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.

Expand Down Expand Up @@ -151,7 +151,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.

Expand Down Expand Up @@ -191,70 +191,70 @@ 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 table 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.

```go
package services

import (
"github.com/appwrite/sdk-for-go/databases"
"github.com/appwrite/sdk-for-go/permission"
"github.com/appwrite/sdk-for-go/tablesdb"
"github.com/open-runtimes/types-for-go/v4/openruntimes"
)

func DoesDatabaseExist(dbs databases.Databases, dbId string) bool {
_, err := dbs.Get(dbId)
func DoesDatabaseExist(tablesDB tablesdb.TablesDB, dbId string) bool {
_, err := tablesDB.Get(dbId)
if err != nil {
return false
}
return true
}

func DoesCollectionExist(dbs databases.Databases, dbId string, collId string) bool {
_, err := dbs.GetCollection(dbId, collId)
func DoesTableExist(tablesDB tablesdb.TablesDB, dbId string, tableId string) bool {
_, err := tablesDB.GetTable(dbId, tableId)
if err != nil {
return false
}
return true
}

func DoesAttributeExist(dbs databases.Databases, dbId string, collId string, attribId string) bool {
_, err := dbs.GetAttribute(dbId, collId, attribId)
func DoesColumnExist(tablesDB tablesdb.TablesDB, dbId string, tableId string, columnId string) bool {
_, err := tablesDB.GetColumn(dbId, tableId, columnId)
if err != nil {
return false
}
return true
}

func InitialiseDatabase(Context openruntimes.Context, dbs databases.Databases, dbId string, collId string) {
doesDbExist := DoesDatabaseExist(dbs, dbId)
func InitialiseDatabase(Context openruntimes.Context, tablesDB tablesdb.TablesDB, dbId string, tableId string) {
doesDbExist := DoesDatabaseExist(tablesDB, dbId)
if !doesDbExist {
dbs.Create(
tablesDB.Create(
dbId,
"URL Databases",
)
}

doesCollExist := DoesCollectionExist(dbs, dbId, collId)
if !doesCollExist {
dbs.CreateCollection(
doesTableExist := DoesTableExist(tablesDB, dbId, tableId)
if !doesTableExist {
tablesDB.CreateTable(
dbId,
collId,
tableId,
"URLs",
dbs.WithCreateCollectionPermissions([]string{permission.Read("any")}),
tablesDB.WithCreateTablePermissions([]string{permission.Read("any")}),
)
}

doesAttribExist := DoesAttributeExist(dbs, dbId, collId, "longUrl")
if !doesAttribExist {
dbs.CreateUrlAttribute(
doesColumnExist := DoesColumnExist(tablesDB, dbId, tableId, "longUrl")
if !doesColumnExist {
tablesDB.CreateUrlColumn(
dbId,
collId,
tableId,
"longUrl",
true,
dbs.WithCreateUrlAttributeArray(false),
tablesDB.WithCreateUrlColumnArray(false),
)
}
}
Expand Down Expand Up @@ -289,12 +289,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 := "urlCollection"
tableId := "urlTable"

services.InitialiseDatabase(Context, *databases, dbId, collId)
services.InitialiseDatabase(Context, *tablesDB, dbId, tableId)

if Context.Req.Method == "POST" {
var requestBody RequestBody
Expand All @@ -307,9 +307,9 @@ func Main(Context openruntimes.Context) openruntimes.Response {
}, Context.Res.WithStatusCode(400))
}

_, err = databases.CreateDocument(
_, err = tablesDB.CreateRow(
dbId,
collId,
tableId,
requestBody.ShortId,
map[string]interface{}{
"longUrl": requestBody.LongUrl,
Expand Down Expand Up @@ -339,15 +339,15 @@ func Main(Context openruntimes.Context) openruntimes.Response {

shortId := path[1:]

document, err := databases.GetDocument(dbId, collId, shortId)
row, err := tablesDB.GetRow(dbId, tableId, shortId)

if err != nil {
Context.Error(err)
return Context.Res.Text("URL not found", Context.Res.WithStatusCode(404))
}

var responseBody ResponseBody
document.Decode(&responseBody)
row.Decode(&responseBody)

return Context.Res.Redirect(responseBody.LongUrl, Context.Res.WithStatusCode(302))
}
Expand All @@ -358,7 +358,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`, `columns.read`, `columns.write`, `rows.read`, `rows.write`,

# More resources

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ The second prompt gives the model a language, a framework, specific libraries, e

The developers getting the most out of AI tools aren't the ones who use it the most. They're the ones who've learned to communicate precisely. Prompting is a communication skill. The better you get at it, the more leverage you get from every AI tool in your workflow.

If you're building applications with AI features and want a backend that keeps up, [Appwrite](https://appwrite.io) gives you auth, databases, storage, and serverless functions in one platform. Appwrite also works with the [Model Context Protocol](/docs/tooling/mcp), so your AI assistant can interact directly with your backend, creating collections, querying data, and managing functions through natural language. It's a practical way to pair better prompting with better tooling.
If you're building applications with AI features and want a backend that keeps up, [Appwrite](https://appwrite.io) gives you auth, databases, storage, and serverless functions in one platform. Appwrite also works with the [Model Context Protocol](/docs/tooling/mcp), so your AI assistant can interact directly with your backend, creating tables, querying data, and managing functions through natural language. It's a practical way to pair better prompting with better tooling.

# More resources
- [Appwrite MCP server](/docs/tooling/mcp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ faqs:
- question: "How does Appwrite help with GDPR compliance?"
answer: "Appwrite hashes passwords with Argon2, encrypts data in transit over TLS, supports MFA on [Appwrite Auth](/docs/products/auth), and lets you delete user accounts (and their data) on request. Appwrite Cloud also offers EU regions so personal data of EU users can stay within the EU, simplifying data transfer compliance."
- question: "What is the right to be forgotten and how do I implement it?"
answer: "Users have the right to request deletion of their personal data. In Appwrite, you can delete a user via the Users API, which removes their identity record. You still need to delete documents, files, and other user-tied records in your collections and buckets, which you can do in an [Appwrite Function](/docs/products/functions) triggered by the user deletion event."
answer: "Users have the right to request deletion of their personal data. In Appwrite, you can delete a user via the Users API, which removes their identity record. You still need to delete rows, files, and other user-tied records in your tables and buckets, which you can do in an [Appwrite Function](/docs/products/functions) triggered by the user deletion event."
- question: "Do I need a Data Processing Agreement (DPA) with my backend provider?"
answer: "Yes. If your backend provider processes personal data on your behalf, GDPR requires a DPA. Appwrite Cloud customers can request a DPA covering Appwrite's role as a data processor. Self-hosted Appwrite means you are processor and controller for your own data."
- question: "How quickly must I report a data breach under GDPR?"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ faqs:
- question: "What is Claude Projects?"
answer: "Projects is a feature in Claude that lets the model retain context across sessions. You can give it background about your codebase, your team's conventions, and the constraints you work under, and it carries that forward into every conversation inside the project. This removes the repetitive setup of re-explaining your stack at the start of each chat."
- question: "What is the Model Context Protocol (MCP) in Claude?"
answer: "MCP gives Claude the ability to connect to external systems like databases, APIs, and services, and actually act on them rather than just describing what it would do. With the Appwrite MCP server, for example, Claude can create users, query collections, manage storage, and trigger functions directly inside an Appwrite project."
answer: "MCP gives Claude the ability to connect to external systems like databases, APIs, and services, and actually act on them rather than just describing what it would do. With the Appwrite MCP server, for example, Claude can create users, query tables, manage storage, and trigger functions directly inside an Appwrite project."
- question: "Can Claude analyze images and generate code from them?"
answer: "Yes. Claude understands images and can take screenshots of UIs, mockups, diagrams, or schemas drawn on a whiteboard, then describe what it sees and generate code to match. This is useful for design-to-code workflows, where a Figma screenshot or screen recording of a broken UI can produce a matching layout or pinpoint where the CSS is off."
- question: "What is Claude Code?"
Expand Down Expand Up @@ -64,7 +64,7 @@ It's worth trying for tasks that would normally take you an afternoon of focused

The **Model Context Protocol (MCP)** gives Claude the ability to connect to external systems, your database, your APIs, your services, and actually interact with them. Not just describe what it would do, but do it.

With the [Appwrite MCP server](/docs/tooling/mcp), for example, Claude can create users, query collections, manage storage, and trigger functions directly inside your Appwrite project. You describe what you need in plain language, and Claude handles the operation. No copy-pasting API responses. No switching tabs to check the console.
With the [Appwrite MCP server](/docs/tooling/mcp), for example, Claude can create users, query tables, manage storage, and trigger functions directly inside your Appwrite project. You describe what you need in plain language, and Claude handles the operation. No copy-pasting API responses. No switching tabs to check the console.

This is what [agentic AI](/blog/post/agentic-ai-vs-generative-ai) actually looks like in practice: the model connected to real systems, taking real actions. If you've only ever used Claude in a chat window, adding MCP changes the category of work it can handle.

Expand Down
Loading
Loading