Skip to content

Deploying

luaudocs build emits a static site at .luaudocs/.vitepress/dist, so any static host serves it as-is.

GitHub Pages

Run luaudocs init if you have not: it writes this workflow to .github/workflows/docs.yml (and skips it when that file already exists), with the docs-directory paths following your [docs] dir:

yaml
name: Docs
on:
  push:
    branches: "main"
permissions:
  contents: read
  pages: write
  id-token: write
concurrency:
  group: pages
  cancel-in-progress: false
jobs:
  publish:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with: { node-version: "22" }
      - uses: actions/cache@v4
        with:
          path: |
            ~/.npm
            .luaudocs/node_modules
          key: ${{ runner.os }}-luaudocs-0.2.0
      - id: pages
        uses: actions/configure-pages@v6
      - run: npx luaudocs@0.2.0 build --url "${{ steps.pages.outputs.base_url }}"
      - uses: actions/upload-pages-artifact@v5
        with: { path: ".luaudocs/.vitepress/dist" }
      - id: deployment
        uses: actions/deploy-pages@v5

Required repository setting

Set the repository's Pages source to GitHub Actions. The site deploys from the workflow run, so there is no gh-pages branch to serve from.

The project needs no luaudocs.toml and no committed .luaudocs/: the same defaults that gave you a site locally apply on the runner, and the build generates the site there. Anything you do commit wins over those defaults.

Two steps the workflow does not need: a toolchain action (Node is the only setup), and an install step (build runs npm install in the docs directory whenever the VitePress it pins is not already resolvable there). The actions/cache step prevents redundant package installations on subsequent runs.

Two details worth knowing:

  • --url takes the URL configure-pages reports, so project-pages base paths and custom domains resolve straight from the Pages settings. It overrides [docs] url.
  • The version is pinned. init writes the version it scaffolded with, in both the cache key and the npx call, preventing upstream releases from altering your deployment behavior. You own this workflow file: update the pinned version as you would any other CI dependency.

Other CI

Nothing about build is Pages-specific: run it, then publish .luaudocs/.vitepress/dist however your host wants it. Three things matter in a pipeline:

  • --strict promotes warnings to failures, so a stale @within or a mistyped @param fails the job instead of shipping (what each one means). luaudocs build --emit-only --strict is the same validation without the VitePress render, which makes it a good pull request gate.
  • Pre-install to use another package manager. The automatic docs-directory install is npm's. For another package manager or your own cache keys, run luaudocs build --emit-only first: it writes the generated package.json without needing VitePress. Install against that, then run the full build, which finds the packages already resolvable and installs nothing.
  • Cache Lute. Reading Luau sources needs Lute, which build downloads on first use. Caching its download directory saves download time on cold CI runners, and runners without internet access can set LUAUDOCS_LUTE to point to a pre-installed Lute binary.

Base path vs. custom domain

The workflow above settles both through --url. Setting it by hand instead:

toml
# user.github.io/repo/: the path becomes the
# site base, so assets and links resolve
[docs]
url = "https://user.github.io/repo/"
toml
# also enter the domain in the repository's Pages
# settings, and point a DNS CNAME at user.github.io
[docs]
url = "https://docs.example.com"

TIP

Deploying from Actions needs no CNAME file. The domain lives in the Pages settings and nothing force-pushes a branch over it, so a public/CNAME is optional rather than load-bearing: this site keeps one, and a project without one deploys just the same.