Skip to content
KB4IT Help

Publish on GitHub Pages

How-to guide Publishing advanced
On this page

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.