Cloud

Cloudflare Pages, Node 22, and Why Boring Deployments Win

A practical case for keeping static technical publishing simple on Cloudflare Pages, with explicit runtime pinning and Git-driven releases.

14 Apr 2026 cloudflarepagesnodedeployment

For a technical content site, the fastest way to lose momentum is to choose a deployment path that is more ambitious than the project itself.

If the goal is a lightweight publication platform with Markdown or MDX content, predictable builds, and very little operational overhead, a static site on Cloudflare Pages is still a strong option. The nuance matters, though. Astro’s current Cloudflare guidance now focuses heavily on Workers for full-stack and on-demand rendering scenarios, while Cloudflare Pages documentation still supports standard Git-connected static deployments and explicitly lists Astro with npm run build as the build command and dist as the output directory. In other words, Pages remains a good fit when the site is static-first and the architecture is intentionally boring.

Keep the architecture boring on purpose

The most reliable technical sites are usually the least magical ones:

  • source files in Git
  • content in MDX
  • static HTML output
  • deployment triggered by a push to main
  • no database, no runtime state, no fragile build chain

That approach makes failures easier to reason about. When a build breaks, the problem is usually one of four things: missing dependencies, incorrect build settings, wrong repository structure, or an asset that was never committed.

For a static-first Astro site, an explicit configuration like this keeps the intent obvious:

javascript astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
integrations: [mdx()],
output: 'static'
});

Git-driven deployment is the feature, not a detail

For a content site, Git integration is one of the biggest operational advantages of Pages.

A push to the production branch should be enough to trigger a new deployment. That keeps the release model boring and auditable:

bash
git add .
git commit -m "Publish new article"
git push origin main

That flow is especially valuable once the site starts to carry actual content. It keeps design changes, article additions, and infrastructure tweaks in the same traceable history.

Pin your Node version deliberately

One detail that is easy to miss on Cloudflare Pages is runtime version handling.

Cloudflare’s current v3 build image ships with Node.js 22 by default, and it allows version overrides with NODE_VERSION, .nvmrc, or .node-version. At the same time, the v3 build system does not detect Node.js versions from package.json engines. If your build depends on a specific Node version, pin it explicitly instead of assuming engines will be honored in the Pages environment.

A small file at the project root is often enough:

text .node-version
22.12.0

That one decision removes a whole class of “works locally, fails in CI” problems.

The failure modes worth checking first

When a static Astro site fails on Pages, start with the boring checks:

  1. Is the app rooted where Pages thinks it is?
  2. Does the build actually produce dist/?
  3. Was the change really pushed?
  4. Is the asset referenced by the page actually committed into public/?

Run the same command locally that Pages will run:

bash
npm run build

If local output is not landing in dist, fix that first.

Use case: small technical publication platforms

For a personal or team-owned technical publication, the practical use case is straightforward. You want:

  • a fast static frontend
  • low deployment friction
  • minimal runtime cost
  • infrastructure you do not need to babysit

Cloudflare Pages plus Astro still fits that shape well. The mistake is usually not choosing Pages. The mistake is adding complexity before the site actually needs it.

References