[build.html]¶
HTML site configuration.
Branding, styling and the quality bar for the site produced by
ubc build html.
The built-in stylesheet exposes its colours, fonts and metrics as
--ubc-* CSS custom properties, which an extra_css file can
override.
Guide: HTML site.
- build.html.announcement¶
- Type:
- string
- Default:
""
A site-wide banner shown at the top of every page.
The value is inserted into the page as raw HTML, not escaped, so the banner can carry markup — a link, emphasis — and, equally, a malformed fragment reaches every page as written. The banner is one line tall and does not follow the page as it scrolls: block markup is clipped, and a value too long for the viewport can be scrolled towards its end but not always back to its start, so keep it to one short sentence. It is not hidden when the page is printed, though whether its colours print depends on the browser’s background-graphics setting. Unset or
""means no banner.
- build.html.copyright¶
- Type:
- string
- Default:
""
The site copyright statement.
Shown in each page’s footer as
Copyright © {value}— e.g. the value"2026, team useblocks"renders asCopyright © 2026, team useblocks. Pages without the site shell (no sidebar and no page-contents column) have no footer. Unset or""means no copyright line.
- build.html.deny¶
- Type:
- string
- Default:
"warning"
The lowest severity of finding that fails the build.
ubc build htmlreports two kinds of finding — render-phase build warnings and indexing diagnostics — and this is the single bar both are held to: any finding at or above this level fails the command with exit code 1. Defaults towarning, so any warning-or-worse finding fails the build;errorlets warnings through and fails only on errors, andnonenever fails. The site is written before the gate is applied either way, so a failing build can still be published for inspection.--denyon the command line overrides this for a single run, and codes silenced under[lint]never reach the gate.Values:
"none": Never fail on findings."info": Fail on any finding, informational ones included."warning": Fail on any warning-or-worse finding."error": Fail only on errors.
- build.html.extra_css¶
- Type:
- array of strings
- Default:
[]
Extra stylesheets to copy into the site and link on every page.
Paths are relative to this
ubproject.toml(or absolute). Each file is copied into the site’s_static/directory and linked AFTER the built-in stylesheet, in the order listed, so a later file wins over an earlier one and any of them wins over the built-in defaults. Two files with the same name are both copied, under distinct names. A file that cannot be read is reported as a build warning and skipped; the rest of the site still builds. Unset or empty means no extra stylesheets.
- build.html.extra_static¶
- Type:
- array of strings
- Default:
[]
Extra files and directories to copy into the site’s
_static/directory.For the files a stylesheet references — background images, fonts, icons — so that a
url(...)in anextra_csssheet resolves beside it. Nothing listed here is linked from the pages.Paths are relative to this
ubproject.toml(or absolute). A listed DIRECTORY has its CONTENTS copied, preserving their structure: with the entryassets, the fileassets/img/bg.pnglands at_static/img/bg.png. A listed FILE lands flat at_static/{filename}. INSIDE a listed directory, dot-prefixed files and directories are skipped and symlinked directories are not descended into; listing such a path as an entry publishes it, because naming it is consent.A destination already claimed — by a built-in site asset, by an
extra_css/logo/faviconcopy, or by an earlier entry — is reported as the build warningbuild.extra_static_collisionand that file is skipped: never renamed, never overwritten, because the destination spelling is what a stylesheet’surl(...)refers to. A file that cannot be read isbuild.extra_static_read_failed(the rest of the tree still copies), and an entry inside the output directory isbuild.extra_static_invalid_entry. Names are compared ignoring case, so a collision that would only bite on macOS or Windows is still reported on Linux.An
extra_csssheet that lives inside a listed directory is copied once for that directory, at its structure-preserving destination, and linked there. Entries that OVERLAP (one nested inside another) are each walked from their own root, so content they share is published under both entries’ destinations.Unset or empty means nothing extra is copied.
- build.html.favicon¶
- Type:
- string
- Default:
""
The site favicon.
An icon file (
.ico,.svg,.png, …) shown in the browser tab. The path is relative to thisubproject.toml(or absolute); the file is copied into the site’s_static/directory and linked from every page. A file that cannot be read is reported as thebuild.favicon_read_failedwarning and skipped. Unset or""means no favicon.
- Type:
- array of tables
- Default:
[]
Icon links shown at the right of every page’s footer row.
Written as a list of tables, one per icon, each with four optional string keys:
html, the icon markup, which is inserted into the page as raw HTML, not escaped (an inline SVG drawn withcurrentColorfollows the site’s light and dark themes);url, the link target;name, the link’s accessible label, which is what a screen reader announces; andclass, extra CSS classes added to the link.An entry with no
url, or with neitherhtmlnorclass, cannot render as a usable link: it is skipped, and reported as the build warningbuild.footer_icon_invalid. An entry with nonameis still rendered — with no label for assistive technology — and reported under the same code. With every entry skipped, no icons row is emitted.An extending configuration replaces the whole list rather than adding to it. Unset or empty means no icons.
Each entry: One icon link in the site footer.
- Type:
- string
- Default:
""
Extra CSS classes for the link, added to the built-in
ub-footer-icon.For an icon supplied by a font shipped through
extra_css, and for per-icon styling of your own.
- Type:
- string
- Default:
""
The icon markup.
Inserted into the page as raw HTML, not escaped. An inline
svgdrawn withfill="currentColor"orstroke="currentColor"takes the footer’s text colour and so follows both the light and the dark theme; the stylesheet sizes ansvgorimghere to one line. May be left out whenclasssupplies the icon instead (an icon font).
- Type:
- string
- Default:
""
The link’s accessible label — what a screen reader announces for it.
An icon has no text of its own, so without this the link is announced with no name at all. Omitting it is reported as the build warning
build.footer_icon_invalid, and the link is still shown.
- Type:
- string
- Default:
""
The link target.
Used as written, so an external link needs its scheme (
https://example.com). An entry without one is skipped and reported as the build warningbuild.footer_icon_invalid.
- build.html.hide_attribution¶
- Type:
- boolean
- Default:
false
Hide the footer’s “Built with ubc” attribution line.
Removes that line and nothing else: the footer, its divider and the
copyrightline (when set) all stay, and so does each page’s<meta name="generator">. When the footer’s bottom row would then be left with no content at all — no copyright, no footer icons — the row is not drawn, rather than leaving a bare divider behind. Defaults to false.
- build.html.hide_title¶
- Type:
- boolean
- Default:
false
The logo artwork already contains the site name, so the title text is not repeated beside it.
Hides the title wherever the site shell brands the site with the logo (today: the sidebar heading); assistive technology still hears the name (it becomes the logo’s alternative text), and browser titles and the narrow-viewport header keep the text. With no logo configured either, the sidebar shows no heading — including its link to the root page. Defaults to false.
- build.html.highlight¶
- Type:
- table
- Default:
{ aliases = {}, enabled = true }
Syntax-highlighting settings for the site.
The same keys as
[build.highlight]. This table inherits every key it does not set from[build.highlight]and wins on every key it does,enabled = falseincluded.The builders colour the code in a
code-block, aliteralincludeand a fenced block — and inline code with a language — using the language the code names. The set of languages is a bundled collection of Sublime Text syntax definitions, so it is the same on every machine and needs nothing installed. The colours are thehl-*roles under[build.pdf.theme.colors]on paper, and the--ubc-hl-*custom properties on the site.These keys can be written once in
[build.highlight]for every output format, or in one format’s own table —[build.pdf.highlight],[build.html.highlight]— which inherits every key it does not set from[build.highlight]and wins on every key it does,enabled = falseincluded.Both
ubc build pdfandubc build htmlread them, and they colour code with the same engine, so a language name and a decision about colour mean the same thing on paper and on the site.
- build.html.highlight.aliases¶
- Type:
- table of strings
- Default:
{}
Extra names for languages, on top of the built-in table.
Each entry maps a name you write — in a
code-blockargument, a:language:option or a.. highlight::— to the language it should be coloured as. The value is another language name ("python","toml","rst"), or"text"to draw the code plain and report nothing.An entry wins over the built-in name of the same spelling, so
default = "text"turns off the built-in “an unmarked block is Python” behaviour. Names are matched ignoring case and surrounding spaces, and a value is looked up ONCE: it must name a language directly, not another entry in this table. A value that names no language is reported when the project is read, and under the default--deny warningthat stops the build — unless highlighting is off for that format, in which case no name is looked up and nothing is reported.Written here this applies to every output format. A format’s own table (
[build.pdf.highlight],[build.html.highlight]) REPLACES this map for that format rather than adding to it.Empty by default, in which case only the built-in names resolve.
- build.html.highlight.enabled¶
- Type:
- boolean
- Default:
true
Colour the code in code blocks and in inline code that names a language.
Defaults to true. Setting this to
falsedraws all code in the document’s own code colour —code-fgon paper, the--ubc-code-fgcustom property on the site — as the builders did before they could highlight. It does not affect the line-number gutter, and it does not affect the band an:emphasize-lines:option draws behind a line. The colours themselves are thehl-*roles under[build.pdf.theme.colors]on paper, and the--ubc-hl-*custom properties on the site.
- build.html.legacy_anchor_redirects¶
- Type:
- array of strings
- Default:
[]
Keep deep links written against a previous
[parse] id_styleworking.For every id on a page that a style listed here would have spelled differently, the page gains a redirect from the old spelling to the new one, so a deep link written against an old anchor that nothing on the page carries any more lands on the element that carried it. List the OTHER style:
"docutils"on a"github"project (anchors a Sphinx build, or ubCode before"github"became the default, made —#needs-types-2-0forwards to#needs_types-20), or"github"on a"docutils"project (links written against GitHub- or MyST-style anchors).An old anchor the page still carries is never redirected: the page’s own anchor always wins, even when the new style gave that string to a DIFFERENT element (a positional
#id1now taken by a footnote, or one title now spelled the way another used to be), and no entry can override it. That is the usual outcome, not a rare one: in ubCode’s own test projects every such anchor lands on a different element, and on its documentation the one case lands on the same section.Unset or empty — the default — generates no entries. A style that is the project’s own
[parse] id_stylegenerates nothing, and says so with the warningconfig.legacy_anchor_redirects_own_style.The generated entries join the page’s anchor-redirect map, the one a
[build.html.redirects]key naming a section writes to, and a[build.html.redirects]entry for the same anchor wins. The forwarding happens in the reader’s browser: a reader without JavaScript, a crawler and anobjects.invconsumer see the new anchors only.Each entry: How HTML ids are made from section titles and names.
Values:
"github": GitHub’s heading-anchor convention (the default)."docutils": Sphinx’s anchors (docutils’make_id), to keep a Sphinx build’s anchors and existing deep links.
- build.html.logo¶
- Type:
- string
- Default:
""
An image file to show above the sidebar heading.
The path is relative to this
ubproject.toml(or absolute); the file is copied into the site’s_static/directory. It is scaled to fit the sidebar width. A file that cannot be read is reported as thebuild.logo_read_failedwarning and skipped. Unset or""means no logo.
- build.html.logo_dark¶
- Type:
- string
- Default:
""
A dark-theme variant of
logo.Shown instead of
logowhile the site renders in its dark theme (chosen with the theme toggle, or following the system preference); printing useslogowhen both are set. Resolved and copied likelogo(an unreadable file is the samebuild.logo_read_failedwarning), and meant to be set together with it — set alone it behaves likelogo(used everywhere, including print). Unset or""meanslogo(when set) is used in both themes.
- build.html.plantuml¶
- Type:
- table
Settings for rendering diagrams with an external
PlantUMLexecutable.ubCode can draw the
needumlandneedarchviews, the authoreduml/plantumldirectives (and theirMyST{uml}/{plantuml}fences), and — whenneedflow/needsequenceare set — theneedflowandneedsequenceviews, by running aPlantUMLexecutable you install and maintain, instead of converting them to Mermaid. It is off by default, and the live preview always uses the Mermaid conversion.These keys can be written once in
[build.plantuml]for every output format, or in one format’s own table such as[build.html.plantuml], which inherits every key it does not set from[build.plantuml]and wins on every key it does,enabled = falseincluded.PlantUML1.2026.2 or newer is required. Older releases accept the command-line options this feature relies on and then ignore them, so the diagram it produced would not be under the controls described here.ubCode always sets
PlantUML’sSANDBOXprofile, as a JVM property and in the environment. That is a safe default rather than a guarantee: the executable is yours, and what you put incommandcan relax it — a later-DPLANTUML_SECURITY_PROFILE=UNSECURE, a wrapper script that re-exports the profile, or an entry that strips the environment. That is your explicit choice: ubCode does not diagnose which of the twoPlantUMLprefers, and cannot contain whatPlantUMLthen reads.
- build.html.plantuml.command¶
- Type:
- array of strings
- Default:
[]
The
PlantUMLexecutable to run, written as a command and its arguments.Always a list, never a single string. For a JAR give the launcher and the JAR —
["java", "-jar", "/opt/plantuml.jar"]— and put any JVM options (-Xmx512m) before-jar; for a wrapper script or a native build, one entry is enough.The FIRST entry is the program: a bare name is looked up on
PATH, and one containing a path separator is taken relative to thisubproject.toml. Every entry after it is passed through EXACTLY as written.To point at a file beside this
ubproject.toml, write{config_dir}and ubCode replaces it with that directory — anywhere in any entry, as often as you like:["java", "-jar", "{config_dir}/libs/plantuml.jar"]. Nothing else in an argument is rewritten, so a container image name, aKEY=VALUEpair or a URL reaches your program unchanged.Required when the renderer is enabled — a command that cannot be run is reported as the build warning
build.plantuml_exec_failed, and so is an unset or empty one.ubCode always runs
PlantUMLunder itsSANDBOXprofile, and what you write here can relax it: a later-DPLANTUML_SECURITY_PROFILE=UNSECUREargument, or a wrapper script that re-exports the profile before startingPlantUML. That is your explicit choice — ubCode does not diagnose whetherPlantUMLprefers the property or the environment, cannot contain whatPlantUMLthen reads, andPlantUML’s own allowlist confines neither..nor symbolic links.
- build.html.plantuml.enabled¶
- Type:
- boolean
- Default:
false
Render
PlantUMLdiagrams with an externalPlantUMLexecutable instead of converting them to Mermaid.Applies to the
needuml/needarchviews and the authoreduml/plantumldirectives in the built output, and to theneedflow/needsequenceviews when their own keys are also set. Defaults to false, which leaves each builder to draw the diagram itself — in the HTML site, as the Mermaid conversion. The live preview always uses the Mermaid conversion, so an enabled project’s diagrams can look different in the preview than on the built page. Writing this table without setting this key leaves the renderer off.
- build.html.plantuml.min_version¶
- Type:
- string
- Default:
""
The oldest
PlantUMLversion this project accepts.Written the way
PlantUMLwrites it,1.2026.4, and checked once per build against the version the executable reports. Below it the renderer is switched off for that build with the warningbuild.plantuml_version_unsupportedand the diagrams fall back to what the builder draws without the renderer (in the HTML site, the Mermaid conversion).This can only RAISE the bar: it cannot be set below the built-in minimum of
1.2026.2, and a lower value is reported as the build warningbuild.plantuml_exec_failedand ignored in favour of that minimum. An executable whose reported version cannot be read at all is reported asbuild.plantuml_version_unparsedand not used, since there is then no version to check against the minimum.Diagram appearance can change between
PlantUMLreleases, so upgrading can change how your diagrams look. Unset or""means1.2026.2.
- build.html.plantuml.needflow¶
- Type:
- boolean
- Default:
false
Also draw the
needflowviews with the externalPlantUMLexecutable.Needs
enabledas well: this key chooses which diagrams the renderer draws, never whether there is one, soneedflow = trueon its own changes nothing. Defaults to false in both builders, which draws everyneedflowthe way ubCode draws it today (in the HTML site, as a client-side Mermaid flowchart; in the PDF, as a box showing the diagram source).This is a FIDELITY setting: the diagram is laid out by
PlantUMLitself, the way a Sphinx-Needs build withneeds_flow_engine = "plantuml"lays it out, and each node becomes a link to its need. Some intents cannot be carried over exactly —:direction: upand:direction: leftare drawn on their axis mate, a typestylethat is not aPlantUMLkeyword is drawn as a rectangle, andstyle_start/style_endare ignored.[needs] flow_engineis the low-precedence default for this key, so aubproject.tomlshared with a Sphinx-Needs build need not say the same thing twice. A diagram’s own:engine:option overrides both, in either direction. The live preview always uses the Mermaid conversion, whatever this says.
- build.html.plantuml.needsequence¶
- Type:
- boolean
- Default:
false
Also draw the
needsequenceviews with the externalPlantUMLexecutable.Needs
enabledas well, exactly asneedflowdoes, and defaults to false in both builders. A separate key fromneedflowbecause a project may well want its traceability graph drawn byPlantUMLand its message diagrams left as they are.[needs] flow_enginedoes NOT drive this key. Sphinx-Needs’ ownneedsequenceisPlantUML-only and has no engine option at all, so the key that chooses between engines has nothing to say about this family.With it off, a
needsequenceis the Mermaid sequence diagram ubCode draws itself (a box showing that source, in the PDF). With it on, it is laid out byPlantUML. The live preview always uses the Mermaid conversion, whatever this says.
- build.html.plantuml.timeout¶
- Type:
- integer
- Default:
60
How long the whole diagram-rendering step may take, in seconds.
The bound covers the single run that renders every diagram needing an update, not each diagram. Diagrams that produced no output when it expires are reported as the build warning
build.plantuml_timeoutand fall back to what the builder draws without the renderer (in the HTML site, the Mermaid conversion). Defaults to 60;0is refused asbuild.plantuml_exec_failed.
- build.html.redirects¶
- Type:
- table of strings
- Default:
{}
Redirects from the paths of pages and sections that moved to where they moved to.
Each key is a page — or a section of one — that no longer exists at that address, and each value is what it became, so a reader holding an old link still arrives.
ubc build htmlwrites a small forwarding page where the old page used to be, carrying the reader on with the?querythey arrived with (unless the target names one of its own), and with their#fragmenttoo — unless the entry names a section, in which case the entry’s own destination replaces it.Keys and targets are written the way a
toctreeentry is:/-separated and relative to the source directory, with a leading/and a source suffix (.rst,.md, …) both optional and both ignored. Either side may name a section ("guide/old#setup" = "guide/new#install"), and a target may instead be an externalhttp:///https://URL; any other URL scheme is refused.A key naming a SECTION works in the reader’s browser, because a fragment never reaches the server: if the key’s page still exists the entry rides that page’s own script, and if the key’s page is itself redirected the entry travels in its forwarding page — a key whose page is neither is refused. A section that is still present always wins, so an entry for an anchor that has not really moved is inert rather than surprising.
Redirect chains are followed to the end, so a reader is forwarded exactly once — including across the two layers, when a page and one of its sections both moved.
Unset — the default — means no redirects and no forwarding pages. Deleting an entry deletes its forwarding page from the output on the next build. A faulty entry is skipped with a build warning rather than stopping the build:
build.redirect_invalid(a key or target that cannot be read, or a section key on a page that is neither rendered nor redirected),build.redirect_source_exists(the key names a page that still exists, and that page keeps its own content),build.redirect_target_missing(the target names no page),build.redirect_cycle(entries that redirect in a loop),build.redirect_anchor_unknown(the target page renders no such section) andbuild.redirect_anchor_shadowed(the key’s section is still there, so the entry can never fire).
- build.html.sd_tabs_storage_prefix¶
- Type:
- string
- Default:
"ubc-tab-id-"
The
localStoragekey prefix under which a reader’stab-itemselection is remembered.A
tab-itemwith a:sync:key records the reader’s choice, so that picking (say) a language in one tab set selects it in every other set on the page, and keeps it on the next page and the next visit. Set this to an empty string to switch that off: tabs then still switch and still sync within a page, but nothing is written to browser storage and every page starts on its default tab.Unset means
ubc-tab-id-. The value is delivered to the browser as an attribute on the tab script that a page with tabs links, so it shapes the built site only — the editor preview runs no script and is not affected either way.Equivalent to sphinx-design’s
sd_tabs_storage_prefixconfiguration value, but NOT sharing its default ofsphinx-design-tab-id-: a page built by both tools on one domain would otherwise read and overwrite the other’s stored choices. Set it explicitly on both sides if you want them shared.
- build.html.search¶
- Type:
- table
- Default:
{ enabled = true }
Site search configuration.
The site produced by
ubc build htmlincludes a full-text search index over its pages, sections and needs, plus a search box in the sidebar and asearch.htmlresults page. Everything is generated at build time and works from a localfile://copy of the site — no server and no network access are needed.
- build.html.search.enabled¶
- Type:
- boolean
- Default:
true
Whether to build the search index and ship the search UI.
Defaults to true. Setting this to
falseremoves the search box, the results page and the index files from the site (a rebuild of an existing site also deletes the ones it wrote before), and skips the indexing work during the build. Turn it off for very large projects where the index file has grown impractical, or where the site is only ever read through a search-capable host.
- build.html.source_branch¶
- Type:
- string
- Default:
""
The branch or tag the source links point at.
Read together with
source_repositorywhen building each page’s view/edit URL — typicallymainormaster. It is not consulted bysource_view_link/source_edit_link, which carry their own targets, and it does nothing on its own: without a repository there is no URL for it to be part of. Set with neither a repository nor a link template it can reach nothing, and is reported as the build warningbuild.source_link_invalid— and a repository set with no branch is reported the same way, for whichever button no template covers. Unset or""means no branch.
- build.html.source_directory¶
- Type:
- string
- Default:
""
The path from the repository root down to this project’s source directory.
Prefixed to each page’s source path when the URL is built from
source_repository, so a project whose sources live indocs/of its repository setsdocs/here. A leading or trailing/is optional.It applies to the
source_repositoryconstruction ONLY: asource_view_link/source_edit_linktemplate receives the page path WITHOUT this prefix. Set with neither a repository nor a link template it does nothing, and is reported as the build warningbuild.source_link_invalid. Unset or""means the sources sit at the repository root.
- build.html.source_edit_link¶
- Type:
- string
- Default:
""
A URL template for the “edit this page” button.
The
source_view_linktwin, with the same{filename}substitution and the same freedom from host checking: it overrides thesource_repositoryconstruction for the edit button alone, and works on its own. Unset or""falls back to that construction.
- build.html.source_repository¶
- Type:
- string
- Default:
""
The URL of the repository holding this project’s source files.
Set it together with
source_branchand every page written from a source file gains “view this page” and “edit this page” buttons above its content, each linking to that page’s own source. The generated search results page has no source file and so shows neither, and a page with no navigation and no sub-sections shows no page chrome at all.Three hosts are recognised, and only over
https:https://github.com/…,https://gitlab.com/…andhttps://bitbucket.org/…. A trailing/— or a trailing.git, as a clone URL carries — is optional.A repository with no
source_branch, anhttp://URL, or a host outside those three draws no button and is reported as the build warningbuild.source_link_invalid— for any other forge, usesource_view_link/source_edit_linkinstead, which override this key and are never checked against the host list. Unset or""means no buttons.
- build.html.source_view_link¶
- Type:
- string
- Default:
""
A URL template for the “view this page” button.
Overrides the
source_repositoryconstruction for this one button, and works on its own with no repository set. Every{filename}in the value is replaced by the page’s source path relative to the project’s source directory, suffix included (guide.rst,topics/intro.md) —source_directoryis NOT prefixed to it.The value is used as written and is not checked, so a template that names a host outside the three recognised ones is fine here. Unset or
""falls back to thesource_repositoryconstruction.
- build.html.title¶
- Type:
- string
- Default:
""
The site title.
Shown as the sidebar heading and appended to each page’s browser title as
page title — site title(a page whose own title already equals it is left unsuffixed). Overrides[project].name, which is used for the sidebar heading when this is unset. Unset or""leaves page titles unsuffixed.