GitHub Pages
GitHub Pages is free static-site hosting served straight from a repository over HTTPS — docs, project sites, blogs, and SPAs, with no server to run.
Why it matters
Most projects need a public face: API docs, a landing page, a coverage report. Pages gives it for free at a predictable URL with automatic TLS, so you ship a site by pushing files. It is the default home for tool docs (mkdocs/Docusaurus/Quartz output) precisely because it couples to the repo and a build workflow.
How it works
A repo’s Pages site builds from a chosen source (a branch+folder, or a Pages-type Actions workflow) and publishes to a URL keyed by repo type.
| Repo name | URL | Type |
|---|---|---|
user.github.io | https://user.github.io/ | user/org site (one per account) |
| any other repo | https://user.github.io/repo/ | project site |
custom CNAME | https://docs.acme.com/ | apex or subdomain |
- Two build paths — legacy “deploy from a branch” runs Jekyll on
main/gh-pages; modern uses an Actions workflow (actions/deploy-pages) that uploads an artifact, which is how non-Jekyll generators deploy. - Limits (soft) — published site ≤ 1 GB, ~100 GB/month bandwidth, ~10 builds/hour. It is for static content only — no server-side code, no databases.
.nojekyll— drop this file at the site root to skip Jekyll; otherwise files/dirs starting with_are silently ignored.- Custom domain — a
CNAMEfile plus a DNSCNAME(or apexA/ALIAS) record; tick “Enforce HTTPS” once the cert provisions.
Example
Deploy a built dist/ via Actions:
permissions: { pages: write, id-token: write }
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build # emits ./dist
- uses: actions/upload-pages-artifact@v3
with: { path: dist }
- uses: actions/deploy-pages@v4Pitfalls
- Root-relative asset paths on a project site —
/style.css404s because the site lives under/repo/; use a base path or relative URLs. - Underscore folders vanish — a
_next/or_assets/dir disappears under Jekyll; add.nojekyll. - Public output from a private repo — the source repo may be private, but the published Pages site is world-readable (unless on Enterprise). Don’t ship secrets into the build.
- Stale DNS / HTTPS — changing the custom domain before DNS propagates leaves the cert unprovisioned; “Enforce HTTPS” stays greyed out until it resolves.