appwrite) runs in the browser for auth and file operations initiated by the user. The server SDK (node-appwrite) runs in Next.js API routes for privileged operations that need a full API key.
Authentication
Prism supports two sign-in methods, both backed by Appwrite’sAccount service.
- Email and password
- Google OAuth
Registration calls Sign in is a single call:
account.create to create the user record, then immediately opens a session with account.createEmailPasswordSession. After a plan label is assigned (see Plan system), the session is deleted — users must sign in explicitly rather than being dropped straight into the app.Plan system
Prism’s plan tiers are stored as Appwrite user labels. Labels are strings attached to the user object and readable viauser.labels. The server-side /api/users/assign-plan route uses the node-appwrite SDK with a full API key to set labels — the client SDK cannot modify labels.
Plan tiers
| Plan | Storage | Documents |
|---|---|---|
free | 5 GB | 10 |
pro | 15 GB | 500 |
enterprise | Unlimited | Unlimited |
admin | Unlimited | Unlimited |
Reading the plan
getUserPlan inspects user.labels and returns the highest matching tier. Labels are checked in priority order: admin → enterprise → pro → free. If the user has no plan label (for example, a legacy account), the function defaults to free.
getCurrentUser in lib/appwrite.ts also self-heals: if the returned user has no plan label, it calls /api/users/assign-plan automatically to assign the free label, then re-fetches the user.
Upgrading a user’s plan requires setting the appropriate Appwrite label on the user account via the server-side API. There is no client-facing upgrade flow built into
lib/appwrite.ts — plan changes are an administrative operation.File storage
All documents are stored in a single Appwrite Storage bucket identified byNEXT_PUBLIC_APPWRITE_BUCKET_ID. Each file gets per-user read, write, and delete permissions at upload time, so no user can access another user’s files even within the same bucket.
uploadDocument
ID.unique() and calls storage.createFile with explicit permission strings:
onProgress is provided, it is called with a percentage (0–100) derived from chunksUploaded / chunksTotal. After upload completes, the caller is responsible for triggering indexing via /api/documents/index.
Other file operations
| Function | Description |
|---|---|
listDocuments | Lists all files in the bucket visible to the current session |
deleteDocument | Deletes the file from Storage, then calls /api/documents/delete to remove Qdrant chunks |
getFilePreview | Returns a preview URL via storage.getFilePreview |
downloadDocument | Returns a download URL via storage.getFileDownload |
renameDocument | Calls /api/documents/rename (server-side rename via node-appwrite) |
Session management
getCurrentUser calls account.get() to retrieve the active session’s user object. It returns null if no session exists — no error is thrown. Components use this to determine the authentication state on mount.
Logging out deletes only the current session: