Per-Tenant Deployment
Run all commands from the repo root. Replace
<tenant>with the tenant's slug (lowercase, hyphen-separated).
1. Install
bun install
2. Create the D1 database
bunx wrangler d1 create <tenant>-edgepress
Copy the returned database_id into wrangler.jsonc:
"d1_databases": [
{
"binding": "DB",
"database_name": "<tenant>-edgepress",
"database_id": "<paste-here>",
"migrations_dir": "./drizzle"
}
]
The binding name must be
DBfor every tenant — that's the contract the code reads. Onlydatabase_nameanddatabase_idchange per tenant.
3. Create (or pick) an R2 bucket for media
bunx wrangler r2 bucket create <your-bucket>
One bucket can be shared across all tenants — uploads land under edgepress/<CLIENT_SLUG>/... so each tenant has its own folder.
4. Set tenant vars in wrangler.jsonc
"routes": [
{ "pattern": "<tenant>.example.com", "custom_domain": true }
],
"vars": {
"CLIENT_DOMAIN": "<tenant>.example.com",
"CLIENT_SLUG": "<tenant>",
"CLIENT_FONT": "Inter",
"MEDIA_PUBLIC_BASE": "https://media.example.com",
"EMAIL_PROVIDER": "RESEND"
},
"r2_buckets": [
{ "binding": "MEDIA", "bucket_name": "<your-bucket>" }
]
5. Apply database migrations
bunx wrangler d1 migrations apply <tenant>-edgepress --local # local
bunx wrangler d1 migrations apply <tenant>-edgepress --remote # production
To regenerate the SQL after a schema change: bun run db:generate.
6. Set secrets
bunx wrangler secret put MASTER_ADMIN_KEY # always
# If EMAIL_PROVIDER=RESEND
bunx wrangler secret put RESEND_API_KEY
# If EMAIL_PROVIDER=GMAIL
bunx wrangler secret put GMAIL_USER
bunx wrangler secret put GMAIL_APP_PASSWORD
7. Regenerate types and deploy
bun run cf-typegen # refresh worker-configuration.d.ts
bun run deploy # astro build + wrangler deploy
8. Configure brand visuals via admin
Open https://<tenant>.example.com/admin/login, paste your MASTER_ADMIN_KEY, then navigate to /admin/settings and fill in brand name, tagline, logo URL, favicon URL, theme primary color, and email From-address.
Saved values take effect immediately on the next page render.