ADR-195: Push-Button Documentation Publishing Platform
Status: Accepted Date: 2026-02-14 Deciders: Hal Casteel (CTO)
Context
CODITECT projects generate rich documentation corpora (markdown documents, JSX interactive dashboards, research artifacts). The BIO-QMS project alone has 83 artifacts (57 markdown + 26 JSX dashboards). Currently:
- JSX dashboards render in a Vite+React viewer but markdown documents have no rendering pipeline
- No search capability across content
- No presentation mode for screen-sharing demos (Zoom/Google Meet)
- No cloud publishing — content only viewable locally via
npm run dev - No reusable package — each project would need to rebuild viewer infrastructure
We need a push-button publishing platform that:
- Renders markdown alongside existing JSX dashboards in a unified viewer
- Provides full-text search across all content
- Supports presentation mode for investor demos
- Deploys to cloud with one command
- Is reusable across all CODITECT platform projects and customer projects
Decision
D1: Unified Markdown Pipeline (unified/remark/rehype)
Use the unified ecosystem for server-side and client-side markdown processing:
- remark-parse: Markdown → MDAST
- remark-gfm: GitHub Flavored Markdown (tables, task lists, strikethrough)
- remark-frontmatter: YAML frontmatter extraction
- remark-math: LaTeX math expression support
- rehype-stringify: MDAST → HTML
- rehype-highlight: Syntax highlighting via highlight.js
- rehype-slug: Heading ID generation
- rehype-autolink-headings: Clickable heading anchors
- rehype-katex: Math rendering via KaTeX
Rationale: unified is the industry standard for markdown processing in JavaScript. It's modular, extensible, and supports both build-time and runtime rendering. Better than marked (less extensible) or markdown-it (weaker ecosystem).
D2: publish.json Manifest
Each project declares its publishable content via a single publish.json manifest:
{
"project": "bio-qms",
"version": "1.0.0",
"title": "CODITECT Biosciences QMS Platform",
"base_url": "/bio-qms",
"auth_mode": "none",
"audiences": ["executive", "technical", "compliance"],
"documents": [
{
"id": "01-executive-summary",
"title": "Executive Summary",
"path": "docs/executive/01-executive-summary.md",
"type": "markdown",
"audience": "executive",
"category": "executive",
"keywords": ["overview", "investment", "market"],
"summary": "Platform overview and investment thesis"
}
]
}
Generation: scripts/generate-publish-manifest.js walks docs/, dashboards/, research/ directories, extracts frontmatter metadata, and emits public/publish.json.
Rationale: Decouples content organization from viewer implementation. Any project can adopt the viewer by generating a publish.json — no code changes needed.
D3: Unified Viewer (extending existing viewer.jsx)
Extend the existing Vite+React dashboard viewer to handle both document types:
- Markdown documents: Route to
MarkdownRenderercomponent - JSX dashboards: Route to existing dynamic import loader
- Detection:
typefield in publish.json determines renderer - Layout: Shared sidebar navigation, breadcrumbs, metadata bar
Rationale: Building on the existing viewer preserves the investment in 26 working dashboards. The viewer becomes a universal content platform rather than a dashboard-only tool.
D4: Client-Side Search (MiniSearch local / MCP API cloud)
Dual-mode search architecture:
| Mode | Engine | Index | Use Case |
|---|---|---|---|
| Local | MiniSearch | search-index.json (build-time) | Offline presentations, local dev |
| Cloud | MCP Semantic Search API | Server-side index | Production deployment, semantic queries |
- MiniSearch: Lightweight (8KB), fast, supports fuzzy matching, field boosting, prefix search
- Build-time indexing: Vite plugin extracts text during build, emits compressed index
- Size target: < 500KB compressed for 100+ documents
Rationale: Local-first search enables offline presentations. Cloud search adds semantic understanding for production deployments. MiniSearch is the best client-side option (better than Lunr.js for size and features).
D5: Presentation Mode
Full-screen presentation mode designed for screen-sharing:
- Entry: Toolbar button + keyboard shortcut (
P) - Navigation: Arrow keys (prev/next document), Up/Down (categories)
- Slide progression: H2 headings as slide boundaries within documents
- Chrome: Minimal — content only, no sidebar/search/breadcrumbs
- Timer: Elapsed time display (toggle with
T) - Presenter notes: Hidden panel visible in separate window
Rationale: Investor and partner demos are the primary use case for Sprint 1. Screen-sharing via Zoom/Google Meet requires clean, distraction-free rendering with keyboard-only navigation.
D6: Cloud Deployment (Cloud Run + CDN)
One-command deployment to GCP Cloud Run:
npm run publish # Build → validate → deploy → verify
- Static hosting: Cloud Run serving Nginx with SPA fallback
- CDN: Cloud CDN for static assets (30-day cache with content hash busting)
- URL:
docs.coditect.ai/{project}or{project}.docs.coditect.ai - SSL: Managed certificates via GCP
- Rollback: Keep previous 3 versions, instant rollback
Rationale: Cloud Run provides auto-scaling, custom domains, and managed SSL with minimal configuration. Combined with Cloud CDN, it delivers sub-100ms global latency for static content.
D7: Multi-Project npm Package
Extract the viewer as a reusable package:
- Package:
@coditect/doc-viewer - Components: MarkdownRenderer, DashboardLoader, SearchPanel, PresentationMode, NavTree
- Config: Accept
publish.jsonURL as primary configuration - Theme: CSS variables + Tailwind config for brand customization
- CLI:
npx @coditect/create-doc-site my-projectfor scaffolding
Rationale: Making the viewer reusable serves both CODITECT internal projects and future customer deployments. The publish.json contract ensures any project can adopt the platform without viewer code changes.
Consequences
Positive
- Unified content experience: All 83+ artifacts viewable in one interface
- Instant demos: Presentation mode enables investor/partner demos from day 1
- Cloud deployment: One-command publishing for any project
- Reusable: npm package serves all CODITECT projects and customers
- Offline-capable: Local search and presentation mode work without internet
- Standards-based: unified/remark ecosystem is well-maintained and extensible
Negative
- Build complexity: Vite plugin for search indexing adds build step
- Package maintenance: npm package requires versioning discipline
- Two search engines: MiniSearch (local) + MCP API (cloud) adds complexity
Risks
- MiniSearch index size: May exceed 500KB for very large document sets (mitigate: pagination, lazy loading)
- JSX security: Dynamic JSX import needs Content Security Policy consideration
- Offline drift: Local and cloud content may diverge (mitigate: version checking)
Implementation Phases
| Phase | Sprint | Scope |
|---|---|---|
| 1 | S1 | Markdown rendering + navigation + search + presentation mode (local) |
| 2 | S2 | Cloud deployment + CDN + publish CLI |
| 3 | S3 | NDA-gated access (ADR-196) + npm package extraction |
| 4 | S4+ | Semantic search (cloud), customer self-service |
Related
- ADR-196: NDA-Gated Conditional Access Control (authentication layer)
- ADR-015: Authentication Architecture (auth.coditect.ai)
- ADR-090: JWT Token Strategy (token format)
- ADR-145: Cloud Authentication (GCP integration)
Author: Hal Casteel Project: BIO-QMS (CODITECT Biosciences QMS Platform)