Skip to content

Deploy to Cloudflare ​

A turnkey, ordered runbook for provisioning and deploying the CaptureFlow web backend (apps/web) to your own Cloudflare account. Every command runs from the repo root.

This mirrors DEPLOY.md in the repo, which is the canonical source if the two ever drift.

1. Log in to Cloudflare ​

bash
pnpm --filter @captureflow/web exec wrangler login
pnpm --filter @captureflow/web exec wrangler whoami   # confirm

2. Create the D1 database ​

The name must be captureflow — it matches wrangler.jsonc and the db:* scripts.

bash
pnpm --filter @captureflow/web exec wrangler d1 create captureflow

Wrangler prints a database_id. Paste it into apps/web/wrangler.jsonc → d1_databases[0].database_id, replacing the placeholder. Then apply migrations to the remote database:

bash
pnpm --filter @captureflow/web db:apply:remote

(That runs wrangler d1 migrations apply captureflow --remote; migrations live in apps/web/migrations/.)

3. Create the R2 bucket ​

The name must be captureflow-recordings.

bash
pnpm --filter @captureflow/web exec wrangler r2 bucket create captureflow-recordings

Prefixes used inside the bucket: videos/, posters/, screenshots/.

3b. Create the transcription queue ​

Transcripts are made by Whisper on Workers AI, one call per uploaded audio chunk, fed through a queue the Worker consumes itself. The queue name must be captureflow-transcription; the AI binding needs no setup.

bash
pnpm --filter @captureflow/web exec wrangler queues create captureflow-transcription

Workers AI includes 10,000 neurons a day for free, about three and a half hours of audio; beyond that it bills per minute on the Workers Paid plan. Queues need the Workers Paid plan as well.

4. Set secrets ​

Secrets are never stored in wrangler.jsonc. The only required one is the auth secret:

bash
openssl rand -hex 32 | pnpm --filter @captureflow/web exec wrangler secret put BETTER_AUTH_SECRET

An optional email (Resend) secret for workspace invites is covered in Configuration & env. Skip it to run with invite-emails disabled (invite links can still be shared manually).

5. Review public vars ​

The non-secret vars already live in apps/web/wrangler.jsonc. If you use a domain other than captureflow.dev, update them now (NEXT_PUBLIC_* site URLs, R2_PUBLIC_BASE_URL, BETTER_AUTH_URL, APP_DEEP_LINK_SCHEME). Full table in Configuration & env.

WARNING

NEXT_PUBLIC_* vars are inlined into the client bundle at build time — they are public by design. Never put a secret behind a NEXT_PUBLIC_ name.

Any address other than captureflow.dev runs as a self-hosted instance, with no storage cap or billing. For an internal tool, also add "ALLOWED_EMAIL_DOMAINS": "yourcompany.com", and set the Google or GitHub secrets so people can sign in. See Private company instance.

6. Bind your domain(s) ​

  • captureflow.dev → the captureflow-web Worker. Add a custom domain in the dashboard (Workers & Pages → captureflow-web → Domains & Routes), or add routes to wrangler.jsonc:

    jsonc
    "routes": [{ "pattern": "captureflow.dev", "custom_domain": true }]
  • cdn.captureflow.dev → the captureflow-recordings bucket's public access (R2 → bucket → Settings → Public access → connect custom domain). This must match R2_PUBLIC_BASE_URL.

Both domains must be on a zone in the same Cloudflare account.

7. Deploy ​

bash
pnpm --filter @captureflow/web cf:deploy

This chains opennextjs-cloudflare build → opennextjs-cloudflare deploy: builds Next.js, packages it through worker.ts (which adds the cron handlers and the transcription queue consumer), and publishes the Worker with its D1/R2/AI/queue bindings, vars, and cron triggers.

TIP

Validate locally first with pnpm --filter @captureflow/web cf:preview, which builds and serves the Worker against your .dev.vars and local D1.

8. Verify ​

  1. Open your domain — the dashboard/landing should load.
  2. Sign up / log in — confirms BETTER_AUTH_SECRET + D1 are wired.
  3. Tail logs: pnpm --filter @captureflow/web exec wrangler tail captureflow-web.
  4. Record + recording from the desktop app and confirm the link resolves and the video plays from your CDN domain (confirms R2 + CDN).

9. Point the desktop app at your backend ​

If you self-host on captureflow.dev, nothing to do. For any other host, see Point the desktop app at your backend.

10. Point the Chrome extension at your backend ​

The extension in the Chrome Web Store talks to captureflow.dev only. Build your own copy for your domain: see Point the extension at your backend.

Released under the AGPL-3.0-only license (MIT-licensed capture engine).