Step-by-step
-
1
Push your site to a GitHub repository
Your source code must be in a GitHub repository. If deploying a pre-built folder (e.g.
dist/), either commit the build output to a dedicated branch or use GitHub Actions to build it automatically (covered later).bashgit init git add . git commit -m "Initial commit" git remote add origin https://github.com/your-user/your-repo.git git push -u origin main -
2
Enable Pages in repository settings
Go to Settings → Pages in your repository. Under Source, choose Deploy from a branch, then select the branch (typically
main) and the folder (/ (root)or/docs). Click Save. GitHub starts a deployment immediately and shows the live URL — usuallyhttps://your-user.github.io/your-repo/— within about 60 seconds.bash# After enabling, verify the deployment status: gh run list --workflow pages-build-deployment -
3
Prevent unwanted Jekyll processing
By default, GitHub Pages pipes your site through Jekyll, which skips any file or folder whose name starts with an underscore (
_app,_next,__mocks__). If your framework outputs files like these, add a.nojekyllfile to the root of your deployed branch.bash# In the root of your repo (or dist/ before deploying): touch .nojekyll git add .nojekyll git commit -m "Disable Jekyll processing" git push -
4
Deploy a built framework with GitHub Actions
For Vite, Next.js static export, or any framework that needs a build step, use GitHub Actions to build and publish instead of committing the
dist/folder. Create.github/workflows/deploy.yml— this is the recommended approach for any non-trivial site.yamlname: Deploy to GitHub Pages on: push: branches: [main] permissions: contents: read pages: write id-token: write jobs: deploy: environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run build # outputs to dist/ - uses: actions/upload-pages-artifact@v3 with: path: dist - id: deploy uses: actions/deploy-pages@v4 -
5
Switch the Pages source to GitHub Actions
When using the workflow above, go back to Settings → Pages → Source and switch from "Deploy from a branch" to GitHub Actions. Otherwise GitHub deploys both your branch and the workflow, which causes conflicts.
bash# Confirm the deployment URL once the workflow finishes: gh run list --limit 5 -
6
Add a custom domain
To serve the site from
www.example.cominstead of the default*.github.ioURL: add aCNAMEfile containing your domain to the root of the deployed branch, then create a CNAME DNS record pointing toyour-user.github.io. HTTPS is provisioned automatically via Let's Encrypt — it typically takes a few minutes to activate.bash# Create the CNAME file echo 'www.example.com' > CNAME git add CNAME && git commit -m "Add custom domain" && git push # DNS record to add with your registrar: # Type: CNAME # Name: www # Value: your-user.github.io -
7
Know the platform limits
GitHub Pages is generous for personal projects but not designed for high-traffic production apps. Keep these limits in mind: the published site must be 1 GB or less; GitHub recommends staying under a soft bandwidth limit of 100 GB/month; and there is a 10 builds/hour limit per repository. No server-side code, no databases — pure static only.
bash# Check your site's published size locally: du -sh dist/ # Anything over ~500 MB is a red flag for a static site.
Tips & gotchas
- For a personal portfolio at <code>username.github.io</code>, create a repo named exactly <code>username.github.io</code> — GitHub auto-serves it from the root without a sub-path.
- If your single-page app shows 404 on deep links, add a <code>404.html</code> that redirects to <code>index.html</code> — GitHub Pages serves it for missing paths.
- Cache-busting is free: GitHub Pages serves files with a strong ETag. Force a re-fetch by appending a query string or using content-hashed filenames (which Vite does automatically).
- The <code>gh-pages</code> npm package (<code>npm install --save-dev gh-pages</code>) automates pushing a <code>dist/</code> folder to the <code>gh-pages</code> branch without the Actions workflow.
Wrapping up
GitHub Pages covers the vast majority of static hosting needs at zero cost. For simple HTML, enable it in Settings in two clicks. For a framework like Vite or Next.js, the Actions workflow above gives you automated CI/CD with no third-party account required. Add a custom domain and HTTPS is handled for you. The only real constraint is the static-only requirement — the moment you need a database or server-side logic, graduate to a platform like Vercel, Render, or a VPS.