NNicheStackTutorials
← All tutorials
Static Hosting

Cloudflare Pages Env Vars Missing at Build Time (Not Runtime)

Astro PUBLIC_ vars work in dev but undefined during CF Pages build. Set production vs preview env and avoid wrangler.toml pitfalls.

·12 min read·Static Hosting
Cloudflare Pages Env Vars Missing at Build Time (Not Runtime) cover

Stack: Astro 5 static, deployed to Cloudflare Pages Error in build log:

[SITE_URL] is required but was undefined during static generation

Worked locally with .env. Failed on CF Pages.

TL;DR

  • CF Pages injects env at build time for static prerender — not just runtime.
  • Set vars for Production AND Preview in dashboard.
  • Use PUBLIC_ prefix for client-exposed Astro/Vite vars.

Cloudflare Pages env UI

Dashboard → Pages → project → Settings → Environment variables

Scopes:

  • Production
  • Preview (PR previews)
  • Can add plaintext or secret

I only set Production. Preview builds on PRs failed.

Astro public vs private

# Available in client bundle — must be set at BUILD time
PUBLIC_SITE_URL=https://example.com

# Server-only — not inlined
API_SECRET=xxx

Static export inlines PUBLIC_* during astro build. If missing at build → empty string in output.

wrangler.toml (optional binding)

name = "my-blog"
pages_build_output_dir = "dist"

[vars]
PUBLIC_SITE_URL = "https://example.com"

Don't commit secrets to wrangler.toml. Use dashboard for secrets.

Fix workflow

  1. Add PUBLIC_SITE_URL for Production AND Preview in dashboard
  2. Retry deployment (Deployments → ... → Retry)
  3. Verify built HTML:
curl https://preview-abc.pages.dev | rg 'example.com'

Different values per environment

Preview can use:

PUBLIC_SITE_URL=https://preview-abc.pages.dev

Set via Preview-specific variable — overrides production on preview branches.

Local parity

# .dev.vars for wrangler pages dev
PUBLIC_SITE_URL=http://localhost:8788

Lesson

Static site "runtime env vars" don't exist. Everything public is baked at build. Plan accordingly.

CI check for missing PUBLIC vars

# .github/workflows/pages.yml
- name: Build
  env:
    PUBLIC_SITE_URL: https://example.com
  run: npm run build

Mirror dashboard vars in CI so local Actions match Cloudflare dashboard — avoids "works in dashboard, fails on manual retry".

Wrangler pages dev

npx wrangler pages dev dist --compatibility-date=2024-01-01

Serves built dist/ with .dev.vars loaded — closest local parity to production build.

FAQ

Why are env vars undefined during Cloudflare Pages build?

Vars may only be set for Production, not Preview. Or Astro/Vite needs PUBLIC_ prefix for client-side access during prerender.

Build-time vs runtime env on Cloudflare Pages?

Static sites prerender at build — anything embedded in HTML must exist at build time. Functions-only vars won't help static prerender.

Does wrangler.toml affect Pages build env?

Pages uses dashboard env primarily. wrangler.toml [vars] can conflict or be ignored depending on setup — prefer dashboard for Pages.

Tags: Cloudflare PagesEnvironment VariablesAstroBuild