Skip to content

AgentEnder/nx-github-pages

Repository files navigation

Nx Github Pages

This project was generated using Nx.

A simple Nx plugin to enable deploying a static project to Github Pages.

Note

This plugin was formerly published as @nx-dotnet/nx-ghpages. It was moved due to not being relevant to .NET and to decouple the releases. To view previous versions and changelogs checkout the nx-dotnet repo

Installation

To install the plugin, run:

nx add nx-github-pages

Usage

Pick a project to deploy and run:

nx g nx-github-pages:configuration --project=<project-name>

After the configuration is generated, you can deploy the project by running:

nx run <project-name>:deploy

Pull Request Preview Deployments

The deploy executor can also publish a pull request preview into a subdirectory of your gh-pages branch (e.g. https://<you>.github.io/<repo>/pr/123/) and post an updating comment on the pull request with the preview URL. The same deploy target handles both modes — it auto-detects a PR context from the environment (GITHUB_REF=refs/pull/<N>/merge or PR_NUMBER) and switches to preview mode when one is present. A companion cleanup-preview executor removes stale previews on a schedule.

Generate a preview-enabled target

nx g nx-github-pages:configuration \
  --project=<project-name> \
  --preview \
  --previewUrl=https://<you>.github.io/<repo> \
  --addCleanupTarget

This creates two things on the project:

{
  "deploy": {
    "executor": "nx-github-pages:deploy",
    "options": {
      "preview": { "url": "https://<you>.github.io/<repo>" },
      "syncWithBaseBranch": true
      /* ...any other deploy options... */
    }
  },
  "cleanup-previews": {
    "executor": "nx-github-pages:cleanup-preview",
    "options": {}
  }
}

syncWithBaseBranch is enabled when --preview is passed so that non-PR deploys merge into gh-pages rather than force-pushing — that preserves the pr/* subdirectories published by previous preview runs.

Preview executor options

All standard deploy options still apply. Preview-specific options live under a preview object:

Option Default Description
preview.pathPrefix pr/${PR_NUMBER ?? GITHUB_SHA} Subdirectory on the target branch to deploy into.
preview.url Derived from CNAME or https://<owner>.github.io/<repo> Base URL used in the PR comment. The pathPrefix is appended automatically.
preview.comment true Whether to upsert a PR comment with the preview link via the GitHub REST API.

When the executor detects a PR context, it switches into preview mode: it clones the target branch, copies the build output into <pathPrefix>/, and pushes without force — so sibling PR folders are preserved. Outside of a PR (e.g. a push to main), the same target runs a standard deploy instead.

⚠️ Your build MUST use a matching base URL

Since the preview is served from a subdirectory, your framework needs to know about that subdirectory at build time, or every asset will 404 after deploy. The plugin enforces this by scanning the build output for references to the path prefix before pushing. If the check fails you'll get a descriptive error pointing at the right base URL flag for your framework.

Pass the prefix to the build step as an environment variable and consume it in your framework config:

PATH_PREFIX="/pr/${PR_NUMBER:-$GITHUB_SHA}"

# Vite
npx nx build my-app -- --base="$PATH_PREFIX/"

# Next.js (in next.config.js: basePath: process.env.NEXT_BASE_PATH)
NEXT_BASE_PATH="$PATH_PREFIX" npx nx build my-app

# Angular
npx nx build my-app -- --base-href="$PATH_PREFIX/"

# Astro
npx nx build my-app -- --base="$PATH_PREFIX"

Then deploy as usual — preview mode is selected automatically when GITHUB_REF/PR_NUMBER indicate a pull request:

npx nx deploy my-app

If you serve previews through a CDN rewrite or some other scheme where the prefix legitimately does not appear in the built files, bypass the check with NX_GITHUB_PAGES_SKIP_BASE_URL_CHECK=true.

Required environment

The executor auto-detects context from standard GitHub Actions environment variables:

Variable Source Purpose
GITHUB_REPOSITORY Actions runner Owner/repo for the PR comment.
GITHUB_REF Actions runner Extracts the PR number from refs/pull/<N>/merge. Presence of a PR number activates preview mode.
PR_NUMBER Set it yourself Fallback for PR number; used in pathPrefix. Presence activates preview mode.
GITHUB_SHA Actions runner Included in the PR comment; fallback path prefix.
GH_TOKEN secrets.GITHUB_TOKEN or PAT Auth for git push and the Octokit comment.

Example GitHub Actions workflow

name: PR Preview
on:
  pull_request:
    branches: [main]

jobs:
  preview:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci

      - name: Build with preview base URL
        run: npx nx build my-app -- --base="$PATH_PREFIX/"
        env:
          PATH_PREFIX: /pr/${{ github.event.number }}

      - name: Deploy preview
        run: npx nx deploy my-app
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.number }}

Cleaning up stale previews

Add a scheduled workflow that runs the cleanup-preview executor. It clones the deployment branch, removes pr/* directories older than maxAgeDays (default 7), and updates each corresponding PR comment to say the preview has been cleaned up.

name: Cleanup PR Previews
on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:
    inputs:
      all:
        description: 'Cleanup every preview regardless of age'
        type: boolean
        default: false

jobs:
  cleanup:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx nx run my-app:cleanup-previews ${{ inputs.all && '--all' || '' }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

cleanup-preview options: remote, baseBranch (default gh-pages), pathPrefix (default pr), maxAgeDays (default 7), all (default false), updatePrComments (default true).

About

A small Nx plugin to simplify deploying static site projects to github pages

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors