Step 9
Step 9 — Free hosting on GitHub Pages
25 min
Step 9 — Free hosting on GitHub Pages
Repo = site. Free, unlimited traffic, auto HTTPS. Static-only but the free part is real.
First deploy — 10 minutes
(a) Simplest — push index.html
mkdir my-site && cd my-site
echo "<h1>Hello GitHub Pages</h1>" > index.html
git init && git add . && git commit -m "first"
git remote add origin git@github.com:USER/my-site.git
git push -u origin main
In the GitHub UI: Settings → Pages → Source: main / / (root). After 1–2 minutes: https://USER.github.io/my-site/.
(b) Actions build + deploy (recommended)
For Vite/Astro/Next.js SSG, add .github/workflows/deploy.yml:
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment: github-pages
steps:
- uses: actions/deploy-pages@v4
In the UI: Settings → Pages → Source: GitHub Actions.
URL patterns — base path trap
| Repo type | URL | base path |
|---|---|---|
<user>.github.io |
https://<user>.github.io/ |
/ |
<user>/<repo> |
https://<user>.github.io/<repo>/ |
/<repo> |
Project sites have a /<repo> prefix. Set Vite's base, Next's basePath, etc.
export default defineConfig({
base: '/<repo>/', // '/' for user sites
plugins: [react()],
});
// Next.js (Static Export)
export default {
output: 'export',
basePath: '/<repo>',
images: { unoptimized: true },
};
Custom domain — free HTTPS
- Add a
CNAMEfile at repo root (one line:example.com). - DNS:
- apex → A records: 185.199.108.153 · .109.153 · .110.153 · .111.153
- www → CNAME
<user>.github.io
- UI → enable Enforce HTTPS. Let's Encrypt issues automatically.
Limits — what's off-limits
- No server code — no Express/FastAPI. No SSR (only static export).
- No DB — bake JSON at build or fetch from an external API.
- Forms — submit via Formspree · Cloudflare Forms.
- Bandwidth — 100GB/month soft limit. Side projects rarely hit it.
vs Replit / Vercel / Netlify
| Aspect | GitHub Pages | Replit Static | Vercel | Netlify |
|---|---|---|---|---|
| Cost | unlimited (free) | 1 free deployment | hobby 100GB | starter 100GB |
| Custom domain (free) | ✓ | ✗ (Core) | ✓ | ✓ |
| Auto HTTPS | ✓ | ✓ | ✓ | ✓ |
| SSR | ✗ | partial | ✓ | ✓ |
| Preview deployments | ✗ | ✗ | ✓ | ✓ |
| Learning curve | medium | low | low | low |
OSS docs · portfolios · blogs → GitHub Pages. SSR · dynamic → Vercel/Netlify.
Try it
Take the Vite React app from getting-started, push to GitHub, set up Actions deploy, and load <user>.github.io/<repo>. When done, archive or delete the repo.
Deeper
- GitHub Pages note
- Replit note — when you do need a backend
Course wrap-up
You now have 6 deploy options in your toolbox: Docker · Caddy · AWS · Fly.io · Replit · GitHub Pages. Side projects → GitHub Pages / Replit. Real workloads → Fly.io or a single server + Caddy.
🎉 You finished Docker · Caddy · Cloud — running on one server
What's next? Pick another course below.