Andy Nguyen

How To Deploy a Static Site to GitHub Pages With gh-pages and GitHub Actions (2026 Update)


This tutorial will show you how to use gh-pages and GitHub Actions to automatically deploy a static site (Astro, Gatsby, Next, etc.) to GitHub Pages. These steps and scripts are currently in use on this site.

Initial Context

This guide assumes there are two git repos, one to house the static site project code and one for the GitHub Pages public files. Each git repo will have these characteristics:

Setting up GitHub Actions secret

In order to transfer files from one GitHub repo to another, the GitHub Actions need an authentication token to commit to the correct repo. The recommended approach in 2026 is a fine-grained personal access token. Follow these steps to set up a secret.

This secret will be used in both the deploy script and in the GitHub Actions workflow.

Installing npm packages

For the deploy step, one npm package is needed:

Setup Deployment

Now for the fun part! The next two scripts will work in tandem to deploy the Gatsby project to the Github Pages repo.

Making the deploy script

Add this npm script to the project’s package.json.

"scripts": {
  ...
  "build": "astro build",
  "deploy": "gh-pages -d dist -b main --dotfiles --nojekyll -r https://$DEPLOY_TOKEN@github.com/username/username.github.io.git"
}

Setting up the GitHub Actions workflow

Add this yaml file to the project’s .github/workflows directory. Name it deploy.yaml, resulting in .github/workflows/deploy.yaml.

name: Deploy site

on:
  push:
    branches: [main]

jobs:
  deploy-site:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - run: npm install --legacy-peer-deps
      - run: npm run lint
      - run: npm run build
      - run: npm test
      - name: Deploy site
        run: |
          npx gh-pages -d dist -b main --dotfiles --nojekyll \
            -m "deploy site via GitHub Actions" \
            -u "YourName <your-email@example.com>" \
            -r "https://$DEPLOY_TOKEN@github.com/username/username.github.io.git"
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

2026 Updates

This post was originally written in 2022 and updated in 2026. Here’s what changed:

Node.js 24 and GitHub Actions Deprecations

Fine-Grained Personal Access Tokens

Build Before Test

gh-pages and .nojekyll

Conclusion

That’s it! Any push to the project repo will trigger a lint → build → test → deploy pipeline. Assuming username.github.io was the repo name and GitHub Pages was configured, there should be a live site at https://username.github.io!

Additional Resources