← route

LSN 05/10 PAGES 12 MIN TIER FREE

Pages: hosting your first site

Connect a Git repo, get a built static site at the edge, attach a custom domain. The path-of-least-resistance hosting on Cloudflare.

Before this: 04 DNS, the part you'll touch daily

Pages is Cloudflare’s static-site hosting product. You connect a Git repository, Cloudflare runs your build, and the resulting static files get served from every Pages edge worldwide. This is the path of least resistance for shipping a site on Cloudflare.

This site (cloudflare.too.foo) is a Pages project. So is everything else under too.foo.

Creating a project

From the dashboard, Workers & PagesCreatePagesConnect to Git. Authorize Cloudflare to read your GitHub or GitLab account if you have not already, then pick the repository.

The next screen asks for build settings:

  • Production branch. Usually main. Pushes to this branch build and deploy to production.
  • Framework preset. A dropdown of common frameworks (Astro, Next.js, Vite, Hugo, Eleventy, etc.). Each preset fills in the build command and output directory. Pick one if it matches; otherwise leave blank and fill in manually.
  • Build command. What Cloudflare runs to build. For most static generators: npm run build, pnpm build, yarn build, hugo, etc.
  • Build output directory. Where the built files end up. Common values: dist, build, public, _site.
  • Root directory (advanced). If your project is not at the repo root (monorepo), point Cloudflare at the right subdirectory.

Click Save and Deploy. The first build takes 30 to 90 seconds. When it finishes you get a URL like your-project.pages.dev that serves your site immediately.

Per-branch previews

Every branch you push (not just main) gets its own preview deploy. The URL pattern is:

https://<branch-slug>.<project>.pages.dev

Where <branch-slug> is the branch name with / replaced by -. So feature/dark-mode becomes feature-dark-mode.your-project.pages.dev. This is genuinely useful: every PR has a live preview URL you can share with a reviewer or the design person.

There is no per-branch configuration. Whatever the build command does, it does for previews too. Use process.env.CF_PAGES_BRANCH inside the build if you need to vary behavior (e.g., different analytics ID for production vs. preview).

Custom domain

A pages.dev URL is fine for a side project but you usually want yoursite.com or a subdomain.

In the Pages project settings, go to Custom domainsSet up a custom domain → enter the hostname. Cloudflare creates the DNS record for you if the domain is on the same Cloudflare account.

Behind the scenes this adds a proxied CNAME from your hostname to your-project.pages.dev. Because the record is proxied (orange cloud), Cloudflare:

  • Issues a TLS certificate automatically (Let’s Encrypt under the hood, but you do not see that).
  • Terminates HTTPS at the edge.
  • Serves the static files from cache.

For an apex domain (yoursite.com, not www.yoursite.com), Cloudflare uses CNAME flattening (see DNS lesson) to make the CNAME work on the apex. You do not have to think about it.

Pages Functions

Pages also supports Functions, which are Workers that live inside your Pages project. Drop a file at functions/api/hello.ts and that file handles requests to /api/hello on your site. The runtime is identical to standalone Workers (next lesson), but the deploy is tied to your Pages project.

Functions are how you add dynamic behavior to an otherwise static site: form submissions, auth, API endpoints, edge-rendered pages.

Monorepo: root_dir and path_includes

A single Git repo can drive many Pages projects, each with their own build. Two settings make this work:

  • Root directory. The subdirectory the build command runs in.
  • Path includes. A list of paths whose changes trigger a rebuild for this project.

On too.foo there are around 30 apps in one monorepo. Each app has its own Pages project with root_dir = apps/<slug> and path_includes covering apps/<slug>/*, packages/**, pnpm-lock.yaml, pnpm-workspace.yaml, package.json. A change to one app’s source rebuilds only that app’s project. A change to a shared package (packages/**) rebuilds every project that depends on it. A change to a totally unrelated app rebuilds nothing.

The trap to avoid: if path_includes does not cover shared packages, a change to a shared UI library will not rebuild apps that consume it, and the design system drifts between subdomains. Always include the shared paths.

Limits

  • 500 builds per month on the free plan. Pro raises this to 5000.
  • Up to 20,000 files per deploy. Bundle if you have more.
  • 25 MB single-file maximum.
  • Unlimited bandwidth. This is the headline feature.
  • Concurrent builds: 1 on free, 5 on Pro.

These limits are generous enough that you usually only hit them when something is misconfigured (a build looping, or a monorepo accidentally including node_modules).

Pages is the easiest place to start on Cloudflare. Once your site is up, the next interesting move is running code at the edge: Workers.