feat: guild-hall hub entity + TechDocs with Mermaid model diagrams#8
Conversation
Move the Guildhall self-description out of examples/mock-org/software.yaml into catalog-info.yaml at the repo root. Required because backstage.io/techdocs-ref: dir:. must resolve relative to the catalog entity file — the TechDocs preparer blocks upward traversal (NotAllowedError). Rename guildhall-portal → guild-hall with spec.type:hub, dropping "portal". The Guild Hall is a practice-layer plugin concept (a hub page), not a portal artifact. spec.type:hub anticipates the hub-page design: singleton overview pages for installed plugin feature groups. Register catalog-info.yaml in app-config.yaml as a separate file location. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add root mkdocs.yml wiring the guild-hall entity's TechDocs site: grand tour
(demo-visir.md), Guildhall model overview, and all ten ADRs.
Add docs/guildhall-model.md: three Mermaid diagrams covering the full concept
map (five layers: people, concern, measurement, procedure, software), the
two-door graft flow (portal Template + agent SKILL.md), and the facets/
multi-natured component model.
Add docs/index.md so mkdocs generates a root index.html — required because
Backstage's TechDocs backend polls for index.html to confirm a successful
build; without it the sync endpoint returns a 200 but the docs tab shows an
error.
Configure mkdocs-mermaid2-plugin + pymdownx.superfences custom fence to
output <div class="mermaid"> blocks rather than Pygments-highlighted code.
Note: Mermaid rendering in Backstage's shadow DOM is still unresolved — the
diagrams render in VS Code markdown preview and should be shown there in demos
until a frontend transformer is available.
Local setup required (gitignored app-config.local.yaml):
techdocs:
generator:
runIn: 'local'
Also requires: pip install mkdocs-techdocs-core mkdocs-mermaid2-plugin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erences The guildhall-portal -> guild-hall (spec.type hub) rename left the ingestion smoke asserting the old entity: it polled component/default/guildhall-portal and checked type portal, so make smoke-catalog would burn its full poll window and FAIL on this branch. The smoke now asserts guild-hall with type hub (23/23 passing — which also proves the root catalog-info.yaml location ingests with its TechDocs ref intact). Also swept the stale entity references the rename orphaned: the demo visir's intro, verify checklist, and tour beat; the org.yaml DevEx comment; and the seed README's instance bullet (now also noting WHY the entity lives at the repo root — TechDocs dir refs cannot traverse upward). Deliberately untouched: leidangr-portal in smoke-gitea and the OpenBao docs (a different, older Gitea-seed entity), and phrasing-level "portal user"/"portal door" wording in the design doc and ADR 0010 — whether that wording survives the portal scrub is a call for the next pass, not a rename fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR replaces the example catalog component with the ChangesGuildhall catalog and documentation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR updates the repo’s “instance” entity to a renamed guild-hall Component (spec.type: hub) that lives at the repo root to support TechDocs dir:., and adds root-level TechDocs content (including Mermaid diagrams) for the Guild Hall model. It also updates smoke-catalog assertions and sweeps references from the mock-org seed/docs to reflect the rename.
Changes:
- Rename/move the instance entity to repo-root
catalog-info.yamlasguild-hallwithspec.type: hub, and register it viaapp-config.yaml. - Add root
mkdocs.yml+ TechDocs pages (docs/index.md,docs/guildhall-model.md) with Mermaid diagrams and navigation. - Update
scripts/smoke-catalog.shand documentation/seed references fromguildhall-portal→guild-hall.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/smoke-catalog.sh | Updates catalog smoke assertions to check guild-hall and type: hub. |
| mkdocs.yml | Introduces root TechDocs/MkDocs config + Mermaid-related configuration. |
| examples/mock-org/software.yaml | Removes the old portal entity from the mock seed and documents where guild-hall now lives. |
| examples/mock-org/README.md | Updates seed documentation to reference guild-hall at the repo root. |
| examples/mock-org/org.yaml | Updates DevEx team comment to reference guild-hall (needs a small pointer fix). |
| docs/index.md | Adds TechDocs root index page (needs terminology alignment with “hub”). |
| docs/guildhall-model.md | Adds Mermaid-based model diagrams describing Guild Hall concepts. |
| docs/demo-visir.md | Sweeps references to the renamed entity/type in the grand tour checklist and narrative. |
| catalog-info.yaml | Replaces the previous root component entity with the new guild-hall hub component + TechDocs annotations. |
| app-config.yaml | Registers the new repo-root catalog entity as a file location (comment needs name update). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app-config.yaml`:
- Around line 130-136: The moved-entity references still use outdated metadata.
In app-config.yaml lines 130-136, rename the guildhall-portal reference to
guild-hall; in examples/mock-org/org.yaml lines 33-34, replace software.yaml
with the root catalog-info.yaml reference.
In `@docs/guildhall-model.md`:
- Line 3: Update the introductory description in guildhall-model.md to say “five
layers” instead of “five Guildhall concepts,” accurately reflecting that the
diagram contains multiple concepts across those layers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a51f6a82-789e-48d6-b9bb-b4763746e2b9
📒 Files selected for processing (10)
app-config.yamlcatalog-info.yamldocs/demo-visir.mddocs/guildhall-model.mddocs/index.mdexamples/mock-org/README.mdexamples/mock-org/org.yamlexamples/mock-org/software.yamlmkdocs.ymlscripts/smoke-catalog.sh
…stale comments Address the Copilot + CodeRabbit round on #8. The substantive one is mkdocs.yml: the mermaid2 plugin is absent from the default TechDocs Docker generator image, so the committed `runIn: docker` default would fail the Docs build for anyone without the gitignored local override — and its div output cannot render inside TechDocs' shadow DOM anyway. Mermaid fences now degrade to plain code blocks until the TechDocs Addons mermaid addon (the planned follow-up) renders them client-side, which needs no mkdocs-side plugin. The rest is drift cleanup: the new TechDocs pages and mkdocs metadata should not have introduced "Portal" wording the branch exists to retire (now "Guild Hall" / hub), the app-config and org.yaml comments still pointed at the pre-rename entity name and pre-move file location, guildhall-model.md described five layers as five concepts, and the smoke-script timeout rationale said six lookups where the loop does ten. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/smoke-catalog.sh (1)
127-128: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssert the parsed
spec.typefield.
grep '"type":"hub"'validates a JSON substring rather than the entity field defined incatalog-info.yamlasspec.type. Usejq -e '.spec.type == "hub"'so the smoke test cannot pass on an unrelated nested value or fail because JSON formatting changes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/smoke-catalog.sh` around lines 127 - 128, Update the “Guild Hall hub ingested (type hub)” assertion to parse the entity with jq and validate that .spec.type equals "hub". Keep the existing $HUB input and failure handling, replacing the raw JSON substring check so formatting or unrelated type fields cannot affect the result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mkdocs.yml`:
- Around line 20-24: Update the TechDocs configuration around the Mermaid
handling comment so the Mermaid TechDocs addon is registered and renders Mermaid
fences from docs/guildhall-model.md; if addon wiring is not supported, remove
the Mermaid diagrams instead of leaving them as raw code blocks.
---
Outside diff comments:
In `@scripts/smoke-catalog.sh`:
- Around line 127-128: Update the “Guild Hall hub ingested (type hub)” assertion
to parse the entity with jq and validate that .spec.type equals "hub". Keep the
existing $HUB input and failure handling, replacing the raw JSON substring check
so formatting or unrelated type fields cannot affect the result.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: de42278a-3d23-441e-b77f-b1a5474b0600
📒 Files selected for processing (6)
app-config.yamldocs/guildhall-model.mddocs/index.mdexamples/mock-org/org.yamlmkdocs.ymlscripts/smoke-catalog.sh
| # Mermaid fences render as plain code blocks for now: the mermaid2 plugin's div | ||
| # output can't render inside TechDocs' shadow DOM anyway, and it is absent from | ||
| # the default TechDocs Docker generator image (breaking `runIn: docker` builds). | ||
| # The planned TechDocs Addons mermaid addon renders client-side from these | ||
| # fences without any mkdocs-side plugin. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## mkdocs.yml excerpt\n'
nl -ba mkdocs.yml | sed -n '1,120p'
printf '\n## Search for TechDocs/Mermaid references\n'
rg -n --hidden --glob '!**/.git/**' -e 'mermaid|TechDocs|techdocs|mermaid2|mkdocs-mermaid2|addons' .
printf '\n## docs/guildhall-model.md excerpt\n'
if [ -f docs/guildhall-model.md ]; then
nl -ba docs/guildhall-model.md | sed -n '1,220p'
else
echo 'docs/guildhall-model.md not found'
fiRepository: SiliconSaga/leidangr
Length of output: 221
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## mkdocs.yml excerpt\n'
python3 - <<'PY'
from pathlib import Path
path = Path('mkdocs.yml')
for i, line in enumerate(path.read_text().splitlines(), 1):
if 1 <= i <= 140:
print(f"{i:4d}: {line}")
PY
printf '\n## Search for TechDocs/Mermaid references\n'
rg -n --hidden --glob '!**/.git/**' -e 'mermaid|TechDocs|techdocs|mermaid2|mkdocs-mermaid2|addons' .
printf '\n## docs/guildhall-model.md excerpt\n'
python3 - <<'PY'
from pathlib import Path
path = Path('docs/guildhall-model.md')
if path.exists():
for i, line in enumerate(path.read_text().splitlines(), 1):
if 1 <= i <= 260:
print(f"{i:4d}: {line}")
else:
print('docs/guildhall-model.md not found')
PYRepository: SiliconSaga/leidangr
Length of output: 15078
🌐 Web query:
TechDocs Mermaid addon shadow DOM TechDocs Addons mermaid client-side render
💡 Result:
In Backstage TechDocs, the integration of Mermaid diagrams via the community-maintained 'backstage-plugin-techdocs-addon-mermaid' relies on client-side rendering within the TechDocs reader [1][2][3]. Because TechDocs renders documentation as static HTML encapsulated within a Shadow DOM [4][5], addons must interact with this DOM to locate and transform Mermaid code blocks into rendered diagrams at runtime [6][1]. Technical Considerations regarding Shadow DOM and Client-Side Rendering: 1. Mechanism: The Mermaid addon functions as a TechDocs Addon [1][2]. It utilizes hooks (provided by '@backstage/plugin-techdocs-react')—such as 'useShadowRootElements' or 'useShadowRoot'—to access the document content rendered inside the Shadow DOM [6][7]. Once the DOM is accessed, the addon identifies specific code blocks (typically tagged for Mermaid) and uses the Mermaid JS library to render them into SVGs or other visual elements [1][2]. 2. Shadow DOM Interaction: The 'TechDocsShadowDom' component is responsible for rendering the static site content [4][8]. Because this creates an isolated scope, global CSS or scripts from the main Backstage application often do not automatically apply to the inner documentation content [5]. Addons must effectively bridge this gap by injecting their logic or styles into the shadow root [6][7]. 3. Known Challenges: Users have reported intermittent issues with addons in certain browsers (e.g., Firefox, Safari) and during navigation between TechDocs pages [7]. These issues often stem from the way addons are managed via React Portals [7]. If the Shadow DOM is re-rendered during navigation, the portals hosting the addon may become disconnected from their containers, causing the diagrams or other addons to disappear until a full page reload occurs [7]. 4. Alternatives: Beyond the client-side addon, there are build-time alternatives such as 'Kroki' or 'markdown-inline-mermaid' [3][9]. These generate static images or code during the TechDocs build process, avoiding the complexities of runtime Shadow DOM manipulation and client-side dependency loading [3][9]. For official guidance and implementation, refer to the Backstage TechDocs Addon documentation [6] and the specific configuration instructions provided in the 'backstage-plugin-techdocs-addon-mermaid' repository [1][2].
Citations:
- 1: https://github.com/johanneswuerbach/backstage-plugin-techdocs-addon-mermaid?tab=readme-ov-file
- 2: https://www.npmjs.com/package/backstage-plugin-techdocs-addon-mermaid
- 3: https://github.com/backstage/backstage/blob/master/docs/features/techdocs/how-to-guides.md
- 4: https://backstage.io/api/stable/functions/_backstage_plugin-techdocs-react.index.TechDocsShadowDom.html
- 5: https://github.com/backstage/backstage/blob/master/docs/features/techdocs/concepts.md
- 6: https://backstage.io/docs/features/techdocs/addons/
- 7: 🐛 Bug Report: techdocs addon fails to render in firefox / safari backstage/backstage#24270
- 8: https://github.com/backstage/backstage/blob/master/plugins/techdocs-react/src/component.tsx
- 9: https://backstage.io/docs/features/techdocs/how-to-guides/
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## Search for TechDocs addon wiring in packages/app/src\n'
rg -n --hidden --glob '!**/.git/**' -e 'techdocs.*addon|addon.*techdocs|mermaid|`@backstage/plugin-techdocs-module-addons-contrib`|TechDocsAddons|TechDocsAddon|useTechDocs|useShadowRoot' packages/app/src packages/app
printf '\n## packages/app/src tree\n'
find packages/app/src -maxdepth 3 -type f | sort
printf '\n## package.json excerpts\n'
python3 - <<'PY'
from pathlib import Path
for p in [Path('packages/app/package.json'), Path('packages/backend/package.json')]:
if p.exists():
print(f"\n### {p}")
text = p.read_text().splitlines()
for i, line in enumerate(text, 1):
if 'techdocs' in line.lower() or 'mermaid' in line.lower() or 'addon' in line.lower():
print(f"{i:4d}: {line}")
PYRepository: SiliconSaga/leidangr
Length of output: 1091
Wire the Mermaid TechDocs addon or drop these diagrams. docs/guildhall-model.md uses Mermaid fences, but mkdocs.yml leaves them as plain code blocks and the app doesn’t register the Mermaid addon, so readers will only see raw source instead of diagrams.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mkdocs.yml` around lines 20 - 24, Update the TechDocs configuration around
the Mermaid handling comment so the Mermaid TechDocs addon is registered and
renders Mermaid fences from docs/guildhall-model.md; if addon wiring is not
supported, remove the Mermaid diagrams instead of leaving them as raw code
blocks.
| # guild-hall (type:hub) lives in the repo root catalog-info.yaml (registered | ||
| # separately in app-config) so its backstage.io/techdocs-ref: dir:. resolves | ||
| # to the root mkdocs.yml — TechDocs dir: refs cannot traverse up past the | ||
| # entity file's own directory. |
Summary
guildhall-portalentity toguild-hallwithspec.type: huband move it to a repo-rootcatalog-info.yaml— "hub" (a feature-group sub-portal) replaces the overloaded "portal" term, and TechDocsdir:.cannot traverse upward from a nested location.mkdocs.ymlplus TechDocs content for the Guild Hall:docs/guildhall-model.mdwith three Mermaid concept diagrams covering the practice/aspect/graft/standard/vísir ladder, anddocs/index.md(TechDocs build detection requires a root index). Wires mermaid2/superfences config for the diagrams.scripts/smoke-catalog.shto assert the renamedguild-hallentity andtype: hub, and sweep staleguildhall-portalreferences (demo-visir checklist, org.yaml comment, seed README). Note theleidangr-portalentity in smoke-gitea/OpenBao docs is a different, older Gitea-seed entity and is deliberately untouched.Test plan
make smoke-catalog— 23/23 passing on the branch (verified 2026-07-17), including the newguild-hall/type: hubassertions.make ci) green on the PR.Related
docs/plans/2026-07-10-guilds-skills-standards-design.mdand ADRs 0007–0010.