.claude/skills/ts-appwrite/SKILL.md
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.
npx skillsauth add eliferjunior/Claude appwriteInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
# One-command Docker setup
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
# Or with Docker Compose (production)
curl -o docker-compose.yml https://appwrite.io/install/compose
curl -o .env https://appwrite.io/install/env
docker compose up -d
# Console: http://localhost/console
# Create your first project in the console UI
// lib/appwrite.js — Client SDK setup and authentication
import { Client, Account, ID } from 'appwrite'
const client = new Client()
.setEndpoint('http://localhost/v1') // Appwrite API endpoint
.setProject('your-project-id') // from console
const account = new Account(client)
// Sign up
async function signUp(email, password, name) {
const user = await account.create(ID.unique(), email, password, name)
// Auto-login after signup
await account.createEmailPasswordSession(email, password)
return user
}
// Login
async function login(email, password) {
return await account.createEmailPasswordSession(email, password)
}
// OAuth login (Google, GitHub, Apple, etc.)
account.createOAuth2Session('google', 'http://localhost:3000/callback', 'http://localhost:3000/login')
// Get current user
async function getCurrentUser() {
try {
return await account.get()
} catch {
return null // not logged in
}
}
// Logout
async function logout() {
await account.deleteSession('current')
}
// lib/database.js — CRUD operations with Appwrite Databases
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'
// Create document
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(),
})
}
// List with filters and pagination
async function listPublishedPosts(page = 1, limit = 10) {
return await databases.listDocuments(DB_ID, COLLECTION_ID, [
Query.equal('status', 'published'),
Query.orderDesc('created_at'),
Query.limit(limit),
Query.offset((page - 1) * limit),
])
}
// Update
async function publishPost(postId) {
return await databases.updateDocument(DB_ID, COLLECTION_ID, postId, {
status: 'published',
published_at: new Date().toISOString(),
})
}
// Delete
async function deletePost(postId) {
await databases.deleteDocument(DB_ID, COLLECTION_ID, postId)
}
// lib/storage.js — Upload and manage files
import { Client, Storage, ID } from 'appwrite'
const storage = new Storage(new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id'))
const BUCKET_ID = 'uploads'
// Upload file
async function uploadFile(file) {
/**
* Upload a file to Appwrite storage.
* Args:
* file: File object from <input type="file"> or drag-and-drop
*/
return await storage.createFile(BUCKET_ID, ID.unique(), file)
}
// Get file URL (with transformations for images)
function getFilePreview(fileId, width = 400, height = 300) {
return storage.getFilePreview(BUCKET_ID, fileId, width, height)
}
// Download file
function getFileDownload(fileId) {
return storage.getFileDownload(BUCKET_ID, fileId)
}
// Delete file
async function deleteFile(fileId) {
await storage.deleteFile(BUCKET_ID, fileId)
}
// functions/on-order-created/src/main.js — Serverless function triggered by database event
// Deploy via Appwrite CLI: appwrite deploy function
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}`)
// Send notification, update inventory, etc.
const users = new Users(client)
const user = await users.get(order.user_id)
log(`Order by: ${user.email}`)
return res.json({ success: true, orderId: order.$id })
}
// hooks/useRealtime.js — Subscribe to live database changes
import { Client } from 'appwrite'
const client = new Client()
.setEndpoint('http://localhost/v1')
.setProject('your-project-id')
// Subscribe to changes in a collection
const unsubscribe = client.subscribe(
'databases.main.collections.messages.documents',
(response) => {
// Fires on create, update, delete
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.$id)
}
}
)
// Cleanup
// unsubscribe()
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:
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:
read("any"), write("user:USER_ID")) to control document access. Default is owner-only — explicitly set permissions for public content.development
Expert guidance for Fireworks AI, the platform for running open-source LLMs (Llama, Mixtral, Qwen, etc.) with enterprise-grade speed and reliability. Helps developers integrate Fireworks' inference API, fine-tune models, and deploy custom model endpoints with function calling and structured output support.
development
Convert any website into clean, structured data with Firecrawl — API-first web scraping service. Use when someone asks to "turn a website into markdown", "scrape website for LLM", "Firecrawl", "extract website content as clean text", "crawl and convert to structured data", or "scrape website for RAG". Covers single-page scraping, full-site crawling, structured extraction, and LLM-ready output.
tools
Expert guidance for Firebase, Google's platform for building and scaling web and mobile applications. Helps developers set up authentication, Firestore/Realtime Database, Cloud Functions, hosting, storage, and analytics using Firebase's SDK and CLI.
development
When the user needs to build file upload functionality for a web application. Use when the user mentions "file upload," "image upload," "upload endpoint," "multipart upload," "presigned URL," "S3 upload," "file validation," "upload to cloud storage," or "accept user files." Handles upload endpoints, file validation (type, size, magic bytes), cloud storage integration, and upload status tracking. For image/video processing after upload, see media-transcoder.