GitHub Pages MVP
Use this setup when a repo already has a docs or site build command and you
want GitHub Pages builds checked on pull requests and deployed from the release
branch.
The important boundary is: @async/pipeline owns the Pages job id, target task,
triggers, artifact path, and deploy policy; async/actions/pages owns Pages
configuration, artifact validation, upload, and deployment.
This MVP deliberately skips package publishing, preview packages, release
doctor gates, source-impact matrices, and custom multi-site routing. Add those
only when the repo needs them.
Minimum Files
Commit these files:
package.json
pnpm-lock.yaml
pipeline.ts
.github/workflows/async-pipeline.yml
.locks/pipeline/github-workflow.lock.json
Keep local run state and built Pages output out of Git:
.async/
.tmp/
Before relying on deploys, configure the repository's Pages source to GitHub
Actions in repository settings.
Site Task Rules
The site task should:
- build from committed docs or source files,
- write static output to
.async/pagesfor the MVP, - declare
.async/pages/**as an output, - avoid writing package tarballs or local-only state into the Pages artifact.
For a package repo, the site task can depend on build so API docs, examples,
or typed output are current before Pages uploads.
Minimal Pipeline
Create pipeline.ts at the repo root:
import { definePipeline, job, sh, task, trigger } from "@async/pipeline";
export default definePipeline({
name: "docs-site",
cache: "file:local",
sync: {
github: {
pages: {
target: "docs.site",
build: { kind: "static", path: ".async/pages" }
}
}
},
triggers: {
pr: trigger.github({ events: ["pull_request"] }),
main: trigger.github({ events: ["push"], branches: ["main"] }),
manual: trigger.manual()
},
namedInputs: {
docs: [
"docs/**",
"README.md",
"package.json",
"pnpm-lock.yaml"
]
},
tasks: {
"docs.site": task({
inputs: ["docs"],
outputs: [".async/pages/**"],
cache: false,
run: sh`pnpm docs:build`
})
},
jobs: {
verify: job({
target: "docs.site",
trigger: ["pr", "main", "manual"]
})
}
});
sync.github.pages: true infers a target from pages, docs.site, docs, then build-pages, uploads .async/pages as a static artifact, builds on pull requests, and deploys from main or selected manual dispatch. Object form lets the repo set target, job, build, artifactName, environment, and trigger settings explicitly.
The sync-level Pages job runs async-pipeline run-task <target> before calling async/actions/pages. The paired deploy job is skipped on pull requests and uses the github-pages environment on non-PR events.
Static Build Script
For a very small docs site, a package script can copy prepared static files:
{
"scripts": {
"docs:build": "rm -rf .async/pages && mkdir -p .async/pages && cp -R docs/. .async/pages/"
}
}
For a framework docs site, make the framework output path .async/pages, or
copy its output there as the last step.
Prerender Variant
Use build.kind: "prerender" when the task already rendered static HTML from an app route tree:
sync: {
github: {
pages: {
target: "docs.site",
build: {
kind: "prerender",
path: ".async/pages",
validateIndex: true,
spaFallback: true
}
}
}
}
Prerender still means the task produced static files. It is not a long-running
server deployment.
Generate The Workflow
Run the site build locally:
pnpm async-pipeline run-task docs.site
Write and check the GitHub workflow:
pnpm async-pipeline sync github generate
pnpm async-pipeline sync github check
Inspect the Pages jobs without deploying:
pnpm async-pipeline github plan --job pages --event pull_request --format json
pnpm async-pipeline github plan --job pages --event workflow_dispatch --selected-job pages --format json
pnpm async-pipeline github run --job pages --event pull_request --mock-network
Commit the workflow and lock:
.github/workflows/async-pipeline.yml
.locks/pipeline/github-workflow.lock.json
Deploy Procedure
- Merge the verified docs or package change to
main. - Let the Pages deploy job run from the
mainpush, or dispatch thepages
job manually.
- Check the Pages deployment URL from the workflow summary or repository
Pages settings.
For package repos that also need npm releases and pull request preview
packages, use the combined package repo MVP.