What is GitHub Pages?
GitHub Pages is a free static site hosting service tightly integrated with GitHub. It takes HTML, CSS, JavaScript, and other static assets directly from a repository and publishes a fully functional website at a predictable URL — either https://username.github.io/repository or a custom domain. There are no server‑side processes, databases, or backend frameworks involved. Everything runs in the visitor’s browser, which makes the service fast, secure, and remarkably simple to manage.
Under the hood, GitHub Pages can serve content from a dedicated branch (usually gh-pages or main) or from a specific directory like /docs. For modern workflows, it also supports building and deploying via GitHub Actions, giving you complete control over the build process. Whether you’re hosting a personal portfolio, project documentation, or a full‑blown static site generated by Jekyll, Hugo, or Next.js, GitHub Pages removes infrastructure concerns so you can focus exclusively on your content.
How it works under the hood
When you enable GitHub Pages for a repository, the service picks up static files from the configured source branch and folder. If you use the built‑in Jekyll builder (the default), GitHub automatically runs jekyll build on every push, placing the generated site in a production environment behind a global CDN. If you opt for a custom GitHub Actions workflow, you can run any static site generator or even a Node.js build script — the only requirement is that the workflow outputs a directory full of static files (typically _site or public) and uploads it as an artifact. GitHub Pages then deploys that artifact to production.
Why GitHub Pages Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →For developers, GitHub Pages solves a fundamental problem: how to publish a website without managing servers, paying for hosting, or configuring DNS for simple projects. It’s instantly available, version‑controlled, and backed by GitHub’s reliability. Here are the concrete benefits:
- Zero cost – Hosting is free for public repositories (and private repos on paid plans), with generous bandwidth and build limits.
- Version‑controlled publishing – Every push to the source branch triggers a new deployment. Rollbacks are as simple as reverting a commit.
- Automatic HTTPS – GitHub provisions TLS certificates for both
*.github.iodomains and custom domains, enforcing HTTPS by default. - Global CDN – Content is served through Fastly’s edge network, ensuring low latency worldwide.
- Deep GitHub integration – Permissions, pull requests, and team workflows apply seamlessly. You can even preview changes with pull‑request‑based previews (via third‑party tools or Actions).
- Static site generator support – Jekyll comes built‑in, but you can bring any generator (Hugo, Gatsby, SvelteKit, etc.) through GitHub Actions.
In a world where Jamstack architectures are increasingly popular, GitHub Pages is the easiest on‑ramp for delivering performant, secure, and scalable static sites right from your development workflow.
How to Deploy a Static Site with GitHub Pages
Let’s walk through a complete, step‑by‑step deployment. We’ll start with a plain HTML site, then show how to use a custom domain and finally a modern build‑with‑actions setup.
1. Create a repository
Start by creating a new repository on GitHub. If you want a user or organization site (the root domain like https://yourname.github.io), name the repository exactly username.github.io (replace username with your GitHub username). For a project site, any name works — it will be available at https://username.github.io/repo-name.
# Example: create a project repository via CLI
git init my-landing-page
cd my-landing-page
echo "# My Landing Page" >> README.md
git add README.md
git commit -m "first commit"
gh repo create my-landing-page --public --push
The gh CLI command creates the repository on GitHub and pushes the initial commit in one step. You can also use the web interface.
2. Add your static files
At a minimum, you need an index.html file. Create it in the root of your repository (or in a /docs folder if you plan to use that source). For this tutorial we’ll use the root.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My GitHub Pages Site</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 600px;
margin: 2rem auto;
padding: 1rem;
background: #f9f9f9;
color: #333;
}
h1 { color: #0366d6; }
</style>
</head>
<body>
<h1>Hello, GitHub Pages!</h1>
<p>This site is deployed automatically from a GitHub repository.</p>
<p>Last updated: <time datetime="2025-01-01">2025-01-01</time></p>
</body>
</html>
Commit and push this file to the repository’s default branch (usually main).
git add index.html
git commit -m "Add homepage"
git push origin main
3. Enable GitHub Pages
Go to your repository on GitHub, click Settings → Pages (in the left sidebar). Under “Source”, choose the branch you want to deploy from (e.g., main) and the directory (/ (root) or /docs). Click Save.
GitHub immediately starts deploying. After a few seconds, you’ll see a banner with the URL: https://username.github.io/repo-name/. For a user site (username.github.io), the URL is simply https://username.github.io. The site is now live.
# Example: if your username is "johndoe" and repo is "my-landing-page"
# Site URL:
https://johndoe.github.io/my-landing-page/
4. Access your site and verify HTTPS
Open the URL in a browser. You should see your styled page. GitHub automatically enforces HTTPS, so the connection will be secure. If you ever need to check deployment status, the “Pages” settings page shows a live log and the latest commit deployed.
5. Custom domain (optional)
To serve from your own domain (e.g., example.com), go back to the Pages settings and enter your domain in the “Custom domain” field. GitHub will create a CNAME record automatically, but you still need to configure your DNS provider:
- For a subdomain like
www.example.com, create aCNAMErecord pointing tousername.github.io. - For an apex domain (
example.com), use anALIAS,ANAME, orArecord pointing to GitHub’s IP addresses (check GitHub documentation for current IPs).
After DNS propagates, check “Enforce HTTPS” in the Pages settings. GitHub will provision a Let’s Encrypt certificate automatically.
# Example: DNS configuration for a subdomain
Type: CNAME
Name: www
Value: johndoe.github.io.
TTL: 3600
6. Deploying with GitHub Actions (advanced)
For modern static site generators like Next.js, SvelteKit, or even plain Node.js builds, you can bypass the default Jekyll builder and use GitHub Actions. This gives you complete control over the build environment, dependencies, and output.
First, disable the default build: In the Pages settings, set the source to GitHub Actions. Then create a workflow file in your repository at .github/workflows/deploy.yml.
# .github/workflows/deploy.yml
name: Deploy static site to Pages
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Build static site
run: npm run build
# This should output static files into "public" or "out"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out # or ./public, depending on your generator
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
This workflow builds on every push to main, uploads the static output, and deploys it to Pages. The upload-pages-artifact action expects a directory containing only static files (no server code). The deploy-pages action publishes that artifact to the production environment. Once you push the workflow file, GitHub automatically picks it up and runs the build — no manual “Save” required.
Best Practices
- Keep source and output separate – When using Actions, never commit built files to the source branch. Let the workflow generate them fresh and upload as an artifact.
- Use relative paths – In HTML and CSS, link assets with relative paths (
./style.css,../images/logo.png) so the site works both locally and at thegithub.ioURL, as well as on a custom domain. - Configure
.nojekyll– If you’re not using Jekyll (e.g., plain HTML or another generator via Actions), add an empty.nojekyllfile to the root of your output directory or source branch. This prevents GitHub from trying to run Jekyll and potentially breaking your paths. - Enforce HTTPS – Always enable the “Enforce HTTPS” checkbox in the Pages settings to redirect HTTP traffic automatically.
- Use a custom 404 page – Create a
404.htmlfile (or404.mdif using Jekyll) at the root of your site. GitHub will serve it for unknown URLs, giving you a branded error page. - Monitor build limits – While generous, GitHub Pages has soft limits (e.g., 10 builds per hour, 100GB bandwidth/month). For high‑traffic sites, consider a CDN‑backed static hosting service, but for most projects it’s more than enough.
- Test locally before pushing – Use a local static server (e.g.,
npx serve .orpython -m http.server) to preview your site. This catches broken links and missing assets early. - Version your dependencies – In Actions workflows, pin action versions (e.g.,
@v4) to avoid surprises when a major update ships.
Conclusion
GitHub Pages turns any repository into a production‑grade static website with almost zero configuration. It combines free hosting, automatic HTTPS, and a global CDN into a single, developer‑friendly service. Whether you’re shipping a quick HTML prototype, comprehensive documentation, or a full Jamstack application powered by GitHub Actions, the workflow remains the same: push code, and your site goes live. By following the steps and best practices outlined here, you can confidently deploy static sites that are secure, fast, and deeply integrated with your development process. The service’s simplicity hides powerful capabilities — from custom domains to CI‑driven builds — making it an essential tool in every modern developer’s toolbox.