Web hosting

How to use GitHub Pages.

Push to main. Site goes live in 60 seconds. No build step, no Netlify, no Vercel, no DNS, no server. Just a static folder named /docs or a branch called gh-pages and a one-click toggle in repo settings.

01 · The layers

What you're actually deploying.

GitHub Pages is a static-file CDN attached to a public repo. There's no runtime, no server-side code, no database. The whole service is "we'll serve whatever's in this folder over HTTPS with a green lock and a free cert." That's the whole product.

L1
Source
A repo on GitHub
Public. Free for personal accounts. Pages is off by default — you turn it on once in repo Settings → Pages. After that, every push to the selected branch triggers a deploy.
L2
Build
A static folder of files
HTML, CSS, JS, images, fonts, anything that doesn't need a server. The whole content of your site is just files in a folder. For a single-page doc site like this one, that's index.html plus an assets/ dir.
L3
CDN
GitHub's edge cache
Pages is served from a global CDN. Files are cached aggressively at the edge. The first request after a deploy takes a beat; every request after that is a cache hit. There's no warm-up script, no origin shield, no config to set.
L4
DNS
A subdomain at github.io
By default your site lives at <username>.github.io/<repo>/. Custom domains work — point an A record at GitHub's four IPs (185.199.108.153, .154, .155, .156) or a CNAME at <username>.github.io.
L5
TLS
Free HTTPS, automatic renewal
Let's Encrypt certificate, provisioned and renewed by GitHub. No config, no certbot, no cron. Add a custom domain and the cert shows up within minutes.
02 · Why

Why Pages wins for this kind of site.

If your content is a doc, a portfolio, a landing page, a marketing site, a research notebook, or a blog with no comments — Pages is the right tool. It's not the right tool for SPAs that need server-side routing, dashboards with auth, or anything that needs a database.

What you wantPages?Why
Doc / long-read / portfolioyesStatic files, low traffic, free hosting, free CDN.
Marketing / landing pageyesSame. Pages is designed for this shape.
Personal blog (no comments)yesMarkdown → static HTML via a build step on push, or just commit HTML.
Project hub with multiple sectionsyesEach section gets its own folder and index.html. That is this site.
Web app with user accountsnoYou need server-side auth. Pages can't run it.
SPA with client-side routingmixedPages serves the SPA shell fine, but 404s on deep links. Add a 404.html that redirects, or use HashRouter.
Anything with a databasenoPages has no runtime. Use Render, Fly, Railway, or a managed DB + Pages frontend.
The 60-second rule

Push a single HTML file. Open Settings → Pages. Pick the branch. Wait 60 seconds. Your site is live on the public internet with HTTPS. That's the whole flow. If your stack needs more than that to go from "files on disk" to "live URL," your stack has too much ceremony.

03 · The artifact

This site, in five files.

The page you're reading right now is a single static HTML file. The whole kai-systems hub is 9 such files plus one shared CSS. The "build" is a typo for "git commit." Here's the actual layout on disk:

# A repo named "kai-systems" on GitHub kai-systems/ ├── index.html ← the hub ├── SPEC.md ← the contract ├── README.md ← the discoverability ├── assets/ │ └── shared.css ← tokens + reset + nav ├── video/ │ └── index.html ← spoke 01 ├── music/ │ └── index.html ├── terminal/ │ └── index.html └── pages/ ← you are here └── index.html

No package.json in the runtime path. No node_modules. No bundler. The CSS lives in one file. Each page has its own inline <style> for the hero and the section layouts, but everything inherited (tokens, body base, nav strip, fonts) comes from assets/shared.css.

04 · In practice

The seven-step deploy.

From an empty GitHub account to a live site. The full ceremony, top to bottom, with the exact commands and the exact screens.

S1
Create the repo
On github.com/new
Public, name it whatever your URL will be. The repo name becomes the path: kai-systems lives at /kai-systems/.
S2
Local
Clone, add a file, commit
The whole "build" is the file system:
git clone git@github.com:kajica2/kai-systems.git cd kai-systems echo '<h1>hello</h1>' > index.html git add . && git commit -m "initial" git push
S3
Settings
Turn on Pages
Repo → Settings → Pages. Under "Build and deployment", Source: Deploy from a branch. Branch: main, folder: / (root). Save.
S4
Wait
60 seconds, sometimes less
A workflow runs in the Actions tab. It copies the branch into a Pages bucket. Refresh the Settings → Pages screen and you'll see "Your site is live at https://kajica2.github.io/kai-systems/".
S5
Iterate
Push → live
Every commit to main triggers a new deploy. There's no "publish" button. The whole edit-checkpoint is git push.
S6
Custom domain
Optional
Add a file called CNAME at the repo root containing your domain (one line, no protocol). At your DNS provider, add either four A records pointing to GitHub's IPs or one CNAME pointing to kajica2.github.io. The cert shows up within 15 minutes.
S7
Custom 404
Add a 404.html at the root
Pages serves this for any missing path. Use it to redirect users back to the hub, or to render a styled not-found page that matches your design.
Site settings, where to find them

After the first deploy, every site-level setting (custom domain, HTTPS enforcement, custom 404, build branch) lives at Settings → Pages. Everything repo-level (visibility, collaborators, branches, Actions permissions) is in the same Settings page but other tabs. The split is intentional: Pages settings are about serving, repo settings are about the source.

05 · Forking the stack

Adopting this for your own project.

Three forks that make sense, ordered from smallest to largest. Pick the shape that matches what you're actually shipping.

F1
Single page
A landing page
One index.html with inline styles. No assets/ dir at all. Pages serves it directly. The whole site is one URL.
portfolio product launch event page
F2
Hub + sections
Multi-section docs
This fork. A hub at the root, one folder per section, a shared CSS. Each section is a static page that links to its siblings via a top nav. No router, no client-side state. The structure is the URL.
documentation research notebook project hub brand site
F3
Markdown source
Blog with build step
Source files in /src are markdown. A GitHub Action runs a static site generator (Jekyll is built-in, or Hugo / Eleventy via community actions) and pushes the rendered HTML to main or gh-pages. Pages serves the output, not the source.
personal blog changelog release notes
Branch strategy

For most projects, serve from main and commit rendered output directly. If you have a heavy build that runs on every push, serve from a separate gh-pages branch — the source stays on main, the build action pushes artifacts to gh-pages, and Pages only watches the artifacts branch. This is how Jekyll-powered GitHub Pages works by default and it keeps the build noise out of the source history.

When NOT to fork this

If you need server-side rendering for SEO of dynamic routes, or you need auth, or you need a database, or you need server-side form handlers — Pages is the wrong tool. Don't fight it. Use Vercel or Render for Next.js, Fly or Railway for full-stack Node/Python, or Cloudflare Pages for serverless functions. Each of those is also free-tier and one-click deploy. Pages is for files. Use the right tool.

git GitHub.com a text editor a domain name (optional)

Nine stacks. One philosophy. Zero babysitting.