Deploying to Cloudflare Workers
TinaCMS works with Cloudflare Workers using git-connected builds. Every push to your production branch runs the build (including the tinacms build step) and deploys the result to the Workers runtime.
Workers is the right target whenever your site needs a server at request time: SSR routes, API endpoints, redirects, and — for the Astro starter — the on-demand route that powers click-to-edit visual editing.
Astro users: deploy to Workers, not Cloudflare Pages. The
@astrojs/cloudflareadapter no longer supports Cloudflare Pages — it targets Workers. The starter's visual-editing route (src/pages/tina-island/[name].ts) is server-rendered (prerender = false), so a static-only Pages upload would break click-to-edit at request time.
Astro (the tina-astro-starter)
This walks the Astro starter from a clean checkout to a live Workers deploy. Push your project to a GitHub repository first.
1. Adapter and wrangler.jsonc (already in the starter)
Nothing to configure — the starter ships this for you:
astro.config.mjsauto-detects the host. In Cloudflare's git-based Workers Builds, theWORKERS_CIenvironment variable is set automatically, which selects the@astrojs/cloudflareadapter. You don't runnpx astro add cloudflare, and you don't edit the config.- A root
wrangler.jsoncenablesnodejs_compat. The visual-editing route usesnode:async_hooks(AsyncLocalStorage); without this flag the island route fails at runtime:
{"name": "tina-astro-starter","compatibility_date": "2026-06-01","compatibility_flags": ["nodejs_compat"]}
That minimal config is all Wrangler needs — the adapter wires up the Worker entrypoint and the static-assets binding at build time.
Adding TinaCMS to an existing Astro site? Runnpx astro add cloudflare, then create awrangler.jsoncat the repo root withcompatibility_flags: ["nodejs_compat"]and a recentcompatibility_date.
2. Create the Worker
In the Cloudflare dashboard go to Workers & Pages | Create | Workers | Import a repository, connect your GitHub account, and select your repo.
Set the build under Build configuration:
- Build command:
pnpm build— the starter'sbuildscript istinacms build --content=local -c "astro build", which indexes your committed content, then runsastro build. - Deploy command:
npx wrangler deploy - Build output:
dist(Astro's default; you don't need to change this).
DEPLOY_ADAPTER is not needed here — WORKERS_CI is detected automatically. You only set DEPLOY_ADAPTER=cloudflare for a manual deploy where no host env var applies (e.g. running npx wrangler deploy from your own machine).
3. Environment variables
tinacms build needs your TinaCloud credentials at build time. Add these under the Worker's Settings | Build | Variables and Secrets (grab both credentials from your TinaCloud project):
PUBLIC_TINA_CLIENT_ID— your TinaCloud client ID. Astro uses thePUBLIC_prefix, not Next.js'sNEXT_PUBLIC_.TINA_TOKEN— a content token from TinaCloud.SITE_URL— your production URL (e.g.https://your-worker.your-account.workers.dev, or your custom domain). Cloudflare Workers injects no deploy-URL variable, so withoutSITE_URLyour sitemap, RSS, and OpenGraph tags fall back tolocalhost.
Workers keep build variables and runtime variables separate. The island route reads your TinaCloud client ID and token at request time, so add
PUBLIC_TINA_CLIENT_IDandTINA_TOKENagain under Settings | Variables and Secrets (not just the build section).SITE_URLis only used at build time.
4. Verify visual editing works at request time
After the first deploy:
- Open
/adminon your Worker's URL, edit a post, and save. The save commits to GitHub, which triggers a rebuild and redeploy. - Open a content page and confirm click-to-edit works: clicking an editable region highlights it and opens its form in the sidebar. This exercises the on-demand
/tina-island/*route running inside the Worker — if it errors, check thatnodejs_compatis set and that your runtime variables are present.
Next.js
Use the OpenNext Cloudflare adapter and follow its setup to generate open-next.config.ts and wrangler.jsonc.
In the dashboard (Workers & Pages | Create | Workers | Import a repository), set:
- Build command:
npx opennextjs-cloudflare build - Deploy command:
npx opennextjs-cloudflare deploy
Add your build-time credentials under Settings | Build | Variables and Secrets:
NEXT_PUBLIC_TINA_CLIENT_ID— your TinaCloud client ID.TINA_TOKEN— a content token from TinaCloud.
As with Astro, Workers keep build and runtime variables separate — if your OpenNext SSR reads these at request time, add them again under Settings | Variables and Secrets.
Finalising TinaCloud setup
Your first deployment gives you a default domain like https://<worker-name>.<account-name>.workers.dev. Set this (or your custom domain) as the Site URL in your TinaCloud project's configuration so the editor loads against the right origin.
Troubleshooting
"JavaScript heap out of memory" during the build. The TinaCloud indexing step can exceed Node's default heap. Raise it with a build-time environment variable NODE_OPTIONS set to --max-old-space-size=4096.