GitHub can build your site and publish it each time you push a change. You keep only the documents and settings in git; the website is made by GitHub Actions.
Prepare the repository
Put the knowledge base at the root of a GitHub repository, or in a folder of an existing one:
config/repo.json
source/...
Do not commit the generated files. Add a .gitignore next to config/:
var/
target/
Keep "source": "source" and "target": "target" in repo.json. They are relative to the knowledge base folder, so the build works on any computer. kb4it create writes them that way.
Sources are published by default
KB4IT copies your .md files to the website, so readers can see the source of each page. Set "publish_sources": false in repo.json if they should not.
Tell KB4IT where the site lives
Add the address GitHub gives the site to repo.json:
"site_url": "https://<user>.github.io/<repository>/"
With it, the build writes sitemap.xml and robots.txt for search engines, a canonical link in every page, and the feed of the blog theme. See site_url.
Add the workflow
Create .github/workflows/site.yml:
name: site
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- id: kb4it
uses: t00m/KB4IT@vX.Y.Z
with:
config: config/repo.json
- uses: actions/upload-pages-artifact@v5
with:
path: ${{ steps.kb4it.outputs.target }}
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v5
The KB4IT action installs KB4IT, checks the documents with kb4it verify and builds the site; its target output is the folder to publish. If the knowledge base is in a folder, say docs-site/, use config: docs-site/config/repo.json.
Pin the version
@vX.Y.Z builds with KB4IT X.Y.Z, so the site does not change when a new KB4IT is released. Upgrade on purpose, after a local build.
Without the action
The same build with plain commands, for example to run extra kb4it commands in the job:
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- run: pip install KB4IT==X.Y.Z
- run: kb4it verify config/repo.json
- run: kb4it build config/repo.json
- uses: actions/upload-pages-artifact@v5
with:
path: target
Turn on GitHub Pages
In the repository on GitHub, open Settings, then Pages, and under Build and deployment set Source to GitHub Actions. Or from a terminal with the GitHub CLI:
gh api -X POST repos/OWNER/REPO/pages -f build_type=workflow
Push a change. The site appears at https://OWNER.github.io/REPO/. The Actions tab shows each build and its log.
Check broken documents in CI
The action runs kb4it verify before building, so a document that cannot be read or a broken link stops the publish. Set verify: false to skip it, or "fail_on_invalid": true in repo.json to make the build itself strict.
This help is published exactly this way; see .github/workflows/help.yml in the KB4IT repository.
Publish versioned help
With apphelp versions, every build adds its own folder and keeps the others. On GitHub Actions each run starts empty, so rebuild every released version from its git tag before the current one. Use the workflow without the action and replace its build steps with:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # all tags
- name: Build every released version, then the current one
run: |
for tag in $(git tag --list 'v*' --sort=version:refname); do
git worktree add "/tmp/$tag" "$tag"
if [ -f "/tmp/$tag/help/config/repo.json" ]; then
python3 - "/tmp/$tag/help/config/repo.json" "${tag#v}" <<'PY'
import json, sys
path, version = sys.argv[1], sys.argv[2]
conf = json.load(open(path, encoding="utf-8"))
conf["version"] = version
conf["target"] = "${{ github.workspace }}/help/target"
conf.setdefault("apphelp", {})["versions"] = {"enabled": True}
json.dump(conf, open(path, "w", encoding="utf-8"))
PY
kb4it build "/tmp/$tag/help/config/repo.json" --force
fi
done
kb4it build help/config/repo.json --force
Each tag is built with the KB4IT of the current commit, so old pages get the current look. Pin latest in repo.json while a new version is still in preparation.