Appwrite Setup
Setting up and configuring Appwrite database, authentication, and storage for BISO Sites.
Appwrite Setup
Appwrite is the backend-as-a-service that powers BISO Sites. This guide covers setup and configuration.
Before you start
- Decide who owns Appwrite credentials (IT manager + backup person).
- Confirm you have access to the current project ID, endpoint, and API key from the password vault.
- Export the latest
database.jsonfiles fromapps/webandapps/adminfor reference.
Choose your hosting option
- Sign up at cloud.appwrite.io.
- Create a project named BISO Sites.
- Note the Project ID and Endpoint for your `.env.local` files.
Setup checklist
Create project + database
In the Appwrite console, create the app database and note its ID. Use the database.json files in apps/web and apps/admin as your schema reference.
Import collections & storage buckets
Manually create collections and buckets (events, product-images, documents) with the permissions outlined below. Double-check indexes for orders, events, and translations.
Configure auth providers
Enable Magic Link for the web app and Microsoft OAuth (BISO tenant) for the admin app. Test each flow once.
Issue API keys + env vars
Generate a server API key (APPWRITE_API_KEY) with databases, users, and storage scopes. Update .env.local files and the vault entry immediately.
Project Configuration
Create Database
- Go to Databases in Appwrite Console
- Create a new database
- Note the Database ID
Create Collections
Both web and admin apps include database.json files with collection schemas:
# Import collections from database.json
# (Manual process via Appwrite Console)Key Collections:
users- User profilesposts- News/blog postsevents- Eventsproducts- E-commerce productsorders- Order trackingdepartments- Units/departmentsmembership_applications- Member data
Set Up Storage
-
Create storage buckets:
events- Event imagesproduct-images- Product imagesdocuments- File uploads
-
Configure permissions:
- Read:
any(public access) - Write:
users(authenticated only)
- Read:
Configure Authentication
Web App (Public Site):
- Enable Magic Link authentication (passwordless email link)
- Optional: Enable OAuth Microsoft provider for BI Business School accounts
- Set session length (default: 365 days)
Admin App:
- Enable OAuth Microsoft provider (required)
- Configure BISO Azure tenant
- Admin-only access via OAuth
- Web App: Magic Link (primary) + optional Microsoft OAuth (for BI students)
- Admin App: Microsoft OAuth only (BISO tenant)
Create API Keys
- Go to Settings → API Keys
- Create server API key with scopes:
databases.*users.*storage.*
- Note the API key (use as
APPWRITE_API_KEY)
Database Schema
BISO Sites uses a custom TablesDB implementation with these methods:
getRow(database, collection, id)- Get single documentlistRows(database, collection, queries)- List documents with queriescreateRow(database, collection, id, data)- Create documentupdateRow(database, collection, id, data)- Update documentdeleteRow(database, collection, id)- Delete document
All collections are in database: app
All server actions use 'app' as the database name: db.listRows('app', 'collection_name', queries)
Core Collections
Key Collections:
content_translations- Localized content (events, products, pages)webshop_products- Product datacart_reservations- Temporary cart items (10 min expiry)orders- Orders and transactionscampus- Campus/location datacampus_data- Campus-specific settingscampus_metadata- Additional campus infodepartments- Units/departments/clubsfunding_programs- BI Fondet funding programsvarsling_settings- Safety reporting settingsuser- Extended user profile data
Content Translation System
The content_translations collection stores all translatable content:
{
content_id: string; // Reference to actual content
content_type: 'event' | 'product' | 'page' | 'post';
locale: 'en' | 'no';
title: string;
description: string;
event_ref: Events; // Relationship to events table
product_ref: WebshopProducts; // Relationship to webshop_products
}Usage example:
// Get events with translations
const response = await db.listRows<ContentTranslations>(
'app',
'content_translations',
[
Query.equal('content_type', 'event'),
Query.equal('locale', 'en'),
Query.select(['content_id', '$id', 'locale', 'title', 'event_ref.*'])
]
);Cart Reservations
Temporary stock reservations with automatic expiration:
{
product_id: string;
user_id: string;
quantity: number;
expires_at: datetime; // Auto-expires after 10 minutes
}Orders
{
status: 'pending' | 'paid' | 'authorized' | 'cancelled' | 'failed';
currency: string;
subtotal: number;
discount_total: number;
total: number;
buyer_name: string;
buyer_email: string;
buyer_phone: string;
membership_applied: boolean;
member_discount_percent: number;
items_json: string; // JSON array of order items
vipps_session_id: string;
vipps_payment_link: string;
campus_id?: string;
}Database Files
Use the included database.json files as reference:
apps/web/database.jsonapps/admin/database.json
Appwrite collections must be created manually via console. Use the database.json files as a reference for attributes, indexes, and relationships.
Verify everything works
Health check
Load the Appwrite console → Health tab. Ensure all services show green. Restart containers if needed.
Web app smoke test
Run bun run dev --filter=web, sign up via Magic Link, and confirm a user document appears in the users collection.
Admin login test
Run bun run dev --filter=admin, authenticate via Microsoft OAuth, and confirm your labels include admin or editor.
Order lifecycle
Place a test checkout (Vipps test mode) and ensure an orders document transitions from PENDING → PAID via webhook.
Security Configuration
Platform Configuration
Add your domains to allowed platforms:
- Go to Settings → Platforms
- Add Web Platform:
- Name: Web App
- Hostname:
yourdomain.com(orlocalhost:3000for dev)
- Add Admin Platform:
- Name: Admin App
- Hostname:
admin.yourdomain.com(orlocalhost:3001for dev)
CORS Configuration
Configure allowed origins in Appwrite settings.
Backup & Restore
# Backup (if self-hosted)
docker exec appwrite backup-database
# Restore
docker exec appwrite restore-database backup.sql