Cloudflare Deployment
Overview
The application runs on Cloudflare Workers (via the @opennextjs/cloudflare adapter) and uses:
- D1 for relational storage and sync
- KV for sessions, metadata, and billing state
- R2 for snapshots and changelog artifacts
Prerequisites
- Node.js LTS
- Wrangler CLI (
npm install -g wrangler) - A Cloudflare account with Pages and Workers enabled
Step 1 — Provision cloud services
Create the required Cloudflare services in your account:
- D1 database — create via the Cloudflare dashboard or Wrangler CLI
- KV namespace — create via dashboard or Wrangler CLI
- R2 bucket — create via dashboard or Wrangler CLI
Note the IDs for each resource — you will need them in wrangler.jsonc.
Step 2 — Configure bindings
Update wrangler.jsonc with your resource IDs:
{
"d1_databases": [
{ "binding": "BOARDS_DB", "database_name": "sticky-notes-db", "database_id": "YOUR_D1_ID" }
],
"kv_namespaces": [
{ "binding": "AUTH_KV", "id": "YOUR_KV_ID" }
],
"r2_buckets": [
{ "binding": "BOARD_STORAGE", "bucket_name": "YOUR_R2_BUCKET_NAME" }
]
}Step 3 — Apply D1 migrations
Run all database migrations in order:
npx wrangler d1 migrations apply sticky-notes-db --remoteMigrations are in the migrations/ folder. All must be applied for the app to function correctly.
Step 4 — Set runtime secrets
Use Wrangler to set all production secrets. Never put secrets in wrangler.jsonc or any committed file.
npx wrangler secret put GOOGLE_GENERATIVE_AI_API_KEY
npx wrangler secret put SMTP2GO_API_KEY
npx wrangler secret put STRIPE_SECRET_KEY
npx wrangler secret put STRIPE_WEBHOOK_SECRET
npx wrangler secret put STRIPE_PRO_PRICE_IDStep 5 — Deploy
npm run build
npm run deployThe deploy script runs pre-deploy validation checks before deploying to Cloudflare Workers.
Step 6 — Configure custom domain
In the Cloudflare dashboard:
- Go to Workers & Pages → your worker → Settings → Domains & Routes.
- Add your production domain (e.g.
epicsandstories.com). - Ensure DNS is configured with the appropriate CNAME or A record.
Post-deploy verification checklist
| Check | How to verify |
|---|---|
| Auth flow | Open the app, request an OTP, verify it, confirm you reach the dashboard |
| Board creation | Create a new board from the dashboard |
| Note create and edit | Add a note, edit it, reload — confirm it persists |
| Export/import | Export the board as Markdown; import it back |
| Sync | Open the board in two browser tabs; edit in one, confirm it appears in the other |
| AI (if enabled) | Send a message in the AI panel; confirm a response streams back |
| Billing webhook | Check Stripe dashboard → Webhooks → confirm recent events delivered |
Environment handling summary
| Secret type | Where it lives |
|---|---|
| Local dev values | .env.local (never committed) |
| Production runtime | wrangler secret (encrypted in Cloudflare) |
| Public config | next.config.mjs / wrangler.jsonc (safe to commit, no secrets) |
See also
- Local Development — Local dev setup
- Tech Stack — All services used
- Authentication and Access — Session and OTP model