ADR-197: Unified Web Publishing Component System
Status: Accepted Date: 2026-02-14 Deciders: Hal Casteel (CTO) Extends: ADR-195 (Push-Button Documentation Publishing Platform)
Context
Problem
CODITECT projects generate rich documentation (markdown, JSX dashboards, Mermaid diagrams, LaTeX equations). The BIO-QMS project proved that a Vite+React viewer with unified/remark/rehype rendering works well — but the implementation required extensive manual tuning:
- Mermaid theming required iterating through 60+ theme variables to achieve high-contrast dark-mode rendering (commit
8cae94f) - CSS styling for code blocks, tables, headings, and diagrams was crafted per-project with no shared standard
- Subgraph color conventions for Mermaid architecture diagrams were invented ad-hoc (Actors=blue, Core=indigo, Data=teal, etc.)
- SVG background stripping was needed because Mermaid injects backgrounds that conflict with container styling
- Pre-render pattern for Mermaid (render to SVG string before React
setHtml()) was discovered through trial-and-error, not documented - Forced dark background on diagram containers was the solution for light/dark mode contrast, but this pattern wasn't codified
Each new project would repeat this discovery process. One-off web publishing doesn't scale.
What ADR-195 Covers (vs. This ADR)
ADR-195 defines the platform architecture: what the viewer does (render markdown, search, present, deploy to cloud, package as npm). ADR-197 defines the component contracts: how each piece is built, themed, and composed so that any project gets identical rendering by adopting the standard components.
| Concern | ADR-195 | ADR-197 (this) |
|---|---|---|
| Viewer application architecture | Yes | No |
| publish.json manifest | Yes | No |
| Cloud deployment (Cloud Run + CDN) | Yes | No |
| Markdown pipeline specification | Mentioned | Detailed |
| Mermaid rendering approach | No | Yes |
| CSS design token system | No | Yes |
| Component interface contracts | No | Yes |
| Theme configuration specification | No | Yes |
| Subgraph color conventions | No | Yes |
| Scaffold templates | Mentioned (create-doc-site) | Detailed |
| Quality grading criteria | No | Yes |
Decision
D1: Modular Component Architecture
The web publishing system is decomposed into 7 core components that compose like building blocks. Each component has a defined interface contract, CSS token dependencies, and can be used independently or as part of the full stack.
@coditect/web-publisher (meta-package)
├── MarkdownRenderer # Markdown → HTML via unified pipeline + Mermaid pre-render
├── MetadataBar # Frontmatter display (audience badges, status, word count)
├── Sidebar # Collapsible category tree with expand-all/collapse-all
├── SearchPanel # Full-text body content search (MiniSearch) with snippets
├── Breadcrumbs # Category → Document navigation trail
├── TableOfContents # Right-rail heading navigation (h2/h3)
├── CategoryLanding # Category index page with document grid
└── generate-publish-manifest.js # Build-time: markdown → publish.json with body_text
Rationale: Lego-like composition means a project can adopt just MarkdownRenderer for minimal rendering, or the full stack for a complete publishing platform. Components share CSS tokens but have no hard coupling. Full-text search indexes both metadata and stripped markdown body content — no server required.
D2: Markdown Rendering Pipeline (Canonical Stack)
The markdown rendering pipeline is standardized on the following exact dependency chain. All CODITECT web publishing projects MUST use this stack:
Source (.md) → parseFrontmatter() → unified pipeline → HTML string → pre-render Mermaid → setHtml()
Pipeline Configuration (REQUIRED):
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import remarkFrontmatter from "remark-frontmatter";
import remarkMath from "remark-math";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import rehypeHighlight from "rehype-highlight";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeKatex from "rehype-katex";
import rehypeRaw from "rehype-raw";
const processor = unified()
.use(remarkParse)
.use(remarkFrontmatter, ["yaml"])
.use(remarkGfm)
.use(remarkMath)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(rehypeSlug)
.use(rehypeAutolinkHeadings, { behavior: "wrap" })
.use(rehypeHighlight, { ignoreMissing: true })
.use(rehypeKatex)
.use(rehypeStringify);
Plugin Order Matters: rehypeRaw must come BEFORE rehypeSlug and rehypeHighlight to ensure raw HTML blocks are processed before heading IDs and code highlighting are applied.
Frontmatter Extraction: Use browser-compatible parseFrontmatter() function (NOT gray-matter which depends on Node.js Buffer). The reference implementation in BIO-QMS handles YAML key-value pairs and list items without any Node.js dependencies.
Rationale: This exact stack was proven in production on 83+ documents in BIO-QMS. Every plugin is necessary: remarkGfm for tables/task lists, remarkMath+rehypeKatex for equations, rehypeRaw for embedded HTML, rehypeHighlight for code blocks.
D3: Mermaid Pre-Render Pattern (REQUIRED)
Mermaid diagrams MUST be pre-rendered to SVG strings and injected into the HTML before React processes it. DOM mutation after dangerouslySetInnerHTML gets overwritten by React re-renders.
Pattern:
// 1. Process markdown to HTML string
let htmlStr = String(await processor.process(body));
// 2. Find all mermaid code blocks in the HTML
const mermaidRegex = /<pre><code class="[^"]*language-mermaid[^"]*">([\s\S]*?)<\/code><\/pre>/g;
// 3. For each match: strip highlight spans, decode HTML entities, render to SVG
let match;
while ((match = mermaidRegex.exec(htmlStr)) !== null) {
const raw = match[1].replace(/<[^>]*>/g, ""); // Strip spans
const decoder = document.createElement("textarea");
decoder.innerHTML = raw;
const source = decoder.textContent; // Decode entities
const id = `mermaid-${Math.random().toString(36).slice(2, 10)}`;
let { svg } = await mermaid.render(id, source);
// Strip Mermaid's injected SVG background
svg = svg.replace(/(<svg[^>]*?)style="([^"]*)"/, (m, pre, style) => {
const cleaned = style.replace(/background[^;]*(;|$)/g, "background:transparent;");
return `${pre}style="${cleaned}"`;
});
htmlStr = htmlStr.replace(match[0], `<div class="mermaid-diagram">${svg}</div>`);
}
// 4. Set the HTML with all diagrams already rendered as inline SVG
setHtml(htmlStr);
Why Pre-Render (NOT Post-Render):
dangerouslySetInnerHTMLreplaces the entire DOM subtree on every React state update- Post-render DOM mutations (calling
mermaid.run()after mount) get wiped on re-render - Pre-rendering embeds the SVG directly in the HTML string, making it part of React's virtual DOM
- This pattern was discovered after multiple failed approaches in BIO-QMS development
SVG Background Stripping: Mermaid's renderer injects a background style into the SVG element. This must be stripped and replaced with background:transparent so the container's background controls the visual appearance.
Rationale: This is the only reliable approach for React SPA rendering. It was proven through iteration — mermaid.run(), mermaid.init(), and useEffect-based approaches all fail because React overwrites the DOM.
D4: Mermaid Theme Configuration (60+ Variables)
All CODITECT web publishing projects MUST use theme: "base" with the following themeVariables configuration. The dark theme is NOT used because it has limited override capability.
Complete Theme Specification:
| Category | Variable | Value | Purpose |
|---|---|---|---|
| Background | background | transparent | Container controls background |
| Background | darkMode | true | Dark mode flag |
| Typography | fontFamily | Inter, system-ui, sans-serif | System font stack |
| Typography | fontSize | 13px | Base diagram font size |
| Primary | primaryColor | #1c3048 | Muted steel blue node fill |
| Primary | primaryTextColor | #d8dee6 | Node text |
| Primary | primaryBorderColor | #5a8ab4 | Node border |
| Secondary | secondaryColor | #1a2636 | Cool slate node fill (no purple) |
| Secondary | secondaryTextColor | #d8dee6 | Alternate text |
| Secondary | secondaryBorderColor | #6a8098 | Alternate border |
| Tertiary | tertiaryColor | #182e2e | Muted teal fill |
| Tertiary | tertiaryTextColor | #d8dee6 | Third text |
| Tertiary | tertiaryBorderColor | #508888 | Third border |
| Lines | lineColor | #8a95a5 | Edge/arrow color |
| Lines | textColor | #d8dee6 | General text |
| Nodes | mainBkg | #1c3048 | Main background |
| Nodes | nodeBorder | #5a8ab4 | Node borders |
| Nodes | nodeTextColor | #d8dee6 | Node text |
| Clusters | clusterBkg | #10151e80 | Subgraph fill (50% opacity) |
| Clusters | clusterBorder | #3a4454 | Subgraph border |
| Labels | titleColor | #d8dee6 | Subgraph titles |
| Labels | edgeLabelBackground | #10151e | Edge label background |
| Labels | labelTextColor | #d8dee6 | Label text |
| Labels | labelBackground | #10151e | Label background |
| Sequence | actorBkg | #182230 | Actor box fill |
| Sequence | actorBorder | #5a8ab4 | Actor border |
| Sequence | actorTextColor | #d8dee6 | Actor text |
| Sequence | actorLineColor | #8a95a5 | Lifeline color |
| Sequence | signalColor | #8a95a5 | Message arrow |
| Sequence | signalTextColor | #d8dee6 | Message text |
| Sequence | labelBoxBkgColor | #182230 | Label box fill |
| Sequence | labelBoxBorderColor | #4a5568 | Label box border |
| Sequence | loopTextColor | #d8dee6 | Loop annotation text |
| Sequence | activationBorderColor | #5a8ab4 | Activation bar border |
| Sequence | activationBkgColor | #1c3048 | Activation bar fill |
| Sequence | sequenceNumberColor | #d8dee6 | Sequence number text |
| Sequence | noteBkgColor | #283848 | Note background |
| Sequence | noteBorderColor | #4a5568 | Note border |
| Sequence | noteTextColor | #d8dee6 | Note text |
| Class | classText | #d8dee6 | Class diagram text |
| Flowchart | fillType0 | #1c3048 | Steel blue |
| Flowchart | fillType1 | #1a2636 | Cool slate |
| Flowchart | fillType2 | #182e2e | Muted teal |
| Flowchart | fillType3 | #24303a | Warm grey |
| Flowchart | fillType4-7 | Repeat 0-3 | 8 fills cycling (no purple/red) |
| State/ER | labelColor | #d8dee6 | State label text |
| State/ER | altBackground | #182230 | Alternate background |
| State/ER | compositeBackground | #10151e80 | Composite fill |
| State/ER | compositeBorder | #3a4454 | Composite border |
| State/ER | compositeTitleBackground | #182230 | Composite title fill |
| State/ER | relationColor | #8a95a5 | Relation arrow |
| State/ER | relationLabelBackground | #10151e | Relation label bg |
| State/ER | relationLabelColor | #d8dee6 | Relation label text |
Neutral Professional Palette Principle: ALL text colors use #d8dee6 (muted off-white). ALL line/edge colors use #8a95a5 (medium grey). Node fills use muted steel blue, cool slate, and teal — no purple, no saturated colors. This creates a professional, readable appearance that works for both technical and executive audiences.
Rationale: These 60+ variables were tuned through multiple iterations across flowchart, sequence, class, and state/ER diagram types in BIO-QMS. The values are optimized for readability at 13px on dark backgrounds.
D5: Forced Dark Diagram Background
Mermaid diagram containers MUST use a forced dark background (#0f172a — slate-900) regardless of the viewer's light/dark mode setting.
.mermaid-diagram {
margin: 1.5rem 0;
padding: 1.5rem 1rem;
background: #0f172a;
border: 1px solid #334155;
border-radius: 0.5rem;
overflow-x: auto;
text-align: center;
}
Why NOT Dual-Theme:
- Mermaid's color system is tuned for one background — supporting both light and dark backgrounds doubles the theming work
- The dark palette was already tuned (60+ variables); creating a light-mode equivalent would require duplicating all values
- Forced dark creates a consistent "diagram island" that looks correct in any viewer theme
- Architecture diagrams contain colored subgraphs that conflict with light backgrounds
CSS Edge Thickness (REQUIRED):
.mermaid-diagram .edgePath .path,
.mermaid-diagram .flowchart-link,
.mermaid-diagram line,
.mermaid-diagram .relation,
.mermaid-diagram .messageLine0,
.mermaid-diagram .messageLine1 {
stroke-width: 2px !important;
}
.mermaid-diagram .actor-line {
stroke-width: 2.5px !important;
stroke: #e2e8f0 !important;
}
.mermaid-diagram .messageText {
font-size: 13px !important;
font-weight: 500 !important;
fill: #f1f5f9 !important;
}
Rationale: Default Mermaid edge widths (1px) are nearly invisible on dark backgrounds at typical screen resolutions. The 2px minimum ensures visibility without overwhelming the diagram content.
D6: Mermaid Subgraph Color Conventions
Architecture diagrams using Mermaid subgraphs MUST use the following semantic color palette for consistent visual communication across all projects:
| Category | Fill | Border | Semantic Meaning |
|---|---|---|---|
| Actors/Input | #1e3a5f | #38bdf8 | Users, external systems, entry points |
| Core/Control | #2d2250 | #818cf8 | Core logic, orchestration, control flow |
| Data/Workers | #1a3636 | #2dd4bf | Data processing, background jobs, pipelines |
| Persistence | #1e293b | #475569 | Databases, file systems, storage |
| Integration | #451a03 | #fbbf24 | External APIs, third-party services |
| Regulated | #3b1d1d | #f87171 | Compliance, audit, security-critical |
Mermaid Style Directive Format:
Rationale: Consistent colors across diagrams enable readers to instantly identify component categories without reading legends. This palette was tuned in BIO-QMS across 12 diagrams in 3 architecture documents.
D7: CSS Design Token Integration
Web publishing CSS MUST integrate with the CODITECT Design Tokens Standard (CODITECT-STANDARD-DESIGN-TOKENS.md). The following publishing-specific tokens extend the base token set:
:root {
/* Publishing Layout */
--coditect-pub-max-width: 900px;
--coditect-pub-sidebar-width: 280px;
--coditect-pub-header-height: 56px;
/* Publishing Typography */
--coditect-pub-font-body: "Inter", system-ui, -apple-system, sans-serif;
--coditect-pub-font-code: "JetBrains Mono", "Fira Code", monospace;
--coditect-pub-font-size-base: 15px;
--coditect-pub-line-height: 1.7;
/* Diagram Tokens */
--coditect-pub-diagram-bg: #0f172a;
--coditect-pub-diagram-border: #334155;
--coditect-pub-diagram-text: #f1f5f9;
--coditect-pub-diagram-line: #e2e8f0;
--coditect-pub-diagram-edge-width: 2px;
/* Code Block Tokens */
--coditect-pub-code-bg: #1e293b;
--coditect-pub-code-border: #334155;
--coditect-pub-code-text: #e2e8f0;
/* Metadata Bar */
--coditect-pub-meta-bg: var(--coditect-color-neutral-800);
--coditect-pub-meta-border: var(--coditect-color-neutral-700);
}
Rationale: Publishing-specific tokens with the --coditect-pub- prefix avoid collision with application-level tokens while maintaining the naming convention from CODITECT-STANDARD-DESIGN-TOKENS.md.
D8: Component Interface Contracts
Each component has a defined prop interface and behavioral contract:
MarkdownRenderer:
interface MarkdownRendererProps {
content: string; // Raw markdown with optional frontmatter
onHeadings?: (headings: Heading[]) => void; // TOC callback
className?: string; // Additional CSS classes
}
// Renders: frontmatter extraction → unified pipeline → Mermaid pre-render → HTML
// Exports: extractSections(content) for presentation mode
MermaidDiagram (standalone):
interface MermaidDiagramProps {
source: string; // Mermaid syntax (e.g., "graph TD\n A-->B")
id?: string; // Unique DOM ID (auto-generated if omitted)
className?: string;
}
// Renders: mermaid.render() → SVG string → div.mermaid-diagram
MetadataBar:
interface MetadataBarProps {
frontmatter: Record<string, any>; // Parsed YAML frontmatter
wordCount?: number;
}
// Renders: audience badge, category, status, word count
CodeBlock:
interface CodeBlockProps {
code: string;
language?: string;
showCopy?: boolean; // Default: true
showLineNumbers?: boolean; // Default: false
}
// Renders: syntax-highlighted code with copy button
Rationale: Defined interfaces enable the agentic system to generate, modify, and compose these components programmatically. When an agent creates a new project viewer, it knows exactly what props to pass and what behavior to expect.
D9: Project Scaffold Templates
Three scaffold templates enable rapid adoption:
Minimal Template (5 files):
project/
├── components/
│ └── MarkdownRenderer.jsx
├── styles.css # Dark-mode diagram CSS
├── vite.config.js
├── package.json # Exact dependency versions
└── index.html
Standard Template (10 files):
project/
├── components/
│ ├── MarkdownRenderer.jsx
│ ├── MetadataBar.jsx
│ ├── NavTree.jsx
│ └── SearchPanel.jsx
├── viewer.jsx # Main SPA shell
├── styles.css
├── tailwind.config.js
├── vite.config.js
├── package.json
└── index.html
Full Template (15+ files):
project/
├── components/
│ ├── MarkdownRenderer.jsx
│ ├── MetadataBar.jsx
│ ├── NavTree.jsx
│ ├── SearchPanel.jsx
│ ├── PresentationMode.jsx
│ └── DashboardLoader.jsx
├── dashboards/ # JSX dashboards
├── docs/ # Markdown content
├── scripts/
│ └── generate-publish-manifest.js
├── viewer.jsx
├── styles.css
├── tailwind.config.js
├── vite.config.js
├── package.json
├── publish.json # Content manifest (ADR-195)
└── index.html
Scaffold Command:
/component-create web-publisher my-project --template standard
Rationale: Templates eliminate the bootstrapping cost. A new project goes from zero to rendering markdown + Mermaid diagrams with correct theming in under 5 minutes.
D10: Dependency Pinning (REQUIRED)
All scaffold templates MUST pin exact dependency versions. No ^ or ~ semver ranges.
Canonical dependency set (as of February 2026):
{
"dependencies": {
"katex": "0.16.28",
"mermaid": "11.12.2",
"react": "19.2.4",
"react-dom": "19.2.4",
"rehype-autolink-headings": "7.1.0",
"rehype-highlight": "7.0.2",
"rehype-katex": "7.0.1",
"rehype-raw": "7.0.0",
"rehype-slug": "6.0.0",
"rehype-stringify": "10.0.1",
"remark-frontmatter": "5.0.0",
"remark-gfm": "4.0.1",
"remark-math": "6.0.0",
"remark-parse": "11.0.0",
"remark-rehype": "11.1.2",
"unified": "11.0.5"
},
"devDependencies": {
"@tailwindcss/vite": "4.1.18",
"@vitejs/plugin-react": "5.1.4",
"tailwindcss": "4.1.18",
"vite": "7.3.1"
}
}
Rationale: Rendering consistency requires identical dependency versions. A unified 11.0.5 → 12.0.0 upgrade could change HTML output, breaking diagram rendering. Version updates must be tested and applied across all projects simultaneously.
D11: Multi-Project Dashboard Switching (Phase 2)
A single viewer deployment supports switching between multiple projects, each with its own dashboard data and branding. This eliminates per-project viewer forks.
Project Configuration (project-config.json):
Each project defines a branding configuration file in the viewer root:
{
"id": "coditect-pilot",
"name": "CODITECT Pilot",
"title": "CODITECT Platform — Pilot Dashboard",
"description": "AI-Driven Work Order Platform for Regulated Industries",
"footer": "CODITECT Pilot | Internal"
}
Project Manifest (public/project-manifest.json):
Generated by scripts/generate-project-manifest.js from project-config.json. Lists all registered projects with their JSON data file paths:
{
"version": 1,
"generated": "2026-02-16T...",
"defaultProject": "coditect-pilot",
"projects": [
{
"id": "coditect-pilot",
"name": "CODITECT Pilot",
"title": "CODITECT Platform — Pilot Dashboard",
"description": "AI-Driven Work Order Platform",
"jsonFile": "project-dashboard-data.json",
"footer": "CODITECT Pilot | Internal"
}
]
}
ProjectSwitcher Component Interface:
interface ProjectSwitcherProps {
projects: Project[]; // From project-manifest.json
currentProject: Project; // Currently active project
onSwitch: (project: Project) => void; // Switch handler
}
// Exports: resolveInitialProject(projects, defaultId) helper
// Resolution priority: URL ?project=ID > localStorage > manifest defaultProject
// Single-project mode: component renders nothing (hidden)
Viewer Manifest Loading:
// viewer.jsx startup sequence:
// 1. Fetch /project-manifest.json (graceful fallback if missing)
// 2. resolveInitialProject() from URL/localStorage/default
// 3. Apply branding (title, description, footer) from matched project
// 4. Fetch project-specific JSON: project.jsonFile
Per-Project JSON Naming:
- Multi-project:
project-dashboard-data-{id}.json - Default fallback:
project-dashboard-data.json(backward compatible) - Generator flag:
--project IDproduces per-project filename
Rationale: Consumer projects (e.g., BIO-QMS) should NOT maintain local copies of viewer, components, dashboards, or scripts. Everything lives in coditect-core's tools/web-publishing-platform/ as the canonical source. Per-project differentiation is achieved through project-config.json (branding) and per-project JSON data files (content), not code forks. This was validated during J.18 consolidation where BIO-QMS was confirmed to have zero local dashboard infrastructure — all components are consumed from core.
Consequences
Positive
- Eliminate one-off publishing: Any CODITECT project adopts consistent rendering via scaffold templates
- Change CSS once, apply everywhere: Design token updates propagate to all projects using the token system
- Agentic reproducibility: The agentic system can create, modify, and deploy web publishing components by following the interface contracts
- Mermaid consistency: 60+ theme variables are standardized — no more per-project tuning
- Architecture diagram readability: Subgraph color conventions create visual consistency across all system diagrams
- Light/dark mode solved: Forced dark diagram background eliminates the dual-theme problem
Negative
- Opinionated theming: Projects cannot easily deviate from the dark-mode Mermaid theme without overriding the standard
- Dependency coupling: All projects must use the same unified/remark/rehype version chain
- React dependency: Components are React-specific (could be generalized to web components in future)
Risks
- Mermaid version upgrades: New Mermaid versions may change themeVariable behavior (mitigate: pin versions, test before upgrading)
- CSS specificity conflicts:
!importantoverrides in diagram CSS may conflict with project-specific styles (mitigate: scope all diagram CSS under.mermaid-diagram) - Template drift: Scaffold templates may diverge from the reference implementation over time (mitigate: automated template validation in CI)
Reference Implementation
BIO-QMS Viewer is the canonical reference implementation:
| File | Component | Lines |
|---|---|---|
components/MarkdownRenderer.jsx | Full rendering pipeline + Mermaid pre-render | 327 |
styles.css | Diagram CSS + dark-mode tokens + edge thickness | ~430 |
viewer.jsx | SPA shell with sidebar navigation | ~400 |
package.json | Exact pinned dependencies | 50 |
vite.config.js | Vite configuration with static copy | ~30 |
docs/architecture/14-c4-architecture.md | Subgraph styled architecture diagrams | ~300 |
docs/architecture/15-mermaid-diagrams.md | Full diagram gallery with all diagram types | ~400 |
Key commits:
03fa78d— feat(viewer): Add client-side Mermaid diagram rendering via mermaid.js8cae94f— fix(viewer): Unified dark-mode Mermaid diagram styling across all architecture docs
Migration Path for Existing Projects
Projects with existing markdown rendering (e.g., coditect-core component-viewer, trajectory-dashboard):
- Adopt
MarkdownRenderer.jsxfrom the standard template — drop-in replacement - Add Mermaid CSS to existing stylesheet (
.mermaid-diagramrules) - Add Mermaid dependency and initialize with standard themeVariables
- Update
package.jsonto use pinned versions - Validate against
CODITECT-STANDARD-WEB-PUBLISHING.mdquality criteria
Glossary
| Term | Definition |
|---|---|
| Pre-render | Converting Mermaid source to SVG string before React processes the HTML |
| Theme variables | Mermaid's 60+ CSS-like configuration values that control diagram appearance |
| Subgraph | A named group of nodes in a Mermaid flowchart, rendered as a bordered container |
| Forced dark | Using background: #0f172a on diagram containers regardless of viewer theme |
| Scaffold | A project template that includes all standard components pre-configured |
Related
- ADR-195: Push-Button Documentation Publishing Platform (platform architecture)
- ADR-196: NDA-Gated Conditional Access Control (authentication layer)
- ADR-085: Atomic Design Component Library (design system patterns)
- ADR-209: Executive Briefing Generator Integration (data-driven dashboard extension)
- CODITECT-STANDARD-DESIGN-TOKENS.md: Base design token definitions
- CODITECT-STANDARD-UI-UX.md: UI/UX design principles
- CODITECT-STANDARD-WEB-PUBLISHING.md: Implementation standard (companion to this ADR)
Author: Hal Casteel Project: PILOT (CODITECT Framework) Track: H.10 (Unified Web Publishing Component System)