Deploy ProtoWiki to GitHub Pages
ProtoWiki is a static SPA. CI builds and deploys on push to main and on
pull requests — you rarely need npm run build locally. For day-to-day
prototyping, use npm run dev (see
protowiki-getting-started).
Golden path (template-first)
Default recommendation for designers/PMs:
- Use
wikimedia/ProtoWikias a template (copy into your own repo). - Build locally with
npm run dev. - Push to
mainin your copied repo to deploy production. - Use branch + PR previews only when you want parallel in-progress links or review.
Do not require a fork or upstream write access for the standard deploy flow.
Local dev vs production build
| Command | When |
|---|---|
npm run dev |
Default — HMR at http://localhost:5173, Vite base: '/'. |
npm run build |
Optional — CI runs this. Locally only to reproduce Pages or debug deploy issues. |
npm run preview |
After a local build — serves dist/ with the same base path as the build. |
Reproducing GitHub Pages locally
When something works in dev but breaks on Pages:
PROTOWIKI_BASE='/ProtoWiki/' npm run build # match your repo name casing
npm run preview # http://localhost:4173
For a PR preview subpath:
PROTOWIKI_BASE='/ProtoWiki/pr-preview/pr-99/' npm run build
npm run preview
The build:
- Runs Vite with
PROTOWIKI_BASE(see Base path). - Code-splits per route (each prototype gets its own JS chunk).
- Copies
public/.nojekyllintodist/so GitHub Pages does not run Jekyll (Jekyll drops Vite chunks whose names start with_, e.g._plugin-vue_export-helper-….js). - Copies
dist/index.htmltodist/404.htmland prependspublic/gh-pages-preview-404.jsso GitHub Pages can serve the SPA shell for production deep links and redirect…/pr-preview/pr-N/…deep links into the preview base.public/gh-pages-restore.jsis injected at the top of<head>on every build so the preview index can restore the stashed path before Vue Router starts.
Base path
Vite's base decides the prefix for asset URLs and the router base.
Defaults to /protowiki/ when unset. CI sets it from the repository name.
PROTOWIKI_BASE='/ProtoWiki/' npm run build
PROTOWIKI_BASE='/ProtoWiki/pr-preview/pr-42/' npm run build # PR preview
PROTOWIKI_BASE='/' npm run build # custom domain at root
GitHub Pages setup (one-time per deployed repo)
| Setting | Value |
|---|---|
| Pages source | Deploy from a branch → gh-pages / / (root) |
| Actions permissions | Settings → Actions → General → Workflow permissions → Read and write |
Do not use the Pages option labeled “GitHub Actions” for this repo —
previews deploy to the gh-pages branch via
rossjrw/pr-preview-action.
Order for a new repo: enable Actions permissions → push (or merge) to
main once so deploy.yml creates gh-pages → set Pages to Deploy from a
branch as above. Until gh-pages exists, that branch will not appear in the
Pages dropdown.
Production deploy
.github/workflows/deploy.yml on push
to main:
- Checks out,
npm ci,npm run buildwithPROTOWIKI_BASE=/${{ repository.name }}/. - Publishes
dist/to thegh-pagesbranch root viaJamesIves/github-pages-deploy-action(clean-exclude: pr-preview/,force: falseso open PR previews are not wiped).
Production URL:
https://<owner>.github.io/<RepoName>/
PR preview deployments
.github/workflows/preview.yml on
pull_request (opened, reopened, synchronize, closed):
- Builds with
PROTOWIKI_BASE=/<RepoName>/pr-preview/pr-<number>/(trailing slash required). - Deploys to
gh-pagesunderpr-preview/pr-<number>/viarossjrw/pr-preview-action@v1. - Leaves a sticky comment on the PR with the preview link (and QR code).
- Removes the preview folder when the PR is closed.
Preview URL:
https://<owner>.github.io/<RepoName>/pr-preview/pr-<number>/
Preview deep links (e.g. …/pr-preview/pr-3/template-chrome) work after a
main deploy: GitHub only reads root 404.html, which preview CI does not
update. The root file redirects into the preview base via sessionStorage; the
preview index.html restores the path before the router boots. Merging preview-only
changes without deploying main leaves deep links broken until the next production
deploy. Hard-refreshing a preview deep URL briefly hops through the gallery (no
server-side SPA rewrite on GitHub Pages).
Deploy path decision tree
Use this three-way decision:
- Template/new repo (default):
- If the user does not have write access to
wikimedia/ProtoWiki, tell them to click Use this template onwikimedia/ProtoWiki(instead of creating a brand-new repo from scratch). - Ask for the URL of their template copy, then deploy there.
- Push to
mainfor production deploy. - For preview links, push your changes to a separate branch and open a
pull request from that branch to
mainin the same repo (pr-preview/pr-<number>/).
- If the user does not have write access to
- Upstream collaborator (
wikimedia/ProtoWikiwrite access):- Optional maintainer flow: branch in upstream and open PR to
main.
- Optional maintainer flow: branch in upstream and open PR to
- No GitHub account yet:
- Prototype locally now; create account/repo only when ready to deploy.
- Agent can guide UI + commands without owning GitHub credentials.
Agent deploy playbook (automated vs guided)
At deploy time, always declare capability mode first:
- Automated mode: "I can do this for you end-to-end."
- Guided mode: "I cannot access GitHub here; I will guide you step-by-step."
Then run:
- Find the current state:
- Does the user have write access to
wikimedia/ProtoWiki? - If not, are they already in a template copy repo?
- Does the user have write access to
- Confirm destination repo (
your copyby default; upstream only if requested and permitted).- If the user lacks upstream write access and has no copy yet, instruct them
to create one via Use this template on
wikimedia/ProtoWiki, then ask for that repo URL and proceed there. - Prefer this route over asking users to create/configure a brand-new repo manually.
- If the user lacks upstream write access and has no copy yet, instruct them
to create one via Use this template on
- Confirm deploy intent:
mainpush for production update, or- separate branch + pull request for preview.
- Never use a direct
mainpush when the user asked for a preview link.
- Check prerequisites:
- repo exists,
- Actions workflow permissions are read/write,
- Pages source is Deploy from a branch →
gh-pages/ / (root) (not “GitHub Actions”).
- Execute (automated) or provide one copy/paste command block at a time (guided).
- Return final URL(s): production and/or PR preview.
When guiding users, include the one-time setup (below) if any of these apply:
the repo was not created from the ProtoWiki template, the user has never deployed before, Pages is
still on the default source, workflows succeed but the public URL 404s, or PR
preview comments appear but preview URLs 404. Skip repeating it once the user
confirms Pages already uses gh-pages at root.
Guided mode: one-time GitHub setup (give users these steps)
Use plain language. One step at a time; ask the user to confirm before the next.
- Workflow permissions — In the repo on GitHub: Settings → Actions → General → Workflow permissions → choose Read and write permissions → Save.
- First production deploy — Push or merge to
main(or walk them through their first commit tomain). In Actions, wait until Deploy to GitHub Pages finishes successfully. That run creates thegh-pagesbranch. - GitHub Pages source — Settings → Pages:
- Under Build and deployment, Source: Deploy from a branch (not “GitHub Actions”).
- Branch:
gh-pages, folder / (root) → Save. - If
gh-pagesis missing, go back to step 2 and wait for the workflow.
- Check the live site — Open
https://<username>.github.io/<repo-name>/(match repo name casing). It can take a minute after saving Pages settings.
Do not tell users to pick GitHub Actions as the Pages source — CI still
writes files to gh-pages; previews depend on that branch layout.
For pull request previews, the same Pages setup applies; after step 3, open a
pull request and use the preview link from the bot comment (under
…/pr-preview/pr-<number>/).
Guided mode communication style (non-technical users)
When guiding designers/PMs, prefer plain language over Git jargon:
- On first deploy (or if the site 404s after a green workflow), walk through Guided mode: one-time GitHub setup before debugging build flags or base paths.
- Say "your project copy" instead of "fork/upstream remote" unless needed.
- Say "make a new branch to test an idea" instead of "create a feature branch".
- Always say "pull request" in full (do not shorten to "PR").
- Say "deploy your prototype" instead of "deploy to GitHub Pages" when context is clear.
- Give one action at a time with an explicit success check ("Paste the link you see").
- Avoid unexplained terms like "rebase", "upstream", "HEAD", "origin", "detached", "CI".
Use this sentence starter in guided mode: "I'll walk you through this step-by-step."
Workflow coverage matrix
| Scenario | Workflow | Result |
|---|---|---|
Push to main in any ProtoWiki-based repo |
deploy.yml |
Updates production site root |
| PR inside same repo | preview.yml |
Creates/removes pr-preview/pr-<number>/ |
| External fork PR into upstream | Not enabled by default in this strategy | Use template-first repo previews; upstream path is collaborator-only unless extra fork-preview workflow is added |
Custom domain
If you point a custom domain (e.g. protowiki.example.org) at Pages:
- Set
PROTOWIKI_BASE='/'(or whatever path the domain serves). - Add a
CNAMEfile atpublic/CNAMEcontaining the domain. - Configure DNS as documented at https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site.
Sharing a single prototype
Once deployed:
https://<org>.github.io/ProtoWiki/ ← gallery
https://<org>.github.io/ProtoWiki/template-chrome ← prototype
https://<org>.github.io/ProtoWiki/template-chrome?theme=dark
https://<org>.github.io/ProtoWiki/template-chrome?skin=mobile
https://<org>.github.io/ProtoWiki/template-app-article?os=ios
https://<org>.github.io/ProtoWiki/template-app-chrome?os=android&theme=dark
https://<org>.github.io/ProtoWiki/template-app-article?os=auto
The ?skin=, ?theme=, and ?os= URL params are handled at boot — paste them
into review tickets to pin a specific preview. ?os=auto|ios|android masks the
saved App OS preference without changing it.
Troubleshooting
- 404 on a deep link (production). The
404.htmlcopy step invite.config.tsmust run; verifydist/404.htmlexists after build (SPA shell + pr-preview preamble script). - 404 or blank page on a route inside a PR preview. Root
gh-pages/404.htmlmust come from a recent main deploy (preview workflows do not update it). Push or merge tomain, wait for Pages, then hard-refresh the preview deep link. - Preview deep link shows the gallery with
?template-…in the URL. That was an older?/redirect experiment; current builds usesessionStorageand should end on…/pr-N/template-…with no query hack. - Preview deep link always lands on the gallery (URL is only
…/pr-N/). Check that root404.htmlincludes the pr-preview preamble and that restore skips deep paths on the 404 page (sosessionStoragesurvives). The preamble must also stop the production bundle in404.htmlfrom booting (wrongPROTOWIKI_BASE); only the previewindex.htmlshould run Vue. - Asset URLs missing the base path. Check
import.meta.env.BASE_URLmatches the deployed URL prefix; the router uses it. - Blank app on Pages or preview. Wrong
PROTOWIKI_BASE(missing repo name prefix or trailing slash). Reproduce withnpm run build+npm run previewusing the same base as CI. - The dev server works but the deployed build is broken. Run
npm run previewlocally after a production build — see Reproducing GitHub Pages locally. - PR preview comment but 404 at the URL. Pages source must be Deploy
from branch
gh-pages, not “GitHub Actions”. Wait a minute for Pages to rebuild after the action commits. - Main deploy deleted PR previews.
deploy.ymlmust keepclean-exclude: pr-preview/andforce: falseon JamesIves. - Blank page; 404 on
_plugin-vue_export-helper-….jsor other_*assets. Missing.nojekyllat the site root — ensurepublic/.nojekyllexists and redeploymain(and re-run the PR preview workflow if needed).