Skip to content

Publish to GitHub Pages

GitHub Actions workflow to build and deploy static sites to GitHub Pages.

When to use

Use this GitHub Actions workflow when you need automated static site deployment that builds, tests, and deploys to GitHub Pages on every push to main.

The pattern

Create .github/workflows/publish-to-github-pages.yaml:

yaml
name: Publish to GitHub Pages

on:
  push:
    branches: [main]
    paths: ["src/**", "scripts/**", "package.json"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  publish-to-github-pages:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm test
      
      - name: Build site
        run: npm run build
      
      - name: Setup Pages
        uses: actions/configure-pages@v4
      
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: "./dist"
      
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Verification checklist

  • Workflow file exists at .github/workflows/publish-to-github-pages.yaml
  • Repository has GitHub Pages enabled in Settings > Pages
  • Source is set to GitHub Actions in Pages settings
  • Build output directory matches path in upload artifact step
  • Tests run before deployment
  • No hardcoded secrets in workflow
  • Concurrency controls configured
  • Using single deployment method (Actions only, not classic Pages)

Trade-offs

  • Trigger strategy: Use push triggers for current docs, tag triggers for releases
  • Path filters: Customize paths array to trigger only on relevant changes
  • Node version: Use LTS versions (18, 20) for stability
  • Build output: Common paths are ./dist, ./build, ./public, ./out