Building a static HTML site

ubc build html renders your project into a self-contained static website — one HTML page per indexed document, plus the assets those pages need. It is ubc doing the rendering, not Sphinx: there is no conf.py, no extension loading and no Python environment involved, so the whole site comes out of the same index the editor and ubc check already use.

Caution

ubc build html is in alpha.

The command works and is under active development, but the emitted markup, the theming surface and the available options may still change between releases, so it is not yet recommended for production builds. Pin your ubc version if you depend on the output, and see Differences from a Sphinx build for what a site built this way does not yet match in a full sphinx-build.

We would love your feedback.

Quickstart

Run the command from anywhere inside your project:

ubc build html

It discovers the closest ubproject.toml, indexes the project, and writes the site next to that file:

Building index for: /home/me/project/ubproject.toml
Processing 3 files
3 page(s): 3 rendered, 0 reused; 3 written, 0 unchanged; 5 asset(s).
Site written to: /home/me/project/_build/html
Root page: /home/me/project/_build/html/index.html
Done in 0.12s

The last two lines are the ones you want: the site directory, and the page to open first.

Principal options

Option

What it does

[PATH]

The project root to build. Defaults to the current directory.

-o, --output <DIR>

Where to write the site. Defaults to _build/html under the project root; a relative path is resolved against the current directory.

-w, --show-warnings

Print the detail of every build and indexing warning (see Warnings).

--fresh

Re-render every page, ignoring any existing build manifest.

--strict-sources

Fail if a source file changes during the build, instead of re-indexing and retrying once.

--no-cache

Index from scratch rather than reading the on-disk cache. It implies --fresh.

-c, --config <TOML>

A configuration override, repeatable — for example -c 'build_tags = ["html"]'.

-v / --verbose additionally names the client-asset bundle the binary carries — the Mermaid, highlight.js and KaTeX versions, and the bundle’s content hash — which is what to quote when the rendered output looks stale or unexpected.

Run ubc build html --help for the complete list.

The output

Each document maps straight to a file: an indexed document at docname guide/setup becomes guide/setup.html — the source layout is mirrored, with no guide/setup/index.html rewriting — and everything shared lives under _static/.

It has no server-side component of any kind. Opening index.html straight from disk — a file:// URL — gives you the whole site, including full-text search, which is what makes a built site usable on an air-gapped machine or straight out of a ZIP file. See Search for what the search does and the three files it adds.

Pages that are no longer produced — because you deleted or renamed a document — are removed from the output directory on the next build, which is reported as Removed N stale file(s). The build only prunes a directory it created itself (or one an earlier ubc build html made); pointed at some other non-empty directory it writes the pages and warns instead of deleting anything.

Rebuilds

Rebuilds are incremental in two independent steps, and the count line reports both:

3 page(s): 0 rendered, 3 reused; 0 written, 3 unchanged; 5 asset(s).
rendered / reused

Whether each page’s body had to be rendered again. A page whose inputs are unchanged has its stored body reused.

written / unchanged

Whether the assembled page differed from what is already on disk. Identical output is not rewritten, so file timestamps stay put and tools watching the directory are not woken for nothing.

The two are separate, and the second is the stricter one. --fresh re-renders every page but still byte-compares the result, so a fresh build of unchanged sources honestly reports 3 rendered, 0 reused; 0 written, 3 unchanged.

Reach for --fresh when you want to rule the manifest out — after upgrading ubc, or when a page looks stale. --no-cache goes one step further and re-indexes from scratch as well.

If a source file changes during the build, the build re-indexes and retries once rather than emitting a half-stale site. --strict-sources turns that into an error instead, which is the right setting for a release pipeline where a moving source tree means something is wrong.

Warnings

The build reports two independent counts.

Indexing warnings are the ordinary project diagnostics — the same findings ubc check reports.

Build warnings are raised by the render phase itself and all carry a build.* code: an unreadable extra_css file, a diagram file that cannot be resolved, a directive or role ubCode has no renderer for, a search index that has grown large. The ones tied to a [build.html] setting are documented with that setting on the [build.html] configuration page. All of them use the ordinary lint configuration, so you can silence one by code or by message.

Both counts are summarised by default and detailed with -w / --show-warnings:

$ ubc build html -w
3 page(s): 1 rendered, 2 reused; 1 written, 2 unchanged; 5 asset(s).
Found 1 build warning(s).
[build.directive_unhandled]
  acks: 1 site rendered as a placeholder — no handler for this directive yet (at index:35)
Site written to: /home/me/project/_build/html
Found 1 indexing warning(s).
[std.ref]
  --> index.rst:39:10
  undefined label: 'nowhere-at-all'
Root page: /home/me/project/_build/html/index.html
Done in 0.08s

Important

Neither count fails the build today. ubc build html exits 0 whatever it reports: a build warning means the site is degraded but complete, and this subcommand carries no --deny or --max-warnings policy flags.

To gate a pipeline on your project’s diagnostics, run ubc check or ubc build index alongside the build — those do have the exit policy — and treat the site build as the artifact step.

Configuring the site

Everything about how the site looks and what it contains is configured under [build.html] in ubproject.toml:

[build.html]
title = "My Project Docs"
logo = "_static/logo.svg"
extra_css = ["_static/theme.css"]

See the HTML site configuration page for every option, and in particular:

Where it differs from Sphinx

A site built by ubc is not yet a drop-in replacement for the output of a full sphinx-build. The user-visible differences are registered, one entry each, on Differences from a Sphinx build — read that page before switching a published site over.