Appearance
Architecture: How Flude Works
Audience: engine developers, and anyone who wants to understand what actually happens between "source code with Doxygen comments" and "a page on a documentation site" — beyond the one-paragraph summary in Getting Started.
Generation is two independent, sequential phases, connected through the file system rather than a direct function call. Understanding this split explains most of the "why does the site show stale content" and "why did nothing render" questions in Troubleshooting.
Phase A: content generation (ude.cli compile, per document)
Phase A runs once per document — one SDK, one language, one output format (e.g. bimnv_api_cpp for BimNv's C++ HTML reference, bimnv_api_cpp_hugo for the same content as Hugo Markdown). It is the pipeline described in Getting Started:
- Collect: a
*DoxygenCollector(engine/ude/collectors/doxygen.py) shells out to the realdoxygenbinary as an external subprocess and reads back its XML output. - Parse: a language-specific
*DoxygenParser, dispatched byengine/ude/parsers/doxygen_router.py, normalizes the XML into aProjectCatalog— the language-independent Intermediate Representation (IR) defined inengine/ude/models.py. - Render: one of 16 concrete renderer classes, named
<Lang><Output><ID>RendererwithLang ∈ {Cpp, Cs, Java, Py},Output ∈ {Html, Hugo},ID ∈ {Default, ODA}(engine/ude/renderers/static_html.py,hugo_markdown.py,oda.py), writes the final output. - Audit: every successful
compileunconditionally prints a documentation coverage table — see CLI Reference.
UdeOrchestrator (engine/ude/orchestrator.py) drives Collect → Parse → Render for a single document; it does not know about, or participate in, Phase B below.
Where Phase A writes, in this repository
Real projects under ude_projects/ resolve output_base_dir (set once, in ude_projects/ude_global_config.json) against each document's own output_subdir. As configured today, that is ../.workdir/output/<output_subdir>/ — for example .workdir/output/bimnv_api_cpp/ for the static-HTML build of BimNv's C++ reference, and .workdir/output/bimnv_api_cpp_hugo/ for the Hugo-Markdown build of the same content (verified directly against ude_projects/ude_global_config.json and ude_projects/BimNv/bimnv_api_cpp/ude_doc_config.json on 2026-08-14). .workdir/ is a single gitignored root directory, not tracked in git.
For renderer.type values html / oda_html, this output is already a complete, self-contained static site for that one document — open it directly in a browser, nothing else needs to run. For hugo_markdown / oda_hugo_markdown, this output is Markdown only, and needs Phase B to become HTML.
Phase B: site build (ude_hugo_site/build_site.py)
Phase B runs separately and later, and does not invoke Doxygen or the parser at all. Each Hugo-variant document has a matching project under ude_hugo_site/projects/<doc>/, with its own hugo.toml. That file's [[module.mounts]] mounts the Phase-A Markdown output directly as that Hugo project's content/:
toml
# ude_hugo_site/projects/bimnv_api_cpp_hugo/hugo.toml (real file, abridged)
[[module.mounts]]
source = "../../../.workdir/output/bimnv_api_cpp_hugo"
target = "content"ude_hugo_site/build_site.py runs hugo --destination for the shared portal (ude_hugo_site/portal/) and every such per-document project, producing the final combined HTML tree at .workdir/output/_hugo_site_dist/ — confirmed on 2026-08-14 to contain one subdirectory per SDK (bimnv/, kernel/, ifc/, ...) plus shared css//js/ and the portal's own index.html. No re-parsing of SDK source happens at this stage.
In other words: there is no direct call between orchestrator.render() and a finished site — these are two independent processes connected only via the file system. See Production Workflow for how to actually run both phases in this repository.
Related Docs
(Paths below are repository-root-relative.)
user-docs/docs/production-workflow.md— running Phase A and Phase B in this repositoryuser-docs/docs/target-settings.md—output_base_dir/output_subdirand the rest of the doc-config schema referenced above
