Skip to main content

doxtr-hugo

A Sphinx builder for the doxtr ecosystem that turns a Sphinx documentation source into content for the Hugo static site generator.

Author in reStructuredText/Sphinx and deploy the result as a Hugo site: the extension adds a hugo builder (sphinx-build -b hugo) that walks the resolved doctree and emits one Markdown file per document plus co-located assets, laid out as a buildable Hugo site. It emits only formats Hugo renders natively (CommonMark/Goldmark Markdown with front matter, and diagrams/figures pre-rendered to static images — SVG preferred, PNG fallback), so no Hugo modules, render-hook JavaScript, or the asset pipeline are required on the consumer side.

Status: early development. See doxtr-hugo-implementation-guide.md for the full specification and IMPLEMENTATION_STATUS.md for progress.

Features

Supported constructs and capabilities:

  • Content translation — section headings, paragraphs, inline markup (emphasis/strong/literal), bullet and enumerated lists (nested), line blocks, block quotes, definition lists, field lists, images and figures, and .. rubric::.
  • Code blocks — literal/.. code-block:: blocks emitted as fenced Goldmark code blocks with language hints.
  • Tables — GFM pipe tables by default, with a raw-HTML fallback for cells that span rows/columns (doxtr_hugo_tables).
  • Admonitions — typed directives (note, warning, tip, caution, danger, error, hint, important, attention, seealso) and generic .. admonition:: titles, emitted as a Hugo shortcode by default or portable raw HTML (doxtr_hugo_admonitions).
  • Cross-references — :doc:/:ref: and internal references emitted as Hugo {{< relref >}} (build-time validated) by default, or plain relative links (doxtr_hugo_link_style); external links and raw-HTML passthrough.
  • toctree → sections — toctree drives the Hugo section/weight model (branch vs. leaf pages, deterministic per-parent weights, _index.md generation) and on-page navigation lists, with no hand-written front matter.
  • Diagrams — five backends pre-rendered to static images: PlantUML, Graphviz, Mermaid, d2 (doxtr_d2), and sphinx_diagrams (the diagrams Python library, PNG-only). SVG is preferred, PNG is the portable fallback, and a missing backend degrades gracefully (doxtr_hugo_on_missing_backend). Custom backends register via doxtr_hugo.register_backend.
  • Math — pre-rendered to transparent PNG by default (zero extra binary via matplotlib mathtext), with mathjax and mathml-passthrough opt-in (doxtr_hugo_math).
  • Invisible nodes — RST comments (.. a comment), substitution definitions, docutils system messages, .. meta::, and transform pending placeholders are stripped from the output (their text never leaks into the page); resolved substitution usages still render.

Installation

pip install doxtr-hugo

The diagram backends are optional. To pull in the Sphinx-side extensions that provide diagram directives (PlantUML, Mermaid, d2, and the diagrams library), install the diagrams extra:

pip install "doxtr-hugo[diagrams]"

To install every optional feature at once (all diagram backends plus PyYAML for YAML front matter), use the all extra:

pip install "doxtr-hugo[all]"

The external rendering binaries (plantuml, dot, mmdc, d2) are not Python dependencies — the builder only invokes them when present on PATH and degrades gracefully otherwise (doxtr_hugo_on_missing_backend).

Usage

Enable the extension in your Sphinx conf.py:

extensions = [
    "doxtr_hugo",
]

Then build the Hugo site:

# Either form works:
make hugo                               # -> build/hugo/
# or:
sphinx-build -b hugo source build/hugo

Previewing locally

The extension does not ship or modify any Makefile. Registering the builder via app.add_builder() is the entire integration surface; the Makefile generated by sphinx-quickstart already forwards unknown targets to sphinx-build, so make hugo works without any extension-side change.

With the default doxtr_hugo_emit_skeleton = "full", the output in build/hugo/ is a self-contained, runnable Hugo site:

# Build the Hugo site (either form works)
make hugo                               # -> build/hugo/
# or:
sphinx-build -b hugo source build/hugo

# Preview it (requires the default emit_skeleton = "full")
cd build/hugo
hugo server

Notes:

  • The output lands in build/hugo/ (the make/sphinx-build BUILDDIR), which is a self-contained, runnable Hugo site because the builder's finish() emitted hugo.toml + layouts/.
  • hugo server requires emit_skeleton = "full" (the default). In "content-only" mode there is no hugo.toml/layouts/, so preview must happen from within the consumer's own Hugo project.
  • Drafts: pages are emitted with draft = false, so plain hugo server shows them; hugo server -D is only needed if the consumer later sets pages to draft.

Using with a third-party Hugo theme

The default emit_skeleton = "full" output ships doxtr-hugo's own layouts/_default/ so the site builds standalone. Those layouts override a theme: Hugo's template precedence puts a site-level layouts/_default/ above any --theme, so building the full output under a theme makes every theme render the skeleton's HTML rather than its own. To deploy under a third-party theme, emit the theme-portable form instead:

