Configuration
Every deploy setting, Worker binding and secret, and the deploy token permissions.
Deploy-time settings (alchemy.run.ts)
Read from the environment of alchemy deploy, usually .env.local (gitignored) through --env-file.
| Variable | Default | Purpose |
|---|---|---|
CLOUDFLARE_API_TOKEN |
— (required) | Deploy token, see permissions below |
CLOUDFLARE_ACCOUNT_ID |
— (required) | Target account |
EMITKIT_DOMAIN |
emitkit.com |
Zone that serves every hostname |
EMITKIT_SITE_HOST |
$EMITKIT_DOMAIN |
Marketing hostname |
EMITKIT_APP_HOST |
app.$EMITKIT_DOMAIN |
PWA + auth + RPC hostname |
EMITKIT_API_HOST |
api.$EMITKIT_DOMAIN |
Public API hostname |
EMITKIT_REDIRECT_HOSTS |
www.$EMITKIT_DOMAIN |
Comma-separated hosts that 301 to the site; empty for none |
EMITKIT_DOCS_HOST |
docs.$EMITKIT_DOMAIN |
Old docs hostname: attached to the Worker and 301’d to <site>/docs/<same path>; empty for none |
EMITKIT_MAIL_DOMAIN |
mail.$EMITKIT_DOMAIN |
Email Sending subdomain (DKIM/SPF records are created automatically) |
EMITKIT_EMAIL_FROM |
noreply@$EMITKIT_MAIL_DOMAIN |
Sender of auth and invitation email |
EMITKIT_WORKER_NAME |
emitkit |
Worker, D1 (<name>-db) and queue (<name>-events) names |
EMITKIT_AE_DATASET |
emitkit_events |
Analytics Engine dataset |
EMITKIT_ALLOW_SIGNUP |
true |
false disables self-service sign-up (invitations still work) |
EMITKIT_VAPID_SUBJECT |
mailto:hi@$EMITKIT_DOMAIN |
Contact for push services |
EMITKIT_PARSEW_KEY |
empty | Publishable Parsew key (pk_…) for brand icons (projects by their website, users by their email domain, links). It is public: the browser puts it in image URLs, so restrict it to the app origin in the Parsew dashboard. Empty shows initials and dots instead. Locally, set PARSEW_PUBLISHABLE_KEY in .dev.vars. |
Build-time settings (pnpm build)
| Variable | Default | Purpose |
|---|---|---|
DOCS_SITE_URL |
https://emitkit.com |
Origin used for the docs’ canonical URLs, sitemap and Open Graph images (docs/blume.config.ts). Set it to your site origin when self-hosting. The docs are always served at /docs on the site host. |
Deploy token permissions
Create a custom account API token scoped to the account and the zone:
- Account: Workers Scripts Edit, D1 Edit, Queues Edit, Workers AI Read, Email Sending Edit, Account API Tokens Edit, Account Settings Read, Secrets Store Edit.
- Zone: Zone Read, DNS Edit, Workers Routes Edit, SSL and Certificates Edit, Single Redirect Edit.
“Account API Tokens Edit” lets the stack mint the Worker’s read-only Analytics Engine token (<name>-analytics-read). “Secrets Store Edit” lets Alchemy reach its state store, whose bearer token lives in the account Secrets Store.
Worker variables and secrets
The stack sets these on the Worker. You don’t set them yourself.
| Binding / variable | Kind | Source |
|---|---|---|
DB |
D1 | Cloudflare.D1.Database, migrations from ./migrations |
EVENTS_DATASET |
Analytics Engine | Cloudflare.AnalyticsEngine.Dataset |
EVENTS_QUEUE |
Queue producer (+ consumer) | Cloudflare.Queues.Queue |
EMAIL |
send_email |
restricted to EMITKIT_EMAIL_FROM |
AI |
Workers AI | optional, emoji suggestions |
ASSETS |
static assets | ./dist/client |
APP_URL, API_URL, SITE_URL |
text | from the hosts above |
EVENT_STORE |
text | analytics-engine in production |
ALLOW_SIGNUP, EMAIL_FROM, VAPID_SUBJECT, AE_DATASET, CF_ACCOUNT_ID |
text | from settings |
VAPID_PUBLIC_KEY |
text | derived from the generated VAPID private key |
BETTER_AUTH_SECRET |
secret | Alchemy.Random (32 bytes), kept in Alchemy state |
VAPID_PRIVATE_KEY |
secret | Alchemy.Random (P-256 scalar), kept in Alchemy state |
CF_ANALYTICS_TOKEN |
secret | account token minted by the stack (Account Analytics Read) |
The Worker validates its configuration at startup (src/server/platform/config.ts). A missing or malformed value fails every request with a logged ConfigError.
Local development (wrangler.jsonc + .dev.vars)
wrangler.jsonc declares the same bindings for @cloudflare/vite-plugin with EVENT_STORE=d1 and *.localhost:5173 URLs. Local secrets go in the gitignored .dev.vars:
BETTER_AUTH_SECRET=<at least 32 random characters>
VAPID_PRIVATE_KEY=<base64url P-256 private scalar>
VAPID_PUBLIC_KEY in wrangler.jsonc must be the matching public key. Development shows how to generate a pair.