| name | appwrite |
| description | Build backends with Appwrite — open-source Backend-as-a-Service. Use when a user asks to set up user authentication, manage a database without writing backend code, handle file storage and uploads, add realtime subscriptions, set up cloud functions, build a mobile or web app backend, replace Firebase with an open-source alternative, or self-host a BaaS platform. Covers auth, databases, storage, functions, realtime, and SDK integration for web, mobile, and server-side. |
| license | Apache-2.0 |
| compatibility | Docker (self-hosted) or Appwrite Cloud |
| metadata | {"author":"terminal-skills","version":"1.0.0","category":"development","tags":["appwrite","baas","backend","auth","database","storage","serverless"]} |
Appwrite
Overview
Appwrite is an open-source Backend-as-a-Service (BaaS) providing authentication, databases, file storage, cloud functions, and realtime subscriptions — all through a single self-hosted Docker deployment. It's the open-source alternative to Firebase, with SDKs for web (JavaScript), mobile (Flutter, Swift, Kotlin), and server-side (Node.js, Python, PHP). This skill covers self-hosting setup, authentication, database operations, file storage, serverless functions, and realtime subscriptions.
Instructions
Step 1: Self-Hosted Deployment
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)/appwrite:/usr/src/code/appwrite:rw" \
--entrypoint="install" \
appwrite/appwrite:latest
curl -o docker-compose.yml https://appwrite.io/install/compose
curl -o .env https://appwrite.io/install/env
docker compose up -d
Step 2: Authentication
import { Client, Account, ID } from 'appwrite'
const client = new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id')
const account = new Account(client)
async function signUp(email, password, name) {
const user = await account.create(ID.unique(), email, password, name)
await account.createEmailPasswordSession(email, password)
return user
}
async function login(email, password) {
return await account.createEmailPasswordSession(email, password)
}
account.createOAuth2Session('google', 'http://localhost:3000/callback', 'http://localhost:3000/login')
() {
{
account.()
} {
}
}
() {
account.()
}
Step 3: Database Operations
import { Client, Databases, ID, Query } from 'appwrite'
const client = new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id')
const databases = new Databases(client)
const DB_ID = 'main'
const COLLECTION_ID = 'posts'
async function createPost(title, content, authorId) {
return await databases.createDocument(DB_ID, COLLECTION_ID, ID.unique(), {
title,
content,
author_id: authorId,
status: 'draft',
created_at: new Date().toISOString(),
})
}
async function listPublishedPosts(page = 1, limit = ) {
databases.(, , [
.(, ),
.(),
.(limit),
.((page - ) * limit),
])
}
() {
databases.(, , postId, {
: ,
: ().(),
})
}
() {
databases.(, , postId)
}
Step 4: File Storage
import { Client, Storage, ID } from 'appwrite'
const storage = new Storage(new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id'))
const BUCKET_ID = 'uploads'
async function uploadFile(file) {
return await storage.createFile(BUCKET_ID, ID.unique(), file)
}
function getFilePreview(fileId, width = 400, height = 300) {
return storage.getFilePreview(BUCKET_ID, fileId, width, height)
}
function getFileDownload(fileId) {
return storage.getFileDownload(BUCKET_ID, fileId)
}
() {
storage.(, fileId)
}
Step 5: Cloud Functions
import { Client, Databases, Users } from 'node-appwrite'
export default async ({ req, res, log, error }) => {
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT)
.setProject(process.env.APPWRITE_PROJECT)
.setKey(process.env.APPWRITE_API_KEY)
const payload = JSON.parse(req.body)
const order = payload.$id ? payload : payload.data
log(`New order: ${order.$id}, total: ${order.total}`)
const users = new Users(client)
const user = await users.get(order.user_id)
log(`Order by: ${user.email}`)
return res.json({ success: , : order. })
}
Step 6: Realtime Subscriptions
import { Client } from 'appwrite'
const client = new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id')
const unsubscribe = client.subscribe(
'databases.main.collections.messages.documents',
(response) => {
const event = response.events[0]
const document = response.payload
if (event.includes('.create')) {
console.log('New message:', document)
} else if (event.includes('.update')) {
console.log('Updated:', document)
} else if (event.includes('.delete')) {
console.log('Deleted:', document.)
}
}
)
Examples
Example 1: Build a full-stack app with auth, database, and file uploads
User prompt: "I want to build a recipe sharing app. Users sign up, post recipes with photos, and browse others' recipes. Use an open-source backend I can self-host."
The agent will:
- Deploy Appwrite with Docker Compose.
- Set up authentication with email/password and Google OAuth.
- Create database collections: recipes (title, ingredients, steps, author, image_id), users.
- Configure file storage bucket for recipe photos with size limits.
- Build a Next.js frontend using the Appwrite Web SDK.
- Set permissions so users can only edit their own recipes but read all published ones.
Example 2: Replace Firebase with a self-hosted alternative
User prompt: "We're using Firebase but want to self-host for data sovereignty. Migrate our auth, Firestore, and storage to something open-source."
The agent will:
- Deploy Appwrite on the target server.
- Export users from Firebase Auth, import to Appwrite.
- Map Firestore collections to Appwrite database collections.
- Migrate storage files using the Appwrite Server SDK.
- Update frontend code to use Appwrite SDK (similar API surface to Firebase).
Guidelines
- Appwrite runs as a set of Docker containers (API, worker, database, cache, etc.). It needs ~2GB RAM minimum for comfortable operation. Use Docker Compose for managing the full stack.
- Configure database indexes in the Appwrite console for fields you filter or sort on — queries on unindexed fields will be slow at scale.
- Use Appwrite's permission system (
read("any"), write("user:USER_ID")) to control document access. Default is owner-only — explicitly set permissions for public content.
- Server SDKs (Node.js, Python) use API keys and bypass permissions — use them for admin operations, cron jobs, and cloud functions. Client SDKs enforce user permissions.
- Appwrite handles auth tokens, session management, and OAuth flows internally. You don't need to manage JWTs or refresh tokens manually.