sphinx-build -b hugo \
  -D doxtr_hugo_emit_skeleton=content-only \
  source build/hugo-content
  • doxtr_hugo_emit_skeleton = "content-only" writes only content/** (section _index.md files + co-located assets) — no hugo.toml, no layouts/. Drop that content/** into your own themed Hugo site.
  • In content-only mode the builder defaults doxtr_hugo_admonitions to "html" automatically (portable raw HTML), because a third-party theme does not ship doxtr-hugo's admonition shortcode — shortcode admonitions would fail there with template for shortcode 'admonition' not found. Set doxtr_hugo_admonitions explicitly to override (e.g. "shortcode" if your site provides its own admonition shortcode).
  • If you instead keep the default "full" emit and add a theme, be aware the emitted layouts/ will shadow the theme; use "content-only" (above) for real theme deployment.

See the configuration knobs doxtr_hugo_emit_skeleton and doxtr_hugo_admonitions for the full surface.

Configuring a theme (ready-to-serve output)

Instead of hand-assembling a themed site from the content-only output, you can configure the theme once in your Sphinx conf.py and have sphinx-build -b hugo emit a complete, version-controllable Hugo site under build/hugo/ whose hugo.toml is correctly configured for that theme:

# conf.py
doxtr_hugo_theme = "docsy"            # a shipped profile, or any theme name

doxtr_hugo_theme_config = {           # deep-merged into hugo.toml (you win)
    "params": {"github_repo": "https://github.com/me/docs"},
}

# Optional: override how the theme is obtained (defaults to a Hugo Module).
doxtr_hugo_theme_source = {"kind": "module", "url": "github.com/google/docsy"}

Building then produces, in build/hugo/:

  • a merged hugo.toml = core defaults (goldmark unsafe + extensions) + the theme profile (e.g. docsy's type="docs" cascade, hugo-book's BookSection="*") + your doxtr_hugo_theme_config (highest precedence);
  • a README-hugo.md listing the exact one-time commands still needed for that theme (e.g. hugo mod get, installing Dart Sass, npm install) before hugo server — the extension documents these, it never runs them;
  • the image render hook so math/diagram images resolve under any theme.

Shipped profiles (edition/toolchain/config captured so the output just works): archie, hugo-terminal, hyde, risotto, notepadium, hugo-book, docsy. A theme with no shipped profile still works — it is emitted with core defaults plus your doxtr_hugo_theme_config, and you supply the theme + config.

The emitted build/hugo/ is Hugo input: commit it, then run the README's commands and hugo server. For light themes vendored into themes/ nothing extra is needed; SCSS themes like docsy require the documented extended Hugo + Dart Sass + npm steps.

Overlay (escape hatch) and hooks

Anything the declarative config cannot express goes in a sidecar overlay directory, copied verbatim into build/hugo/ on top of the emitted site (your files win):

source/.doxtr/hugo/            # doxtr_hugo_theme_overlay_dir (confdir-relative)
  config/overlay.toml          # extra raw Hugo config fragments
  layouts/partials/head.html   # custom/partial template overrides
  assets/scss/_variables_project.scss
  static/img/logo.png

The extension auto-excludes .doxtr/** from Sphinx's document scan, so overlay files are never parsed as reStructuredText. For programmatic post-processing, doxtr_hugo_theme_hook = "mypkg.mymod:callable" runs your own project code last (called with outdir, config, app), after all files are written.

Configuration keys: doxtr_hugo_theme, doxtr_hugo_theme_config, doxtr_hugo_theme_source, doxtr_hugo_theme_overlay_dir, doxtr_hugo_theme_hook.

Page titles (no duplicate heading)

By default (doxtr_hugo_title_heading = "frontmatter") the page's leading top-level heading is not emitted into the Markdown body — it is carried by the title front matter, which every Hugo theme (and the built-in skeleton) renders. Emitting it in the body too would show the title twice. Deeper headings (## and below) are always kept. Set doxtr_hugo_title_heading = "body" to restore the legacy behavior of writing the leading # Title into the body (for a theme that does not render .Title itself).

Changelog

See CHANGELOG.md for the release history.

License

MIT — see LICENSE.

Metadata

Release files for doxtr-hugo 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for doxtr-hugo 0.1.0
File Size Uploaded Provenance
doxtr_hugo-0.1.0.tar.gz 127.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for doxtr-hugo 0.1.0
File Interpreter ABI Platform
doxtr_hugo-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 222.3 kB

Release files / doxtr_hugo-0.1.0.tar.gz

Download URL doxtr_hugo-0.1.0.tar.gz
Size 127.1 kB
Tags Source
SHA-256 checksum
How to use checksums
124ca3e14d79614a9eacc7ee2a83bf857332bda1db31e98a21d0065cb2db425a
BLAKE2b-256 checksum
How to use checksums
1f3b0d0d245110fc79e613fc6a95cbc5161b7d31584acf39c540c9eda4989977
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / doxtr_hugo-0.1.0-py3-none-any.whl

Download URL doxtr_hugo-0.1.0-py3-none-any.whl
Size 95.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
43c5b707357cef7dd4627b1941319b289fb5bdda1b540b139071079bf1f34d3c
BLAKE2b-256 checksum
How to use checksums
0f78a0f831f8f9f55768b23ab95e2d7b55c123459d7a94873afcc53a133c0b3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Security for doxtr-hugo 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for doxtr_hugo-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page