Home / News+Media / News / MrDocs in the Wild

MrDocs in the Wild

Engineering Posted on April 24, 2026
post-no-image-1

The questions changed. For a long time, people asked about MrDocs in the abstract: what formats will it support, how will it handle templates, when will it be ready. Then, gradually, the questions became specific. Jean-Louis Leroy, the author of Boost.OpenMethod, became one of our most active sources of feedback. His library exercises corners of C++ that most projects never touch, which means MrDocs gets tested in ways we would not have anticipated. He wanted to know why his template specializations were not sorted correctly. He wanted macro support because Boost libraries rely heavily on macros. He hit a crash when his doc comments contained HTML tables. These are not theoretical questions about a tool that might exist someday. These are questions from someone who already generated documentation with MrDocs and needs it to work better.

In our previous post, we described MrDocs transitioning from prototype to product. This post is about what happened when MrDocs went into the wild.

Real Projects, Real Problems

mindmap
  root((Feedback))
    First impressions
      Unstyled demos
      Custom stylesheets
    Navigation
      Breadcrumbs
      Orphaned pages
    AST edge cases
      Friend targets
      Parameter packs
      Detail namespaces
    Rendering
      Anchor links
      Code blocks
      Description ordering
    Runtime
      Compiler fallback
      JS engine switch

The Demo Page

Right after the previous post, where we announced the MVP and encouraged people to try MrDocs, we noticed the demos page was not doing us any favors. Someone shared MrDocs on a developer community and the website started getting traffic. The landing page looked polished, but visitors clicked through to the demos and saw raw, unstyled HTML: no fonts, no spacing, no colors. The HTML generator produced correct semantic markup, and that is technically the point: users are supposed to customize the output with their own stylesheets. But on the demos page, there was no stylesheet at all, and the result looked broken rather than customizable.

The custom stylesheet system added five configuration options (stylesheets, linkcss, copycss, no-default-styles, stylesdir) so projects can match their own branding. A bundled default CSS now ships with MrDocs, and it was refined to remove gradients in favor of solid, readable backgrounds.

Stylesheet commits

MrDocs generates thousands of reference pages, one per C++ symbol. We maintain an Antora extension, the antora-cpp-reference-extension, that integrates these pages into Antora-based documentation sites. But the generated pages end up orphaned from the navigation tree. Users found the navigation confusing: clicking on “boost” in the breadcrumb did not go where expected, and reference pages had no trail showing where they belonged in the hierarchy.

The obvious fix would be to list every page in Antora’s nav.adoc, but maintaining a navigation file with thousands of entries that changes every time a symbol is added or removed is not practical. Worse, Antora renders the navigation file in the sidebar, so listing every reference page would flood the UI with thousands of entries. We discussed the problem extensively with the Antora maintainer on the Antora community chat. His position was clear: Antora was designed so that pages must be in the navigation file. Programmatic editing of navigation is not supported.

That was not acceptable for us. We needed breadcrumbs that work for thousands of generated pages without polluting the sidebar or requiring a hand-maintained navigation file. The Antora author’s position was reasonable from his perspective (Antora is a general-purpose documentation tool, not a reference generator), but our use case was fundamentally different from what Antora was designed for.

The antora-cpp-reference-extension now builds breadcrumbs independently from the navigation file. MrDocs generates reference pages in a directory structure that mirrors the C++ namespace hierarchy (boost/urls/segments_view.adoc lives inside boost/urls/). The extension uses this structure to reconstruct the breadcrumb trail: each directory maps to a namespace, and the page title (which is the symbol name) becomes the last breadcrumb entry. The result reads naturally: Reference > boost > urls > segments_view.

Zero changes to the nav file. The sidebar stays clean. Breadcrumbs appear automatically and update when symbols are added or removed.

Breadcrumb and reference extension commits
  • ae95eb2 feat: synthesize reference breadcrumbs without nav files
  • 10a4019 feat: add auto base URL detection
  • 6a6c08b docs: auto-base-url option
  • 4f7c79f refactor: enhance release asset validation

Coordinating Two Independent Extensions

The antora-cpp-reference-extension generates reference pages and breadcrumbs. The antora-cpp-tagfiles-extension resolves cross-library symbol links (so a reference to boost::system::error_code in Boost.URL’s docs links to the correct page in Boost.System’s docs). These are two independent Antora extensions running as separate jobs.

The problem was that the reference extension generates tagfiles as a side effect of producing reference pages, and the tagfiles extension needs the most recent version of those tagfiles to resolve links correctly. MrDocs changes the tagfiles every time the corpus changes. Manually keeping them in sync was not sustainable: committing tagfiles to the repository meant they were always stale by the time the next build ran.

We made the extensions coordinate directly. The reference extension now hands its tagfile to the tagfiles extension at build time, so the links always reflect the current state of the documentation. The reference extension also gained auto base URL detection, removing the need for manual path configuration when switching between development and production builds.

Extension coordination commits (antora-cpp-reference-extension)
  • 6e8ffcb feat: antora-cpp-tagfiles-extension coordination
  • 8f12576 chore: version is 0.1.0
Extension coordination commits (antora-cpp-tagfiles-extension)
  • 98eba40 feat: antora-cpp-reference-extension coordination
  • 5a1723c feat: add global log level control for missing symbols
  • 453f01b chore: version is 0.1.0

Edge Cases in the Wild

As more libraries adopted MrDocs, edge cases in C++ symbol extraction surfaced. Boost.Beast exposed a duplicate ellipsis in parameter pack rendering (#1108, #1129):

Before: T& emplace(Args...&&... args)

After: T& emplace(Args&&... args)

Boost.OpenMethod revealed that friend targets were not resolving correctly. Boost.Buffers uncovered a problem with detail namespaces: when a class inherits from a base in a hidden namespace, the inherited members appeared in the documentation but their doc comments were lost (#1107). We fixed this so derived classes inherit documentation from hidden bases.

Unnamed structs also sparked an extended design discussion. When C++ code declares constexpr struct {} f{};, MrDocs needs a stable, unique name for hyperlinks. The team established a collaborative design process using shared documents, with Peter Dimov contributing an insight about C compatibility (typedef struct {} T; makes the struct named in C++).

AST and metadata commits
  • c85be75 fix: remove duplicate ellipsis in parameter pack expansion
  • c3dbded fix(ast): prevent TU parent from including unmatched globals
  • 76b7b43 fix(ast): canonicalize friend targets
  • 05f5852 fix(metadata): copy impl-defined base docs
  • 35cf1f6 fix: UsingSymbol is SymbolParent
  • c406d57 fix: preserve extraction mode when copying members from derived classes (#1120)
  • 4e7ef04 fix: prevent infinite recursion when extracting non-regular base class (#1132)
  • 0a69301 fix: extract and fix some special member function helpers

STAY UP TO date

Get C++ Alliance news, project updates, and community highlights in your inbox.

Subscribe

Empowering C++ — funding libraries, building community, shaping the future of the language.

Connect with us