GitHub Actions Pages Deployment
GitHub Pages hosts static websites straight from a repository at no cost for public projects. A workflow can build your site, upload the result, and publish it on every push. The method suits portfolios, documentation, blogs, and project landing pages.
Pages Deployment in Simple Words
Picture a print shop. You hand over your design files, the shop prints them, and a delivery truck places the finished posters in a public gallery. The workflow is the print shop, the built site is the poster, and GitHub Pages is the gallery.
Enable Pages for Actions
Open Settings, choose Pages, and set Source to GitHub Actions. The setting tells GitHub to accept deployments from workflows instead of a branch.
The Deployment Pipeline
+---------+ +-----------+ +-----------------+ +--------------+
| Push to | --> | Build job | --> | Upload site as | --> | Deploy job |
| main | | (npm run | | Pages artifact | | publishes to |
| | | build) | | | | github.io |
+---------+ +-----------+ +-----------------+ +--------------+Complete Workflow
name: Deploy Site to Pages
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
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/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4Action version numbers change over time. Confirm the latest tags on each action page in the GitHub Marketplace before copying this file.
What Each Part Does
Permissions
The pages: write scope lets the workflow publish. The id-token: write scope lets the deploy action prove its identity to Pages.
Concurrency
The group named pages allows only one deployment at a time. Setting cancel-in-progress to false lets a running deployment finish instead of stopping halfway.
Build Job
This job installs dependencies, creates the final files in a folder named dist, and packages that folder as a Pages artifact. A plain HTML site skips the build commands and uploads its root folder directly.
Deploy Job
The deploy job receives the artifact and publishes it. Its environment block makes the live address appear on the run page.
Folder Names by Tool
| Tool | Build Command | Output Folder |
|---|---|---|
| Plain HTML | None | Repository root or a chosen folder |
| Vite or Vue | npm run build | dist |
| Create React App | npm run build | build |
| Jekyll | jekyll build | _site |
Your Site Address
Project sites appear at https://username.github.io/repository-name/. A repository named username.github.io publishes at the shorter address https://username.github.io/. Many tools need a base path setting that matches the repository name, or pages load without their styles.
Custom Domains
Open Settings, then Pages, and type your domain in the Custom domain box. Create a CNAME record at your domain provider that points to username.github.io. GitHub issues an HTTPS certificate automatically after the records propagate.
Troubleshooting
- A 404 page after deployment often means the upload path is wrong or the base path is missing.
- A failed deploy with a permission message means the
pagesorid-tokenscope is absent. - Styles that fail to load point to absolute paths. Switch to relative paths or set the base path.
Every merge to main now updates the live site within a minute or two. The workflow log shows each stage, so a broken build never replaces a working site.
