> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streamly.watch/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Cloudflare

> Deploy Streamly to Cloudflare Workers with OpenNext and Wrangler — KV setup, wrangler personalization, and production checklist.

Streamly ships a premade **Cloudflare Workers** path using **OpenNext** and **Wrangler**. This runs the **full app** (operator admin + viewer storefront + APIs) — not CDN-only static hosting.

Production reference: **`https://streamly.watch`** via `pnpm run deploy:cloudflare`.

<Warning>
  The repo `wrangler.jsonc` is wired for **streamly.watch** (routes, KV ids, and often `ENABLE_DEMO=true`). Before your own production deploy, create **your** KV namespace, replace ids, change routes/vars to your domain, and **turn off demo mode**.
</Warning>

## When to use this

| Goal                           | Use                                           |
| ------------------------------ | --------------------------------------------- |
| Match production / edge deploy | This guide                                    |
| Simple Node VM                 | [Deploy (Node)](/getting-started/deploy-node) |
| Local Workers runtime          | `pnpm run preview:cloudflare`                 |

## Requirements

* Node.js **20+**, pnpm, Cloudflare account
* Same secrets as a normal deploy ([Environment Variables](/technical/environment-variables))
* Cloudflare KV (incremental cache), queues; R2 optional when enabled on the account

## 1 — Install

```bash theme={null}
corepack enable
pnpm install --frozen-lockfile
pnpm exec wrangler login --use-keyring
```

Cloudflare-related files: `wrangler.jsonc`, `open-next.config.ts`, `custom-worker.ts`.

## 2 — Create Cloudflare resources (once)

```bash theme={null}
# Incremental cache (required while R2 is disabled in wrangler.jsonc)
pnpm exec wrangler kv namespace create NEXT_INC_CACHE_KV
pnpm exec wrangler kv namespace create NEXT_INC_CACHE_KV --preview

pnpm exec wrangler queues create streamly-jobs
pnpm exec wrangler queues create streamly-jobs-dead
```

Paste the returned `id` / `preview_id` into `wrangler.jsonc` → `kv_namespaces` binding `NEXT_INC_CACHE_KV` (replace the Streamly account values).

Optional when R2 is available: create the cache/media buckets noted in product `DEPLOYMENT.md`, then re-enable R2 bindings.

## 3 — Personalize wrangler.jsonc

| Setting                                | Action                                                                         |
| -------------------------------------- | ------------------------------------------------------------------------------ |
| `routes`                               | Your domain patterns + `zone_name` (not `streamly.watch` unless that is yours) |
| `vars.NEXT_PUBLIC_*` / build env       | Your public URL, platform host, API base                                       |
| `vars.ENABLE_DEMO`                     | Set `"false"` (or remove) on real buyer installs                               |
| Worker `name` / self-reference service | Keep consistent if you rename the worker                                       |

`pnpm run deploy:cloudflare` currently bakes `https://streamly.watch` public URLs in `package.json` scripts — for your domain, set those env vars in the shell before deploy or adjust the scripts:

```bash theme={null}
export NEXT_PUBLIC_APP_URL=https://your.domain
export NEXT_PUBLIC_PLATFORM_HOST=your.domain
export NEXT_PUBLIC_STREAMLY_API_BASE=https://your.domain/api/v1
```

## 4 — Secrets

```bash theme={null}
pnpm exec wrangler secret put SUPABASE_SERVICE_ROLE_KEY
pnpm exec wrangler secret put TENANT_SECRETS_MASTER_KEY
pnpm exec wrangler secret put STREAMLY_CRON_SECRET
pnpm exec wrangler secret put ENVATO_PERSONAL_TOKEN
pnpm exec wrangler secret put RESEND_API_KEY
# plus TMDB, STREAMLY_FROM_EMAIL, Cloudflare SaaS tokens, etc. as needed
```

Local Workers preview uses `.dev.vars` (from `.dev.vars.example`, includes `NEXTJS_ENV=development`) — never commit it.

## 5 — Deploy

```bash theme={null}
pnpm run typecheck   # recommended
pnpm run deploy:cloudflare
```

What it runs: OpenNext Cloudflare build → worker minify → `opennextjs-cloudflare deploy -- --minify`.

Preview:

```bash theme={null}
pnpm run preview:cloudflare
```

Also available: `pnpm run upload:cloudflare` (build + upload without full deploy flow).

## 6 — Domains & SaaS

Attach your custom domain in Cloudflare → Workers & Pages → Domains & Routes.

Optional Cloudflare for SaaS hostname automation:

* `CLOUDFLARE_ACCOUNT_ID`
* `CLOUDFLARE_ZONE_ID`
* `CLOUDFLARE_CUSTOM_HOSTNAMES_API_TOKEN`
* `CLOUDFLARE_SAAS_FALLBACK_HOST` (default `customers.streamly.watch`)

## 7 — After deploy

| Check          | Expect                                                 |
| -------------- | ------------------------------------------------------ |
| Storefront `/` | Theme + branding load                                  |
| `/admin/login` | Operator activation (Resend magic-link in production)  |
| Stripe webhook | `https://your.host/api/webhooks/stripe`                |
| Legal pages    | Terms/privacy render (bundled markdown — Workers-safe) |
| Demo flags     | Off on production                                      |

<Warning>
  Do not rely on runtime `fs` reads for content under `content/` on Workers. Legal markdown is imported at build time via `lib/landing/legal-markdown.ts`.
</Warning>

## Troubleshooting

| Issue                      | Fix                                                            |
| -------------------------- | -------------------------------------------------------------- |
| KV / binding errors        | Create your namespace; replace ids in `wrangler.jsonc`         |
| Wrong tenant / branding    | Check `NEXT_PUBLIC_PLATFORM_HOST` and DNS `Host`               |
| Auth cookies fail          | Confirm HTTPS URL matches `NEXT_PUBLIC_APP_URL`                |
| Demo license still showing | Set `ENABLE_DEMO` false in wrangler vars + secrets             |
| Preview env missing        | Copy `.dev.vars.example` → `.dev.vars`                         |
| Worker size limit          | Ensure deploy uses `--minify` (default in `deploy:cloudflare`) |

## Related

* [Cloudflare Workers (technical)](/technical/cloudflare-workers)
* [First Launch Checklist](/getting-started/first-launch-checklist)
* [Environment Variables](/technical/environment-variables)
* [Deployment FAQ](/faq/deployment-faq)
