- CSS 63.7%
- JavaScript 29.4%
- Python 5.4%
- HTML 1.5%
| buildtools | ||
| docs | ||
| static | ||
| templates | ||
| .gitignore | ||
| action.yml | ||
| AGENTS.md | ||
| README.md | ||
Docbuilder
A Forgejo custom action and Nix library that builds Asciidoc documentation into
a static HTML site with full-text Stork search. Designed to be reusable across
any repository that has a docs/ directory containing .adoc files.
Nix API
Docbuilder exposes two functions for use by other flakes:
mkSite — single docs tree
Builds a site from one docs/ directory:
inputs = {
docbuilder = {
url = "git+ssh://git@git.simple.fast/simplefast/docbuilder.git?shallow=1";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
};
outputs = { self, nixpkgs, flake-utils, docbuilder, ... }:
flake-utils.lib.eachDefaultSystem (system: {
packages.default = docbuilder.lib.${system}.mkSite {
docs-src = self + "/docs";
};
});
Parameters:
| Parameter | Required | Description |
|---|---|---|
docs-src |
yes | Path to the docs directory. Contains .adoc files and any project-specific assets. |
site-title |
no | Override site.nix title |
site-subtitle |
no | Override site.nix subtitle |
search-placeholder |
no | Override search input placeholder |
The output is a derivation with the static site contents directly in $out/.
mkMultiSite — unified site from multiple source trees
Builds a single site from a root docs directory plus docs from multiple source repositories. All pages share one Stork search index.
Use case: a central nixpkgs flake builds a sitewide docs site at
packages.simple.fast that aggregates documentation from every package.
# In nixpkgs flake.nix
nixpkgs-docs = callPackage ./pkgs/nixpkgs-docs {
docbuilder = docbuilder;
src = self;
sources = {
bot = inputs.bot-src;
pi = inputs.pi-mono;
skills = inputs.skills-src;
rfd = inputs.rfd-src;
};
};
# In pkgs/nixpkgs-docs/default.nix
{ docbuilder, lib, src, sources ? {} }:
let
# Auto-discover: include only sources with a docs/ directory containing .adoc files.
# The attr name becomes the URL path segment (e.g. "bot" -> /bot/).
hasAdocDocs = path:
builtins.pathExists path &&
builtins.length (
builtins.filter (name: lib.strings.hasSuffix ".adoc" name)
(builtins.attrNames (builtins.readDir path))
) > 0;
sections = lib.flatten (lib.mapAttrsToList (name: source:
lib.optional (hasAdocDocs (source + "/docs")) {
path = name;
docs-src = source + "/docs";
}
) sources);
in
docbuilder.mkMultiSite {
root.docs-src = src + "/docs";
inherit sections;
}
Parameters:
| Parameter | Required | Description |
|---|---|---|
root.docs-src |
yes | Path to the root docs directory. Must contain site.nix; may contain index.adoc and other .adoc files that become top-level pages. |
sections |
no | List of { path, docs-src } attrsets. Each docs-src is copied into <path>/ in the output. Sections with no .adoc files are silently skipped. |
site-title |
no | Override site.nix title |
site-subtitle |
no | Override site.nix subtitle |
search-placeholder |
no | Override search input placeholder |
Output structure
Given the nixpkgs config above (with bot, rfd having docs; pi and skills having none):
index.html # root docs: index.adoc
bot.html # root docs: bot.adoc (overview with links into bot/)
pi.html # root docs: pi.adoc
skills.html # root docs: skills.adoc
rfd.html # root docs: rfd.adoc
bot/
architecture.html # bot-src/docs/architecture.adoc
observability.html # bot-src/docs/observability.adoc
rfd/
001.html, 002.html, ... # rfd-src/docs/*.adoc
index.st # ONE Stork index across all pages
stork.js / stork.wasm
styles.css / fonts/
Cross-references between sections use relative links. From a root page, link to
a section page with link:bot/architecture.html[Bot Architecture]. From within
a section, link back with link:../pi.html[Pi].
Forgejo Action
Upload as artifact
Build docs and attach the site as a workflow artifact for download or use in later jobs:
# .forgejo/workflows/build-docs.yml
on:
push:
branches: [main]
pull_request:
jobs:
build-docs:
runs-on: nix
steps:
- uses: actions/checkout@v4
- name: Build documentation site
id: docbuilder
uses: https://git.simple.fast/Simple.Fast/docbuilder@main
- name: Upload site artifact
uses: actions/upload-artifact@v3
with:
name: docs-site
path: ${{ steps.docbuilder.outputs.site-path }}
Deploy via rsync
Build and push the site to a server in one job:
# .forgejo/workflows/deploy-docs.yml
on:
push:
branches: [main]
jobs:
deploy-docs:
runs-on: nix
steps:
- uses: actions/checkout@v4
- name: Build documentation site
id: docbuilder
uses: https://git.simple.fast/Simple.Fast/docbuilder@main
- name: Deploy to server
run: |
rsync -avz --delete \
${{ steps.docbuilder.outputs.site-path }}/ \
deploy@webserver.example.com:/var/www/docs/
Custom docs directory
If documentation lives somewhere other than docs/:
- uses: https://git.simple.fast/Simple.Fast/docbuilder@main
with:
docs-dir: src/documentation
Landing page
Docbuilder generates the landing page using niccup
(hiccup-style HTML generation in Nix). Configuration comes from a site.nix
file in the root docs directory:
# docs/site.nix
{
site-title = "My Project";
site-subtitle = "My Org";
search-placeholder = "Search docs…";
}
All fields are optional. Defaults are Documentation, empty, and Search <title>….
If index.adoc exists in the root docs, it becomes the landing page. Otherwise,
docbuilder generates a landing page with the site title and a search input.
Inputs
| Input | Default | Description |
|---|---|---|
docs-dir |
docs |
Path to docs directory relative to repo root |
Outputs
| Output | Description |
|---|---|
site-path |
Path to the static site root ready for serving or deployment |
How it works
- Copies the docs directory (or merged tree for
mkMultiSite) into the build sandbox - Recursively finds all
.adocfiles and converts each to HTML via asciidoctor - Preserves the folder structure in the output
- Copies binary assets (images, video, PDF) through, maintaining relative paths
- Reads
site.nixfrom root docs for landing page configuration - Generates landing page HTML via niccup with the configured title, subtitle, and search
- Builds a Stork full-text search index across all generated HTML (one index for the entire site)
- Bundles fonts, CSS, JS, and stork runtime into a self-contained output
Requirements
The runner must have Nix with flakes enabled. The runs-on: nix label must
map to a host with nix in PATH and experimental-features = nix-command flakes
configured.