Your Cloudflare Pages env vars do nothing (Direct Upload vs Git build)

2 min read CloudflarePagesCI

You set a PUBLIC_ variable in the Pages dashboard, redeploy, and the build still can't see it. The reason: a Direct Upload project builds in your CI, not on Cloudflare, so the dashboard env vars never reach the build.

The symptom

I set a PUBLIC_ environment variable in the Cloudflare Pages dashboard (Settings, then Environment variables), redeployed, and the built site behaved as if the variable was empty. The value was definitely saved. Re-checking, re-saving, redeploying, nothing changed. The variable simply never reached the build.

What was actually happening

There are two kinds of Cloudflare Pages project, and they handle environment variables completely differently:

  • Git-integrated build: Cloudflare clones your repo and runs the build on Cloudflare’s build infrastructure. The dashboard env vars are injected into that build. This is what most docs and tutorials assume.
  • Direct Upload: the build happens somewhere else (a GitHub Action, or a local wrangler pages deploy), and only the finished dist/ is uploaded. Cloudflare never runs your build, so the dashboard variables are never present when your bundler runs. For Astro or Vite, which inline PUBLIC_ / VITE_ values at build time, the value gets baked in as empty.

My project deployed through a GitHub Action (cloudflare/wrangler-action), so it was Direct Upload. The Pages dashboard env-var screen was decorative for build purposes.

The fix

Set the variable where the build actually runs. For a GitHub Action, that’s the workflow, on the build step:

# .github/workflows/deploy.yml
      - run: npm ci
      - run: npm run build
        env:
          PUBLIC_BUTTONDOWN_USERNAME: basedev   # public value, fine inline
      - uses: cloudflare/wrangler-action@v3
        with:
          command: pages deploy dist --project-name=my-site

For a secret, reference a repo secret instead of inlining it: ${{ secrets.MY_VAR }}. The rule is simple once you see it: a PUBLIC_ / VITE_ variable is consumed at build time, so it has to exist in the environment that runs npm run build, which for Direct Upload is your CI, not Cloudflare.

The lesson

If your Pages project is Direct Upload (you deploy a prebuilt dist), the dashboard’s Environment variables never touch your build. Put build-time vars in the place that runs the build, your CI workflow. The dashboard env-var screen only matters for Git-integrated builds and for runtime Pages Functions.

Related fixes

Discussion

Powered by GitHub. Sign in to leave a comment.