{ "label": "Bane's Lab Site", "summary": "The banes-lab.com site — the PAG grammar, the Disciplined AI Collaboration methodology, the architecture, the ontology and the anatomy of its own source, every page a typed section set rendered through one element factory, navigated by an event bus, prerendered per route with a JSON payload and a Markdown twin, served as a static Vite build.", "maturity": "experimental", "domains": [ {"meta": "frontend-ui", "sub": "dom-construction"}, {"meta": "frontend-ui", "sub": "navigation"}, {"meta": "content", "sub": "copywriting-strings"} ], "ecosystem": "typescript", "visibility": {"private": true, "hidden": false}, "capabilities": [ "register-pages-by-identifier", "route-between-pages-through-events", "render-inline-markup-without-parsed-html", "animate-elements-on-intersection", "copy-content-to-clipboard", "render-typed-document-sections", "switch-tabs-through-query-parameters", "render-chapter-layout-with-cited-panels", "link-vocabulary-to-ontology-records-and-chapters", "reveal-record-and-chapter-references-on-hover", "explore-ontology-records-by-face", "walk-the-source-tree-with-definitions-and-sources", "emit-per-route-head-metadata-and-schema" ], "governedBy": [ "separation-of-concerns", "type-safety" ], "entries": ["runtime/entrypoints/*.entrypoint.ts"], "docs": { "overview": "A document site. Every page is a light record under `presentation/records/` whose `registerPage` call names the page and loads its view from `presentation/views/` on demand, so the bundle carries one chunk per page; the route coordinator listens for `route.requested` events, renders the page into the main region, and emits `route.changed` so the panel and the mobile menu mark the active page. Copy lives in `configuration/strings/` as typed `Section` data (`types/document.types.ts`) whose blocks (`types/block.types.ts`, `types/grammar.types.ts`) are rendered by `presentation/renderers/block.renderer.ts`; the legal pages and the FAQ go through `document.renderer.ts`, the PAG, methodology, architecture, ontology and anatomy pages through `tab.widget.ts`, and the methodology and architecture chapters through `chapter.renderer.ts`, prose beside cited panels (`panel.renderer.ts`, pan and zoom viewports from `panel.component.ts`, diagrams fetched by digest in `diagram.renderer.ts`). The ontology page renders the build-time snapshot in `core/assets/ontology.generated.ts` through the converters in `domain/converters/`; the anatomy page renders `core/assets/anatomy.generated.ts`, the member's own tree with per-file walks, definitions, docs coverage and the source (`anatomy.renderer.ts`, `folder.renderer.ts`, `walk.renderer.ts`, `source.renderer.ts`). `site.strings.ts` passes every content module through `linkTabs` in `domain/converters/link.converter.ts`, so the first mention of an ontology term or another page's chapter in each section becomes a link, and `reference.widget.ts` reveals the record or chapter behind any such link on hover, focus or tap, grounded in the anatomy's constructs through `evidence.loader.ts`. Icons live in `configuration/icons/`, section ids in `core/ids/`, resource locations in `core/assets/`. Element construction goes through `core/factories/element.factory.ts`; inline markup in copy is converted to runs by `core/converters/markup.converter.ts` and rendered by `presentation/renderers/text.renderer.ts`, so no parsed HTML ever reaches a live node. `page.renderer.ts` derives each route's head — title, description, canonical, open-graph type and the JSON-LD graph from `schema.renderer.ts` — and `text.converter.ts` turns a rendered page into the Markdown twin the copy button and the prerender share.", "whenToUse": [ "Adding a page — add a `.record.ts` under `presentation/records/` whose `registerPage` call names the page and loads its `.view.ts` from `presentation/views/` on demand; the glob barrel discovers the record, the prerender writes its route, payload and twin, and the view's chunk is fetched only when the page is opened.", "Changing copy — edit the `.strings.ts` module that owns it; no view carries a literal. A section that outgrows the file cap continues in `.fragment.strings.ts`, and a chapter section cites each of its panels by tag from the prose.", "Citing the ontology or another page — write the record's exact name or the chapter's exact title; the vocabulary linker resolves it, and an anchor the vocabulary does not carry goes through `stageLink`, `layerLink` or `nodeLink` from `link.converter.ts`.", "Adding a block kind — extend `types/block.types.ts` (or `grammar.types.ts`), render it in `block.renderer.ts`, style it in `presentation/styles/`, and declare it in the panel kinds if a chapter may cite it.", "Changing the shell — the panel widget, the menu widget and their styles under `presentation/`." ], "whenNotToUse": [ "Deploying. The deploy member owns the droplet, nginx and the upload; this member only builds.", "Deriving the snapshots. The ontology, anatomy and diagram assets are written by the build plugins under the workspace scripts member, never by hand.", "Governance code. Rules and validators belong to `.govlab/` and the `govlab.*` members.", "Tests. Every suite lives under `codebase.testing/test.web/`." ], "install": "Resolved through the root `package.json` `workspaces` glob; every third-party dependency is hoisted from the root. `npm run dev` from the root serves it over HTTPS on a generated self-signed certificate; `npm run build -w @banes-lab/web` runs the build plugins in `vite.config.ts` and emits the static site into the builds output declared as `builds.web` in `project.paths/paths.yaml`, then renders the methodology checkouts.", "quickStart": [ { "intent": "Register a page", "lang": "ts", "code": "import { registerPage } from \"#domain/registries/page.registry\";\n\nregisterPage({\n description: HOME_DESCRIPTION,\n icon: HOME_ICON,\n id: HOME_PAGE,\n listed: true,\n load: async () => (await import(\"#presentation/views/home.view\")).PAGE,\n order: 10,\n title: HOME_TITLE,\n});" }, { "intent": "Request a route from anywhere", "lang": "ts", "code": "import { emitEvent } from \"#core/buses/base.bus\";\nimport { ROUTE_REQUESTED } from \"#core/ids/route.ids\";\n\nemitEvent({ name: ROUTE_REQUESTED, page: HOME_PAGE });" }, { "intent": "Link a content module against the ontology and the chapter vocabulary", "lang": "ts", "code": "import { METHODOLOGY_CONTENT } from \"#configuration/strings/methodology.strings\";\nimport { METHODOLOGY_PAGE } from \"#core/ids/page.ids\";\nimport { SITE_VOCABULARY } from \"#configuration/strings/site.strings\";\nimport { linkTabs } from \"#domain/converters/link.converter\";\n\nexport const METHODOLOGY_TABS = linkTabs(METHODOLOGY_CONTENT, SITE_VOCABULARY, METHODOLOGY_PAGE);" } ], "configuration": [ { "option": "vite.config.ts", "note": "the application build and its plugin order — ontology, anatomy, diagrams, prerender, prune, chapters — with roots, output and the dev certificate resolving through `@ssot/paths`." }, { "option": ".govlab/taxonomy.config.ts `containers`", "note": "declares this member as a governed root with `configuration`, `core`, `domain`, `presentation`, `runtime` and the flat `types` bucket." }, { "option": "configuration/constants/vocabulary.constants.ts", "note": "the ambiguous phrases the vocabulary linker never links from prose." }, { "option": "configuration/constants/evidence.source.constants.ts", "note": "the classified registry that grounds ontology records and chapters in this member's own constructs, read by the reference widget both ways." } ], "disposal": [ "Remove the member's workspace entry from the root `package.json` and the `#host/*` imports key.", "Remove its governed-root entry from `containers` and `specialContainers` in `.govlab/taxonomy.config.ts`.", "Remove the `app` branch from `project.paths/paths.yaml`.", "Delete the directory, reinstall, run the gate." ], "apiNotes": [ { "name": "registerPage", "note": "Stores by `id`, so registering the same id twice replaces. Only pages with `listed: true` appear in the panel; every registered page is routable, and the prerender throws on an id declared in `page.ids.ts` that no record registers." }, { "name": "linkTabs", "note": "Links the first occurrence of each vocabulary phrase per section — whole words, case, plural and British spelling folded — never inside code, a diagram, a tag or an existing link, and never a section to itself." }, { "name": "createLink", "note": "The one link factory: a same-tab hash scrolls to the target and reveals a collapsed record; a page path routes through the bus; an external address opens as a plain anchor." }, { "name": "mountReference", "note": "Mounts the hover, focus and tap reveal for every link to an ontology record or a chapter, reading the chapter from the route's json payload and the record from the lazily imported face module." } ], "aiContext": [ "No view writes copy inline. A new string is a const in the owning `.strings.ts`.", "Interactive controls (buttons, inputs) are constructed only inside `presentation/components/*.component.ts`.", "Children emit events; parents subscribe. A widget never receives a callback to call back up.", "A `*.generated.ts` asset is written by a build plugin and never edited; a missing or stale one means the build has not run.", "Tests for this member live at `codebase.testing/test.web//tests/` and import it by package specifier." ] } }