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 devWrangler 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-assetsApply the migrations to your remote database once it exists:
npm run migrate:remoteDeploy with wrangler
The deploy script builds tokens, bundles islands, and ships the Worker in one step.
npm run deployThat 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_KEYFor local dev, copy .dev.vars.example to .dev.vars and fill in what you need.