How do I publish docs against my L2?¶
The unified docs site renders against any L2 institution YAML. Point it at yours and the SAME source produces a different rendered handbook (vocab, diagrams, intro prose) with zero markdown edits.
Render against your L2¶
# Build the site to ./site/ — bound to your L2.
recon-gen docs apply --l2 run/my-l2.yaml -o site
# Or live-reload preview at http://localhost:8000:
recon-gen docs serve --l2 run/my-l2.yaml
The rendered site/ directory is a static site you can publish to
GitHub Pages, S3 or any static host that runs HTTP.
Ship a portable site (open via file://)¶
By default the site uses pretty URLs (/scenario/) which need an
HTTP server to map the slug to its index.html. For a wiki / USB
stick / zip-attachment build that opens directly in a browser:
recon-gen docs apply --portable --l2 run/my-l2.yaml -o portable-site
--portable does two things:
- Flips
use_directory_urls: falseso every page emits as<slug>/index.htmland links resolve viafile://. - Post-processes the rendered
stylesheets/qs-graphviz-wasm.jsto inline the WASM diagram bundle directly into the script (browsers block ES module imports underfile://for security; inlining bypasses that). Diagrams render without a web server.
The CLI echoes the absolute path to the entry-point index.html you
can hand to a stakeholder. Zip the directory and ship — recipients
double-click and read.
Advanced: hand-build with your own mkdocs config¶
If you want to integrate with an existing mkdocs build pipeline (a custom theme, an extra plugin set, your own CI), extract the source:
recon-gen docs export -o /tmp/my-docs --l2 run/my-l2.yaml
RECON_GEN_DOCS_L2_INSTANCE=/Users/me/run/my-l2.yaml \
mkdocs build -f /tmp/my-docs/mkdocs.yml
What changes per L2 instance¶
Three substitution surfaces:
- Vocab strings (
{{ vocab.institution.name }},{{ vocab.institution.acronym }}, etc.) substitute throughout the prose. Thesasquatch_prfixture (via its declaredinstitution_name/institution_acronym) carries Sasquatch flavor; any other instance falls back to a neutral "Your Institution" voice derived from the L2 description's first proper-noun-shaped run. - L2-driven diagrams (
{{ diagram("l2_topology", kind="accounts") }},{{ diagram("dataflow", app="l1_dashboard") }}) regenerate from your L2's structural data — accounts + rails + chains laid out visually for your specific institution. - The page set stays the same; the CONTENT of each page reflects your L2.
What stays the same¶
- Conceptual diagrams (
docs/_diagrams/conceptual/*.dot) are hand-authored teaching aids. They don't change per L2. - Reference material describing the L1 invariants, the SPEC and the Schema v6 contract are persona-blind and identical across renders.
- Walkthroughs describing per-sheet operator flows are written against the dashboard structure (which is the same regardless of L2). Body examples may still mention Sasquatch-flavored identifiers (gl-1010, Bigfoot Brews) where the example is illustrative; those are tagged for future cleanup or replacement with vocab pulls.
Adding your institution's flavor¶
If your institution wants richer flavor than the neutral fallback,
the primary path is the top-level institution_name /
institution_acronym / description fields on your L2 YAML
(BXa.1 dissolved the persona: block — its stakeholders /
gl_accounts / merchants / flavor sub-fields were never
substituted in any docs page and got dropped). The
handbook templates substitute via vocab Jinja references at render time.
See How do I brand my handbook prose? for the full field set, the field-by-field map to handbook surfaces and the neutral fall-through behavior when fields are omitted.
The Investigation walkthroughs' worked-example admonitions (the
??? example "Worked example: <fixture>" blocks naming specific
accounts) are wired by role from the L2 YAML's top-level
investigation_personas: block (typed {name, account_id, role}
entries; templates gate on roles convergence_anchor /
counterparty_bank / operations_account / shell_entity).
BXa.1 already lifted them out of the deleted
_sasquatch_pr_vocabulary code intercept into the YAML — no
Python edit needed.