Featurevisor

Integrations

GitHub Pages

GitHub Pages can host your datafiles, and the Catalog beside them, published by a GitHub Actions workflow.

This page builds on GitHub Actions. Set up its project, .nvmrc and checks workflow first, then use the publish workflow below in place of the one there.

Publish the datafiles

This workflow runs on every push to main or master. It checks, builds, pushes the state, then publishes the datafiles directory to GitHub Pages:

.github/workflows/publish.yml
name: Publish
on:
push:
branches:
- main
- master
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: featurevisor-publish
cancel-in-progress: false
jobs:
publish:
name: Publish
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm ci
- name: Lint
run: npx featurevisor lint
- name: Build
run: npx featurevisor build
- name: Test specs
run: npx featurevisor test
- name: Git configs
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Push back to origin
run: |
git add -A .featurevisor
if ! git diff --cached --quiet; then
git commit -m "[skip ci] Revision $(cat .featurevisor/REVISION)"
fi
git push origin "HEAD:${{ github.ref_name }}"
- name: Create index.html
run: echo "<html><body>It works.</body></html>" > datafiles/index.html
- name: Setup Pages
uses: actions/configure-pages@v6
- name: Upload artifact
uses: actions/upload-pages-artifact@v5
with:
path: 'datafiles'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5

The index.html step only gives the site a page at its root. The workflow pushes the state files before it deploys. If the push is rejected, run it again from the latest main and never force push. If the deployment fails, keep the pushed state and run it again. The concurrency and branch protection rules from GitHub Actions apply here too.

Each target's datafile is then at its path under the site:

  • https://<username>.github.io/<repo>/featurevisor-all.json
  • https://<username>.github.io/<repo>/production/featurevisor-web.json, with environments

A custom domain replaces the first part of the URL. Applications fetch these URLs with an SDK.

Publish the Catalog

To publish the Catalog beside the datafiles, export it into the datafiles directory before the upload. Use this workflow instead of the one above, not alongside it:

Publish workflow with Catalog
.github/workflows/publish.yml
name: Publish with Catalog
on:
push:
branches:
- main
- master
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: featurevisor-publish
cancel-in-progress: false
jobs:
publish:
name: Publish
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm ci
- name: Lint
run: npx featurevisor lint
- name: Build
run: npx featurevisor build
- name: Test specs and save report
run: npx featurevisor test --json > test-report.json
- name: Git configs
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Push back to origin
run: |
git add -A .featurevisor
if ! git diff --cached --quiet; then
git commit -m "[skip ci] Revision $(cat .featurevisor/REVISION)"
fi
git push origin "HEAD:${{ github.ref_name }}"
- name: Export Catalog
run: npx featurevisor catalog export --out-dir=./datafiles --hash-router --test-report=./test-report.json
- name: Setup Pages
uses: actions/configure-pages@v6
- name: Upload artifact
uses: actions/upload-pages-artifact@v5
with:
path: 'datafiles'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5

Keep fetch-depth: 0 on checkout. Fetching the full history lets the exported Catalog show earlier changes, not only the latest commit.

For a user or organization Pages site, or a custom domain serving at its root, keep the default catalogBasePath: '/'. For a repository site, set catalogBasePath: '/your-repository-name/' in featurevisor.config.js. Hash routing lets direct entity links work without a server fallback.

Keep uploading the entire datafiles directory, including the generated Catalog HTML, assets and data. On a custom domain such as https://flags.example.com/, the Catalog opens at that URL, entity links use https://flags.example.com/#/features/checkout, and SDK datafiles remain at https://flags.example.com/featurevisor-all.json. Do not overwrite the generated index.html with the placeholder.

Use --hash-router because GitHub Pages serves a 404 page for missing paths. The fragment stays in the browser, so opening or refreshing an entity link requests the existing Catalog directory instead of a missing HTML file. A custom 404 page alone does not configure a successful HTML fallback.

Keep the order build, test, then catalog export, and do not rebuild or change definitions between the report and export, because the report's fingerprint includes the allocation state the build writes. A failed test must stop deployment.

Catalog exports include project definitions, Git history and the supplied test results. Reports can contain test contexts, expected values and actual values. A GitHub Pages site is public unless your plan offers access control for Pages, so a Catalog published this way shows every definition, unlaunched work included, to anyone with the URL. Use private hosting when that matters. Keep its generated UI and data together, and follow the export retention guidance when updating an existing deployment.

Previous
GitHub Actions