NoteTry or Cry

How to host a website on Cloudflare Pages for free

· Day 4 · Obsidian · 3 minGuide card: How to host a website on Cloudflare Pages for free

Cloudflare Pages hosts a website for free, straight from a GitHub repository. You connect the repository, tell it how to build the site, and from then on every push to main rebuilds and publishes it. This site runs on the free plan: the pages, the newsletter sign-up and up to 500 builds a month.

What you need

  • the website's code in a GitHub repository (mine is built with Astro, but any static site works)
  • a free Cloudflare account
  • a domain, if you want your own address. Without one you get a free your-project.pages.dev address.

Step 1: connect the repository

Cloudflare dashboard → Workers & Pages → Create → Pages → Connect to Git. Allow Cloudflare to see your GitHub account, then pick the repository.

Step 2: build settings

Setting Value
Production branch main
Framework preset Astro
Build command npm run build
Build output directory dist

The Node version comes from the .nvmrc file in the repository (mine says 22).

Press Save and Deploy. The first build takes a minute or two. When it is green, the site is live on its pages.dev address.

Step 3: secrets

Anything the build needs but nobody should see goes into Settings → Variables and secrets, as type Secret. Add it for Production and Preview.

Mine has one so far: OBSIDIAN_TOKEN. My notes live in a second, private repository, and the build needs to read them. The token comes from GitHub: Settings → Developer settings → Fine-grained tokens, repository access only the notes repository, permission Contents: read-only. Read-only on purpose: the build has no business writing anything.

Step 4: rebuild without a push

Every push to main already starts a build. For everything else there is a deploy hook: a secret address that starts a build when something calls it.

Settings → Builds → Deploy hooks → add one for main, and copy the address. Then on GitHub, in each repository that should be able to start a build: Settings → Secrets and variables → Actions → New repository secret, name CF_PAGES_DEPLOY_HOOK, value: that address.

I use it twice:

Step 5: your domain

Your project → Custom domains → add the domain. If the domain is on Cloudflare already, it sets everything up by itself. If not, it shows you which records to add where you bought it. Add www as well, plus a redirect rule (Rules → Redirect Rules) that sends it to the main address. The certificate is free and automatic.

What else Cloudflare does for this site

  • Security headers. A file called _headers in the site tells Cloudflare which headers to send: which scripts may run, how long files may be cached. Mine allows scripts and styles only from the site itself.
  • The one dynamic part. Cloudflare does not run PHP. The newsletter sign-up is a small function next to the pages (a Pages Function), and it runs on the same free plan.
  • 404s. A 404.html in the build is served for every address that does not exist.

What it costs

The hosting: nothing. The free plan has a limit of 500 builds a month. The nightly rebuild uses about 30, so there is room for a lot of publishing. Single files can be up to 25 MB, which is why I keep video clips small. The domain is the one thing I pay for.

When the build fails

Cloudflare shows the build log under Deployments. The usual suspects:

  • "git clone … failed": the build could not read a second repository. The token is missing, expired, or allowed on the wrong repository.
  • A missing package: the build installs exactly what package-lock.json says. Commit that file.
  • The wrong output folder: Astro builds into dist. Another tool might use build or out.

A failed build changes nothing. The last good version stays online until the next build works.

Next: How a note in Obsidian becomes a page on my website, how my notes turn into pages. The whole story in one post: How this site works, and how I built it.

Want me in your inbox? 😏

One email every Sunday: what I made, what it earned, and what went wrong.

lassewehlmann.com

The newsletter is coming.

I’m still wiring it up. Until then, every day lands on this site first.