HERON

Free hosting, your own address

GitHub Pages with your own domain

To use a custom domain with GitHub Pages, add the domain in the repository settings under Pages, then create DNS records at your domain registrar: four A records pointing to GitHub's addresses for the bare domain, and a CNAME record for www pointing to yourname.github.io. After the check passes, tick Enforce HTTPS.

Below are the exact records, the steps in order, the usual errors, and the same setup for Cloudflare Pages.

DNS records for GitHub Pages

Use these at your registrar. Replace yourname with your GitHub user or organization name.

TypeName (host)Value
A@185.199.108.153
A@185.199.109.153
A@185.199.110.153
A@185.199.111.153
AAAA@2606:50c0:8000::153
AAAA@2606:50c0:8001::153
AAAA@2606:50c0:8002::153
AAAA@2606:50c0:8003::153
CNAMEwwwyourname.github.io

Step by step

  1. 1

    Verify the domain

    On GitHub: your profile Settings → Pages → Add a domain. GitHub shows a TXT record; add it at your registrar. This stops anyone else from claiming your domain on GitHub Pages.
  2. 2

    Set the domain in the repository

    Repository → Settings → Pages → Custom domain. Type example.com and save. When the site is built by GitHub Actions, this setting is what counts; when it is published from a branch, GitHub also adds a CNAME file with the domain to that branch.
  3. 3

    Add the DNS records

    Create the A, AAAA and CNAME records from the table above. Delete any other A or CNAME records for the same names, such as a parking page from the registrar.
  4. 4

    Wait for DNS

    Usually minutes, sometimes up to 24 hours. GitHub shows "DNS check successful" when it sees the records.
  5. 5

    Turn on HTTPS

    Tick Enforce HTTPS in the same Pages settings. The certificate is free and renews on its own. If the box is grey, wait for the certificate to be issued, up to an hour.

Common errors

"Domain's DNS record could not be retrieved"

DNS has not updated yet, or an old record still points elsewhere. Remove extra records and wait.

Enforce HTTPS is unavailable

The certificate is not issued yet. Remove the custom domain, save, add it again, and wait up to an hour.

The domain resets after every publish

The site is published from a branch and the CNAME file is missing from the published folder. Keep a CNAME file with your domain in the root of what you publish.

404 on the domain, the github.io address works

The custom domain field is empty or has a typo.

Mixed content warnings

Some links or images still use http://. Use https:// or addresses relative to the site.

Cloudflare Pages with your domain

Cloudflare Pages is the other free option. Connect your GitHub repository in the Cloudflare dashboard → Workers & Pages → Create → Pages, then open the project → Custom domains → Set up a domain.

Domain already on Cloudflare

The DNS record is created for you in one click.

Domain elsewhere

Add a CNAME record for your subdomain pointing to yourproject.pages.dev. For the bare domain, Cloudflare asks you to move the domain's DNS to Cloudflare.

HTTPS

Issued and renewed automatically.

Publish a HERON site on GitHub Pages

HERON builds the dist/ folder with all pages, images, the sitemap and llms.txt. GitHub Pages serves it.

  1. 1

    Set the domain

    Put your domain in site.yaml or in the configurator, so canonical addresses and the sitemap use it.
  2. 2

    Build

    The strict build checks every link and description.
  3. 3

    Publish `dist/`

    Through GitHub Actions on every push, or by pushing the folder to the branch Pages publishes from. Add a CNAME file with your domain to static/ so it lands in the root of dist/.
  4. 4
  5. 5

Updates on every push

Once the domain works, publishing is the git routine: edit a page file, commit, push. GitHub Actions runs the HERON build and hands dist/ to Pages. In Settings → Pages set Source to "GitHub Actions" and add this file as .github/workflows/pages.yml:

name: pages
on:
  push:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - run: docker run --rm -v "$PWD":/site -w /site --user $(id -u):$(id -g) ghcr.io/fmstm/heron:prod build . --env prod --strict
      - uses: actions/upload-pages-artifact@v3
        with:
          path: dist
  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deploy.outputs.page_url }}
    steps:
      - id: deploy
        uses: actions/deploy-pages@v4

What happens on a push

GitHub checks out the site with its full history (for correct page dates), builds it with the stable HERON image, stops if the strict check finds an error, and publishes the result.

Where to watch

The Actions tab of the repository shows every run; a red run means the site was not changed, and the log names the file and line.

Every update after that

git add . && git commit -m "New services page" && git push, then open the site a minute later.

Limits and rules of GitHub Pages

WhatLimit
Published siteUp to 1 GB
TrafficSoft limit of 100 GB a month
Builds from a branchSoft limit of 10 an hour; does not apply to a GitHub Actions workflow like the one above
Repository on a free accountPublic only; private needs GitHub Pro or a team plan
What it is not forHosting an online business, a shop or a paid service (SaaS)

Questions

Is GitHub Pages free with a custom domain?

Yes, for public repositories on a free account. Private repositories need a paid GitHub plan for Pages. You only pay the registrar for the domain.

Should I use the bare domain or www?

Either. Set one as the custom domain in GitHub, and create records for both: GitHub redirects the other one to it.

How long does it take for the domain to work?

Usually minutes after the DNS records are saved, up to 24 hours depending on the registrar.

Can GitHub Pages do redirects from old addresses?

Not real server redirects: GitHub Pages only serves files. For true 301 redirects use your own server with nginx, where HERON writes the redirect rules into the config, or Cloudflare redirect rules built from the same list in dist/redirects.map.

Is there a size limit?

Yes: a published site may be up to 1 GB, with a soft limit of 100 GB of traffic a month. A typical business site is a few megabytes. See the limits.