Docs

Self-host quickstart.

Quoda runs entirely on Cloudflare primitives. You can have it running locally in a couple of minutes, then deploy the same code to your own account.

Requirements

Node 18+ and a Cloudflare account (only needed to deploy — local dev needs no external services). Everything else is installed by npm.

Local development

Clone the repo, install dependencies, apply the local D1 migrations, and start the dev server. The dev command also builds the design tokens and bundles the client islands.

git clone https://github.com/canerdogan/quoda
cd quoda
npm install
npm run migrate:local
npm run dev

Wrangler serves the app at http://localhost:8787 with local D1, KV, and R2 — no cloud account required. Sign-in emails are printed to the dev console as a clearly labelled [DEV MAGIC LINK] banner.

Create D1, KV & R2

To deploy, create the bindings Quoda expects, then copy the returned ids into wrangler.jsonc. Quoda needs one D1 database, three KV namespaces, and one R2 bucket.

# D1 database (binding: DB)
wrangler d1 create quoda

# KV namespaces (bindings: SCAN_COUNTERS, RATE_LIMIT, SESSION_CACHE)
wrangler kv namespace create SCAN_COUNTERS
wrangler kv namespace create RATE_LIMIT
wrangler kv namespace create SESSION_CACHE

# R2 bucket (binding: ASSETS_BUCKET)
wrangler r2 bucket create quoda-assets

Apply the migrations to your remote database once it exists:

npm run migrate:remote

Deploy with wrangler

The deploy script builds tokens, bundles islands, and ships the Worker in one step.

npm run deploy

That runs build:tokens && build:client && wrangler deploy. After it finishes, your Worker is live on your workers.dev subdomain or your custom domain.

Environment variables

Set APP_URL to your deployed origin so generated short links and hosted pages resolve correctly. For real sign-in emails, add a RESEND_API_KEY; without it, magic links are logged to the console (never silently dropped).

# wrangler.jsonc -> vars
"vars": { "APP_URL": "https://your-domain.com" }

# secret (optional — enables real email delivery)
wrangler secret put RESEND_API_KEY

For local dev, copy .dev.vars.example to .dev.vars and fill in what you need.