Skip to main content

CODITECT Doc Viewer — Customer Onboarding Guide

Version 1.0.0 | Status: Active | Last Updated: February 16, 2026


Table of Contents

  1. Welcome & Overview
  2. Prerequisites
  3. Quick Start (5-Minute Setup)
  4. Adding Your Content
  5. Configuring Your Site
  6. Adding JSX Dashboards
  7. Customizing the Theme
  8. Deploying to Production
  9. Setting Up Access Control
  10. Maintaining Your Site
  11. Reference Implementation: BIO-QMS
  12. Troubleshooting & FAQ
  13. Getting Support

1. Welcome & Overview

Welcome to the CODITECT Doc Viewer platform. This guide will help you deploy a world-class documentation site for your organization in under 30 minutes.

1.1 What CODITECT Doc Viewer Provides

The CODITECT Doc Viewer is a modern, client-side documentation platform that transforms markdown files and JSX dashboards into interactive, searchable documentation sites. Built for regulated industries and enterprise customers, it provides:

  • Unified Rendering Engine: Markdown with GitHub Flavored Markdown (GFM), YAML frontmatter, syntax highlighting, math equations (KaTeX), and Mermaid diagrams
  • Full-Text Search: MiniSearch-powered instant search across all documentation and dashboard content
  • Smart Navigation: Hierarchical sidebar, breadcrumbs, table of contents, keyboard shortcuts
  • Presentation Mode: Convert any document into a slide deck with keyboard navigation and timer
  • Interactive Dashboards: JSX components for data visualization, calculators, and interactive tools
  • Audience Segmentation: Organize content by audience (executive, technical, compliance, etc.)
  • Compliance-Ready: Audit trails, NDA-gated access, PDF export, print-optimized layouts

1.2 Architecture Overview

The CODITECT Doc Viewer is a client-side React Single Page Application (SPA):

  • No Backend Required: All content is served as static files (HTML, CSS, JS, markdown, images)
  • Build-Time Manifest: A publish.json manifest indexes all documents at build time for instant search
  • Vite-Powered: Fast development server with hot module replacement (HMR) and optimized production builds
  • CDN-Friendly: Deploy to any static hosting provider (Google Cloud Run, Vercel, Netlify, S3+CloudFront)
  • Framework: React 19, Tailwind CSS 4, Vite 7, MiniSearch, unified/remark/rehype markdown pipeline
┌─────────────────────────────────────────────────────────────┐
│ CODITECT Doc Viewer │
├─────────────────────────────────────────────────────────────┤
│ React SPA (viewer.jsx) │
│ ├─ MarkdownRenderer (unified + remark + rehype) │
│ ├─ SearchPanel (MiniSearch) │
│ ├─ Sidebar Navigation │
│ ├─ Breadcrumbs + TOC │
│ └─ PresentationMode │
├─────────────────────────────────────────────────────────────┤
│ Content Layer │
│ ├─ docs/ (markdown files with YAML frontmatter) │
│ ├─ dashboards/ (JSX React components) │
│ └─ public/publish.json (generated manifest) │
├─────────────────────────────────────────────────────────────┤
│ Static Assets │
│ ├─ images, diagrams, PDFs │
│ └─ CSS (Tailwind + custom themes) │
└─────────────────────────────────────────────────────────────┘

1.3 BIO-QMS Reference Implementation

This guide uses the CODITECT Bioscience QMS Platform as a reference implementation. BIO-QMS is a production documentation site with:

  • 133 documents across 14 categories
  • 83 markdown documents (executive summaries, architecture, compliance, operations)
  • 26 JSX dashboards (executive decision briefs, market analyzers, project trackers)
  • 8 audience categories (Executive, Technical, Compliance, Business, Planning, etc.)
  • Full-text search across 500,000+ words of content
  • GCP Cloud Run deployment with Identity-Aware Proxy (IAP) for NDA-gated access

Throughout this guide, we reference BIO-QMS patterns and configurations as proven examples.

1.4 Time Estimate

TaskTimePrerequisite
Initial setup (scaffolding)5 minutesNode.js installed
Adding first 10 documents15 minutesMarkdown files ready
Theme customization10 minutesBrand assets ready
Production deployment30-60 minutesCloud provider account
Total (first deployment)60-90 minutes-

After initial setup, adding new documents takes ~2 minutes per document (write markdown, regenerate manifest, deploy).


2. Prerequisites

Before starting, ensure you have the following:

2.1 Required Software

RequirementMinimum VersionCheck CommandInstall Guide
Node.js18.0.0+node --versionnodejs.org/download
npm9.0.0+npm --versionIncluded with Node.js
Git2.0.0+git --versiongit-scm.com/downloads

Verify your environment:

# Check Node.js version (must be 18+)
node --version
# Expected output: v18.x.x or higher

# Check npm version (must be 9+)
npm --version
# Expected output: 9.x.x or higher

# Check Git (for version control)
git --version
# Expected output: git version 2.x.x or higher

If Node.js is not installed or version is too old:

# macOS (using Homebrew)
brew install node

# Ubuntu/Debian
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Windows (using installer)
# Download from https://nodejs.org/download and run the MSI installer

2.2 Cloud Provider Account (for Production Deployment)

Choose one of the following cloud providers for production deployment:

ProviderFree TierBest ForSetup Time
VercelYes (100GB bandwidth/month)Fast deployment, preview URLs5 minutes
Google Cloud RunYes (2M requests/month)Regulated industries, IAP auth30 minutes
NetlifyYes (100GB bandwidth/month)Simple CI/CD, form handling10 minutes
AWS S3 + CloudFront12-month free tierFull AWS integration45 minutes

Recommendation: Start with Vercel for fastest setup, migrate to Google Cloud Run if you need compliance features (audit logging, IAP, VPC).

2.3 GitHub Account (for Package Access)

CODITECT packages are published to GitHub Packages (npm registry). You'll need:

  • A GitHub account
  • A Personal Access Token (PAT) with read:packages scope

Create a GitHub PAT:

  1. Go to github.com/settings/tokens
  2. Click "Generate new token (classic)"
  3. Select scope: read:packages
  4. Copy the token (save it securely — you won't see it again)

Configure npm to use GitHub Packages:

# Create .npmrc in your home directory
echo "@coditect:registry=https://npm.pkg.github.com" >> ~/.npmrc
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_PAT" >> ~/.npmrc

Replace YOUR_GITHUB_PAT with your actual token.

2.4 Basic Familiarity

You should have basic familiarity with:

  • Markdown syntax: Headings, lists, links, code blocks
  • Command line: Running commands in a terminal
  • Text editor: VS Code, Sublime Text, or similar (VS Code recommended)

Optional but helpful:

  • React/JSX (for creating custom dashboards)
  • Git (for version control)
  • CSS/Tailwind (for theme customization)

3. Quick Start (5-Minute Setup)

Let's create your first documentation site in 5 minutes.

3.1 Step 1: Scaffold a New Site

Run the @coditect/create-doc-site CLI tool to generate a new project:

# Create a new documentation site
npx @coditect/create-doc-site my-docs

# Expected output:
#
# 🚀 CODITECT Doc Viewer — Project Scaffolding
#
# This will create a new documentation site in ./my-docs
# Press Ctrl+C to cancel, or press Enter to continue...

What this does:

  • Downloads the latest @coditect/create-doc-site scaffolding tool
  • Creates a new directory my-docs/
  • Prompts you for configuration options
  • Installs all dependencies automatically

3.2 Step 2: Choose a Template

The CLI will ask you to choose a starting template:

? Choose a template:
> Bio-QMS (Full-featured: 133 docs, 26 dashboards, compliance-ready)
Generic (Minimal: 10 sample docs, basic navigation)
Blank (Empty: no sample content, fastest setup)

Template comparison:

TemplateDocumentsDashboardsUse CaseSetup Time
Bio-QMS13326Reference implementation, learn all features3 minutes
Generic100Standard documentation site, quick start1 minute
Blank00Custom site, bring your own content30 seconds

Recommendation: Choose Generic for your first site. You can always add Bio-QMS examples later.

3.3 Step 3: Answer Configuration Prompts

The CLI will ask for basic configuration:

? Project name: My Documentation Site
? Site title: Acme Corp Documentation
? Primary color (hex): #1e40af
? Logo URL (leave blank for default): https://acme.com/logo.png
? Enable authentication? No (local development)

Prompt explanations:

PromptPurposeExample
Project namenpm package name (kebab-case)my-documentation-site
Site titleDisplayed in header and browser tabAcme Corp Documentation
Primary colorBrand color for links, buttons, highlights#1e40af (blue)
Logo URLCompany logo in header (or local file path)/logo.png or URL
AuthenticationEnable IAP, basic auth, or noneNo for local dev

The CLI will then:

  1. Copy template files to my-docs/
  2. Generate package.json with your project name
  3. Create doc-site.config.js with your configuration
  4. Run npm install to install dependencies (~60 seconds)

3.4 Step 4: Start the Development Server

Navigate to your new project and start the development server:

cd my-docs
npm run dev

Expected output:

> my-documentation-site@1.0.0 dev
> vite --open

VITE v7.3.1 ready in 423 ms

➜ Local: http://localhost:5173/
➜ Network: http://192.168.1.100:5173/
➜ press h + enter to show help

What this does:

  • Starts Vite development server on http://localhost:5173
  • Opens your default browser automatically (due to --open flag)
  • Enables Hot Module Replacement (HMR): changes to files automatically reload the browser

3.5 Step 5: Explore Your Documentation Site

Your browser should now show your documentation site:

┌───────────────────────────────────────────────────────────┐
│ [Logo] My Documentation Site 🌙 🔍 ? [Avatar] │
├─────────────┬─────────────────────────────────────────────┤
│ │ │
│ 📁 Getting │ Welcome to My Documentation Site │
│ Started │ │
│ │ This is your documentation homepage. │
│ 📁 Guides │ │
│ │ 📑 10 documents • 5 categories │
│ 📁 Reference│ │
│ │ Choose a document from the sidebar │
│ 📁 API │ or use search (/) to find content. │
│ │ │
│ │ │
└─────────────┴─────────────────────────────────────────────┘

Test the key features:

FeatureActionExpected Result
SearchPress / or Ctrl+KSearch panel opens
NavigateClick "Getting Started" in sidebarDocument loads
Dark ModeClick moon icon in headerTheme switches to dark
Sidebar TogglePress Ctrl+B (or ⌘B on Mac)Sidebar collapses
Keyboard HelpPress ?Shortcuts modal appears

Congratulations! You now have a working documentation site running locally.


4. Adding Your Content

Now let's replace the sample content with your own documentation.

4.1 Document Directory Structure

All content lives in the docs/ directory. The directory structure determines navigation hierarchy:

my-docs/
├── docs/
│ ├── getting-started/
│ │ ├── 01-installation.md
│ │ ├── 02-quick-start.md
│ │ └── 03-first-project.md
│ ├── guides/
│ │ ├── authentication.md
│ │ ├── deployment.md
│ │ └── troubleshooting.md
│ ├── reference/
│ │ ├── api-reference.md
│ │ ├── configuration.md
│ │ └── glossary.md
│ └── architecture/
│ ├── system-overview.md
│ └── data-model.md
├── dashboards/ # Optional: JSX dashboards
│ └── executive/
│ └── metrics-dashboard.jsx
├── public/
│ └── publish.json # Generated automatically
└── package.json

Directory naming conventions:

  • Use kebab-case: getting-started, api-reference, user-guides
  • Use descriptive names: compliance, operations, architecture
  • Use numeric prefixes for ordering: 01-installation.md, 02-configuration.md

4.2 Markdown Format with YAML Frontmatter

Each markdown file starts with YAML frontmatter (metadata) followed by markdown content:

---
title: 'Installation Guide'
type: guide
audience: customer
category: getting-started
summary: 'Step-by-step installation instructions for all platforms'
keywords:
- installation
- setup
- prerequisites
tags:
- guide
- customer
status: active
created: '2026-02-16'
updated: '2026-02-16'
---

# Installation Guide

This guide walks you through installing the software on macOS, Windows, and Linux.

## Prerequisites

Before installing, ensure you have...

4.3 Required Frontmatter Fields

The following frontmatter fields are required for proper rendering and search:

FieldTypeDescriptionExample
titlestringDocument title (shown in sidebar, breadcrumbs)'Installation Guide'
audiencestringTarget audience (see Audience Categories below)'customer'
categorystringDocument category (maps to sidebar sections)'getting-started'

Minimal example:

---
title: 'Quick Start'
audience: technical
category: guides
---

4.4 Optional Frontmatter Fields

These fields enhance search, organization, and display:

FieldTypeDescriptionExample
summarystringShort description (shown in search results)'Step-by-step installation guide'
keywordsarraySearch keywords['install', 'setup', 'config']
tagsarrayTopic tags['guide', 'customer']
typestringDocument type'guide', 'reference', 'tutorial'
statusstringPublication status'active', 'draft', 'deprecated'
authorstringAuthor name'Jane Smith'
createdstringCreation date (ISO 8601)'2026-02-16'
updatedstringLast update date (ISO 8601)'2026-02-16'

4.5 Audience Categories

Organize content by audience to enable role-based navigation:

AudienceDescriptionTypical Content
executiveC-level, board membersExecutive summaries, business cases, ROI calculators
businessProduct managers, sales, marketingMarket analysis, competitive positioning, pricing
technicalEngineers, architectsSystem architecture, API reference, technical specs
contributorInternal developers, maintainersDevelopment guides, coding standards, workflows
complianceQA, regulatory, legalCompliance policies, audit procedures, validation
operationsSRE, DevOps, supportRunbooks, deployment guides, troubleshooting
customerEnd users, clientsUser guides, tutorials, FAQs

BIO-QMS example audience breakdown:

  • Executive: 6 docs (executive summaries, investment thesis)
  • Business: 8 dashboards (market analysis, revenue model)
  • Technical: 20 docs (architecture, API specs, data models)
  • Compliance: 10 docs (FDA 21 CFR Part 11, HIPAA, SOC2)
  • Operations: 14 docs (deployment, monitoring, incident response)

4.6 Adding Images, Diagrams, and Code Blocks

Images:

![Architecture Diagram](pathname://images/architecture.png)

<!-- Or use HTML for more control -->
<img src="../images/screenshot.png" alt="Screenshot" width="600" />

Place images in docs/images/ or public/images/.

Code blocks with syntax highlighting:

```javascript
// JavaScript example
function greet(name) {
return `Hello, ${name}!`;
}
```

```python
# Python example
def greet(name: str) -> str:
return f"Hello, {name}!"
```

```bash
# Bash example
echo "Hello, world!"
```

Supported languages: JavaScript, TypeScript, Python, Bash, JSON, YAML, SQL, Go, Rust, Java, C++, and 150+ more (via Highlight.js).

Tables (GitHub Flavored Markdown):

| Feature | Supported | Notes |
|---------|-----------|-------|
| Markdown || Full GFM support |
| Math || KaTeX rendering |
| Diagrams || Mermaid support |

Math equations (KaTeX):

Inline math: $E = mc^2$

Block math:

$$
\int_{a}^{b} f(x) \, dx = F(b) - F(a)
$$

Mermaid diagrams:

```mermaid
graph LR
A[User] --> B[Load Balancer]
B --> C[Web Server 1]
B --> D[Web Server 2]
C --> E[Database]
D --> E
```

4.7 Adding Your First Document

Let's create a new document step by step:

Step 1: Create the file

mkdir -p docs/guides
touch docs/guides/deployment.md

Step 2: Add frontmatter and content

Open docs/guides/deployment.md in your editor and add:

---
title: 'Deployment Guide'
type: guide
audience: operations
category: guides
summary: 'Production deployment instructions for cloud and on-premises environments'
keywords:
- deployment
- production
- cloud
- docker
tags:
- guide
- operations
status: active
created: '2026-02-16'
---

# Deployment Guide

This guide covers deploying to production environments.

## Prerequisites

- Docker 20.10+
- Kubernetes 1.24+ (for orchestration)
- Cloud provider account (GCP, AWS, or Azure)

## Deployment Steps

### 1. Build the Docker Image

```bash
docker build -t my-docs:1.0.0 .
docker tag my-docs:1.0.0 gcr.io/my-project/my-docs:1.0.0

2. Push to Container Registry

docker push gcr.io/my-project/my-docs:1.0.0

3. Deploy to Cloud Run

gcloud run deploy my-docs \
--image gcr.io/my-project/my-docs:1.0.0 \
--platform managed \
--region us-central1 \
--allow-unauthenticated

Verification

After deployment, verify the site is accessible:

curl https://my-docs-abc123.run.app

Troubleshooting

If the deployment fails, check the logs:

gcloud run logs read my-docs --limit 50

**Step 3: Regenerate the manifest**

After adding or modifying documents, regenerate the `publish.json` manifest:

```bash
npm run generate-manifest

Expected output:

> my-documentation-site@1.0.0 generate-manifest
> node scripts/generate-publish-manifest.js

Generated publish.json: 11 documents across 2 categories
Getting Started: 3 (3 markdown)
Guides: 8 (8 markdown)

Step 4: Verify in the browser

The development server automatically reloads. Navigate to your new document:

  • Click "Guides" in the sidebar
  • Click "Deployment Guide"
  • Verify frontmatter fields appear correctly

5. Configuring Your Site

Customize your site's appearance and behavior via doc-site.config.js.

5.1 Configuration File Structure

The doc-site.config.js file is generated during scaffolding. Here's the full structure:

// doc-site.config.js
export default {
// Branding
branding: {
siteName: "Acme Corp Documentation",
logo: "/logo.png",
favicon: "/favicon.ico",
colors: {
primary: "#1e40af",
secondary: "#3b82f6",
accent: "#60a5fa",
},
fonts: {
sans: "'Inter', system-ui, sans-serif",
mono: "'JetBrains Mono', 'Fira Code', monospace",
},
},

// Navigation
navigation: {
sidebar: {
order: ["getting-started", "guides", "reference", "api"],
collapsible: true,
defaultExpanded: ["getting-started"],
},
breadcrumbs: {
enabled: true,
showHome: true,
separator: "›",
},
toc: {
enabled: true,
maxDepth: 3,
minHeadings: 2,
},
},

// Features
features: {
search: {
enabled: true,
placeholder: "Search documentation...",
maxResults: 50,
},
presentationMode: {
enabled: true,
slideBreakLevel: 2, // H2 headings start new slides
},
darkMode: {
enabled: true,
default: "light",
},
printStyles: {
enabled: true,
removeInteractive: true,
},
},

// Authentication
auth: {
enabled: false,
provider: "none", // "none" | "gcp-iap" | "basic" | "custom"
config: {},
},

// Publishing
publish: {
manifestPath: "public/publish.json",
autoGenerate: true,
},
};

5.2 Branding Configuration

Update site name and logo:

branding: {
siteName: "Your Company Docs",
logo: "/assets/logo.png", // Path relative to public/
favicon: "/assets/favicon.ico",
}

Customize brand colors:

colors: {
primary: "#1e40af", // Links, active states
secondary: "#3b82f6", // Buttons, highlights
accent: "#60a5fa", // Tags, badges
}

Preview color changes:

After updating doc-site.config.js, the dev server reloads automatically. Check:

  • Links in content (should use primary color)
  • Sidebar active item (should use primary background)
  • Search highlights (should use accent color)

5.3 Navigation Configuration

Sidebar category order:

navigation: {
sidebar: {
order: ["getting-started", "guides", "api", "reference"],
collapsible: true,
defaultExpanded: ["getting-started", "guides"],
},
}

The order array determines sidebar section order. Categories not in order appear at the bottom in alphabetical order.

Table of contents (TOC) depth:

toc: {
enabled: true,
maxDepth: 3, // Show H1, H2, H3 (not H4+)
minHeadings: 2, // Only show TOC if document has 2+ headings
}

5.4 Feature Flags

Enable/disable presentation mode:

features: {
presentationMode: {
enabled: true,
slideBreakLevel: 2, // H2 starts new slide (or 1 for H1)
},
}

Customize search behavior:

search: {
enabled: true,
placeholder: "Search docs (press / to focus)",
maxResults: 50,
fuzzyThreshold: 0.2, // Lower = stricter matching
}

Dark mode settings:

darkMode: {
enabled: true,
default: "light", // "light" | "dark" | "system"
}

5.5 BIO-QMS Configuration Example

Here's the production doc-site.config.js from BIO-QMS:

export default {
branding: {
siteName: "CODITECT Bioscience QMS Platform",
logo: "/coditect-logo.png",
colors: {
primary: "#1e40af",
secondary: "#3b82f6",
accent: "#60a5fa",
},
},
navigation: {
sidebar: {
order: [
"executive",
"business",
"market",
"product",
"architecture",
"compliance",
"operations",
"planning",
],
defaultExpanded: ["executive", "business"],
},
toc: {
maxDepth: 4, // Show H1-H4 (deep technical docs)
minHeadings: 3,
},
},
features: {
search: {
maxResults: 100, // Large doc set
},
presentationMode: {
enabled: true,
slideBreakLevel: 2,
},
},
auth: {
enabled: true,
provider: "gcp-iap",
config: {
projectId: "coditect-citus-prod",
backendServiceId: "bio-qms-docs",
},
},
};

6. Adding JSX Dashboards

Beyond markdown documents, you can add interactive JSX dashboards for data visualization, calculators, and dynamic tools.

6.1 When to Use JSX vs Markdown

Use CaseFormatExample
Static content (text, images, tables)MarkdownUser guides, API reference, architecture docs
Interactive visualizationsJSX DashboardMarket analysis, ROI calculators, project trackers
Data tables with sorting/filteringJSX DashboardFeature comparison, pricing tables, status dashboards
Real-time updatesJSX DashboardLive metrics, system health, deployment status

Rule of thumb: If you need React state, event handlers, or complex UI components, use JSX. Otherwise, use markdown.

6.2 Dashboard Component Structure

Dashboards are React components that export a default function:

// dashboards/executive/roi-calculator.jsx

import { useState } from "react";
import { DollarSign, TrendingUp } from "lucide-react";

export default function ROICalculator() {
const [licenses, setLicenses] = useState(10);
const [pricePerLicense, setPricePerLicense] = useState(5000);

const annualRevenue = licenses * pricePerLicense * 12;
const threeYearValue = annualRevenue * 3;

return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-bold mb-4">ROI Calculator</h1>

<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div className="bg-surface border border-line rounded-lg p-4">
<label className="block text-sm font-medium mb-2">
Number of Licenses
</label>
<input
type="number"
value={licenses}
onChange={(e) => setLicenses(Number(e.target.value))}
className="w-full px-3 py-2 border rounded"
/>
</div>

<div className="bg-surface border border-line rounded-lg p-4">
<label className="block text-sm font-medium mb-2">
Price per License
</label>
<input
type="number"
value={pricePerLicense}
onChange={(e) => setPricePerLicense(Number(e.target.value))}
className="w-full px-3 py-2 border rounded"
/>
</div>
</div>

<div className="bg-primary-soft border border-primary rounded-lg p-6">
<div className="flex items-center gap-3 mb-2">
<DollarSign className="w-6 h-6 text-primary" />
<h2 className="text-xl font-bold">Annual Revenue</h2>
</div>
<p className="text-4xl font-bold text-primary">
${annualRevenue.toLocaleString()}
</p>
</div>
</div>
);
}

6.3 Dashboard Directory Structure

Place dashboards in dashboards/ organized by category:

dashboards/
├── executive/
│ ├── roi-calculator.jsx
│ ├── executive-summary.jsx
│ └── decision-brief.jsx
├── business/
│ ├── market-analysis.jsx
│ ├── revenue-model.jsx
│ └── competitive-landscape.jsx
├── technical/
│ ├── architecture-visualizer.jsx
│ ├── api-explorer.jsx
│ └── data-model-erd.jsx
└── operations/
├── deployment-status.jsx
└── system-health.jsx

6.4 Data Sources and Props

Dashboards can receive data from:

1. Hardcoded data (simplest):

const marketData = {
tam: 15.0,
sam: 2.4,
som: 0.8,
};

2. Fetched from API (dynamic):

import { useState, useEffect } from "react";

export default function SystemHealth() {
const [health, setHealth] = useState(null);

useEffect(() => {
fetch("/api/health")
.then((res) => res.json())
.then(setHealth);
}, []);

if (!health) return <div>Loading...</div>;

return <div>Status: {health.status}</div>;
}

3. Imported from JSON files:

import marketData from "../data/market-analysis.json";

export default function MarketDashboard() {
return (
<div>
<h1>TAM: ${marketData.tam}B</h1>
</div>
);
}

Place JSON data files in public/data/ or dashboards/data/.

6.5 Registering Dashboards in publish.json

The generate-publish-manifest.js script automatically indexes JSX files in dashboards/:

// scripts/generate-publish-manifest.js (excerpt)

const dashDir = join(ROOT, "dashboards");
const files = walk(dashDir, [".jsx"]);

for (const file of files) {
const relPath = relative(ROOT, file);
const parts = relPath.split("/");
const category = parts[1] || "Dashboards";

documents.push({
id: relPath.replace(/[/\\]/g, "-").replace(/\.jsx$/, ""),
title: titleFromFilename(file),
path: relPath,
type: "dashboard",
audience: "technical",
category,
keywords: [],
summary: "",
});
}

After adding a new dashboard:

npm run generate-manifest

The dashboard appears in the sidebar under its category.

6.6 BIO-QMS Dashboard Examples

BIO-QMS includes 26 dashboards across 4 categories:

DashboardCategoryPurposeKey Features
Executive Decision BriefBusinessC-level summary of productCards, metrics, risk matrix
Market Opportunity DashboardBusinessTAM/SAM/SOM analysisBar charts, competitor table, market signals
Revenue Model DashboardBusinessPricing tiers and projectionsInteractive tier selector, 5-year revenue chart
Comprehensive Compliance DashboardComplianceFDA, HIPAA, SOC2 statusCompliance scorecards, evidence links
Work Order State Machine VisualizerSystemFSM diagram with transitionsMermaid state machine, interactive guards
Project Command CenterPlanningReal-time project statusTrack completion, velocity, burndown chart

View the source:

All BIO-QMS dashboards are available in:

/dashboards/business/
/dashboards/compliance/
/dashboards/system/
/dashboards/planning/

7. Customizing the Theme

Tailor the visual design to match your brand.

7.1 CSS Variables Reference

The theme uses CSS custom properties (variables) for colors, spacing, fonts, and more. All variables are defined in styles.css:

/* styles.css */
:root {
/* Colors — Light Mode */
--color-background: #ffffff;
--color-surface: #f9fafb;
--color-surface-dim: #f3f4f6;
--color-line: #e5e7eb;
--color-line-soft: #f3f4f6;
--color-heading: #111827;
--color-body: #374151;
--color-muted: #6b7280;
--color-label: #9ca3af;

/* Primary Brand Colors */
--color-primary: #1e40af;
--color-primary-hover: #1e3a8a;
--color-primary-soft: #dbeafe;

/* Semantic Colors */
--color-success: #059669;
--color-warning: #d97706;
--color-danger: #dc2626;
--color-info: #0ea5e9;

/* Typography */
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.5rem;
--font-size-3xl: 1.875rem;

/* Spacing */
--spacing-1: 0.25rem;
--spacing-2: 0.5rem;
--spacing-3: 0.75rem;
--spacing-4: 1rem;
--spacing-6: 1.5rem;
--spacing-8: 2rem;
--spacing-12: 3rem;

/* Layout */
--sidebar-width: 16rem;
--header-height: 4rem;
--max-content-width: 80rem;

/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);

/* Transitions */
--transition-fast: 150ms ease;
--transition-base: 300ms ease;
--transition-slow: 500ms ease;
}

/* Dark Mode */
[data-theme="dark"] {
--color-background: #0f172a;
--color-surface: #1e293b;
--color-surface-dim: #334155;
--color-line: #475569;
--color-line-soft: #334155;
--color-heading: #f1f5f9;
--color-body: #cbd5e1;
--color-muted: #94a3b8;
--color-label: #64748b;

--color-primary: #3b82f6;
--color-primary-hover: #60a5fa;
--color-primary-soft: #1e3a8a;
}

Complete CSS variables table:

VariableLight ModeDark ModeUsage
--color-background#ffffff#0f172aPage background
--color-surface#f9fafb#1e293bCards, panels
--color-surface-dim#f3f4f6#334155Hover states
--color-line#e5e7eb#475569Borders
--color-heading#111827#f1f5f9H1-H6 headings
--color-body#374151#cbd5e1Body text
--color-muted#6b7280#94a3b8Secondary text
--color-primary#1e40af#3b82f6Links, buttons
--color-primary-hover#1e3a8a#60a5faHover states
--color-primary-soft#dbeafe#1e3a8aBackgrounds
--color-success#059669#10b981Success states
--color-warning#d97706#f59e0bWarning states
--color-danger#dc2626#ef4444Error states
--font-sans'Inter''Inter'Sans-serif font
--font-mono'JetBrains Mono''JetBrains Mono'Code font
--sidebar-width16rem16remSidebar width
--header-height4rem4remHeader height

7.2 Tailwind Configuration Extension

The project uses Tailwind CSS 4 for utility classes. Extend the configuration by creating a tailwind.config.js file if it doesn't exist:

// tailwind.config.js
export default {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'var(--color-primary)',
hover: 'var(--color-primary-hover)',
soft: 'var(--color-primary-soft)',
},
surface: 'var(--color-surface)',
heading: 'var(--color-heading)',
body: 'var(--color-body)',
muted: 'var(--color-muted)',
},
fontFamily: {
sans: ['var(--font-sans)'],
mono: ['var(--font-mono)'],
},
spacing: {
sidebar: 'var(--sidebar-width)',
header: 'var(--header-height)',
},
},
},
};

Using Tailwind classes in content:

<div className="bg-surface border border-line rounded-lg p-4">
<h2 className="text-heading text-2xl font-bold mb-2">Title</h2>
<p className="text-body">Body text</p>
<button className="bg-primary text-white px-4 py-2 rounded hover:bg-primary-hover">
Click Me
</button>
</div>

Override default components by editing files in the components/ directory:

Header customization:

// components/Header.jsx
export default function Header({ siteName, logo }) {
return (
<header className="h-header bg-surface border-b border-line px-6 flex items-center justify-between">
<div className="flex items-center gap-4">
<img src={logo} alt={siteName} className="h-8" />
<h1 className="text-xl font-bold text-heading">{siteName}</h1>
</div>
<nav className="flex items-center gap-4">
<a href="/support" className="text-body hover:text-heading">Support</a>
<a href="/pricing" className="text-body hover:text-heading">Pricing</a>
<button className="bg-primary text-white px-4 py-2 rounded">
Sign In
</button>
</nav>
</header>
);
}

Footer customization:

// components/Footer.jsx
export default function Footer() {
return (
<footer className="bg-surface border-t border-line py-8 px-6 text-center">
<p className="text-muted text-sm">
© {new Date().getFullYear()} Acme Corp. All rights reserved.
</p>
<div className="flex justify-center gap-4 mt-4">
<a href="/privacy" className="text-muted hover:text-primary">Privacy</a>
<a href="/terms" className="text-muted hover:text-primary">Terms</a>
<a href="/contact" className="text-muted hover:text-primary">Contact</a>
</div>
</footer>
);
}

7.4 Dark Mode Configuration

Dark mode is controlled by the data-theme attribute on the <html> element:

// Toggle dark mode
const toggleDarkMode = () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
};

Persist user preference:

// Load saved theme on page load
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);

The default implementation (in viewer.jsx) already handles this.

7.5 Print Styles Customization

The print stylesheet removes interactive elements for clean PDF export:

/* styles.css — Print Styles */
@media print {
/* Hide interactive elements */
.sidebar,
.search-panel,
.breadcrumbs,
header button,
.keyboard-shortcut,
.toc-toggle {
display: none !important;
}

/* Full-width content */
main {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
}

/* Page breaks */
h1, h2 {
page-break-after: avoid;
}

pre, table {
page-break-inside: avoid;
}

/* High-contrast text */
body {
color: #000;
background: #fff;
}

/* Show URLs in links */
a::after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #666;
}
}

Test print layout:

  1. Open any document
  2. Press Ctrl+P (or ⌘P on Mac)
  3. Preview the print layout
  4. Verify header, footer, sidebar are hidden
  5. Verify page breaks are sensible

7.6 Responsive Breakpoints

The default breakpoints match Tailwind CSS:

BreakpointMin WidthCSS ClassUse Case
sm640pxsm:flexLarge phones
md768pxmd:grid-cols-2Tablets
lg1024pxlg:w-sidebarLaptops
xl1280pxxl:max-w-7xlDesktops
2xl1536px2xl:px-12Large screens

Mobile-first design:

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* 1 column on mobile, 2 on tablet, 3 on desktop */}
</div>

8. Deploying to Production

Deploy your documentation site to a production environment.

8.1 Build for Production

Before deploying, create an optimized production build:

npm run build

Expected output:

> my-documentation-site@1.0.0 build
> node scripts/generate-publish-manifest.js && vite build

Generated publish.json: 11 documents across 2 categories
Getting Started: 3 (3 markdown)
Guides: 8 (8 markdown)

vite v7.3.1 building for production...
1247 modules transformed.
dist/index.html 2.14 kB │ gzip: 0.89 kB
dist/assets/index-abc123.css 45.32 kB │ gzip: 11.24 kB
dist/assets/index-def456.js 312.45 kB │ gzip: 98.76 kB

✓ built in 8.42s

What this does:

  1. Generates public/publish.json manifest
  2. Bundles React components and dependencies
  3. Minifies JavaScript and CSS
  4. Optimizes images
  5. Outputs to dist/ directory

The dist/ directory contains:

dist/
├── index.html # Entry point
├── assets/
│ ├── index-abc123.css # Bundled CSS
│ ├── index-def456.js # Bundled JavaScript
│ └── vendor-xyz789.js # Third-party libraries
├── docs/ # Markdown files (copied)
├── dashboards/ # Dashboard bundles
├── publish.json # Document manifest
└── images/ # Static assets

This is a static site — no server-side rendering or API required.

8.2 Deployment Options

Choose a deployment platform based on your requirements:

PlatformCostSetup TimeBest ForFeatures
VercelFree tier5 minQuick launch, preview URLsAuto-deploy, CDN, analytics
Google Cloud RunPay-per-use30 minEnterprise, IAP authCustom domains, VPC, audit logs
NetlifyFree tier10 minJAMstack, formsSplit testing, serverless functions
AWS S3 + CloudFront~$1-5/mo45 minAWS ecosystemS3 bucket, CloudFront CDN
Self-hosted (Nginx)Server cost60 minOn-premises, full controlCustom SSL, reverse proxy

Google Cloud Run provides:

  • Identity-Aware Proxy (IAP): OAuth 2.0 authentication, NDA-gated access
  • Audit Logging: Track all access for compliance
  • VPC Connectivity: Private network access
  • Custom Domains: docs.acme.com
  • Auto-scaling: 0 to 1000+ instances

Prerequisites:

Step 1: Create a Dockerfile

# Dockerfile
FROM nginx:alpine

# Copy built site to nginx html directory
COPY dist/ /usr/share/nginx/html/

# Copy custom nginx config (optional)
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 8080

CMD ["nginx", "-g", "daemon off;"]

Step 2: Create nginx configuration

# nginx.conf
server {
listen 8080;
server_name _;

root /usr/share/nginx/html;
index index.html;

# SPA routing — always serve index.html
location / {
try_files $uri $uri/ /index.html;
}

# Cache static assets for 1 year
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

# Don't cache HTML
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
}

Step 3: Create a Cloud Build configuration

# cloudbuild.yaml
steps:
# Build the Docker image
- name: 'gcr.io/cloud-builders/docker'
args:
- 'build'
- '-t'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docs/viewer:$SHORT_SHA'
- '.'

# Push the image to Artifact Registry
- name: 'gcr.io/cloud-builders/docker'
args:
- 'push'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docs/viewer:$SHORT_SHA'

# Deploy to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- 'run'
- 'deploy'
- 'my-docs'
- '--image=us-central1-docker.pkg.dev/$PROJECT_ID/my-docs/viewer:$SHORT_SHA'
- '--platform=managed'
- '--region=us-central1'
- '--allow-unauthenticated'
- '--memory=512Mi'
- '--cpu=1'
- '--max-instances=10'

images:
- 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docs/viewer:$SHORT_SHA'

options:
machineType: 'N1_HIGHCPU_8'

Step 4: Deploy

# Set your GCP project ID
export PROJECT_ID=your-project-id
gcloud config set project $PROJECT_ID

# Create Artifact Registry repository (one-time)
gcloud artifacts repositories create my-docs \
--repository-format=docker \
--location=us-central1 \
--description="Documentation site images"

# Build and deploy via Cloud Build
gcloud builds submit --config=cloudbuild.yaml

# Expected output:
# Creating temporary tarball archive of 87 file(s) totalling 12.3 MiB...
# Uploading tarball of [.] to [gs://your-project_cloudbuild/source/...]
# ...
# ID CREATE_TIME DURATION STATUS
# abc123-def456-ghi789 2026-02-16T12:00:00+00:00 2M 14S SUCCESS

Step 5: Verify deployment

# Get the service URL
gcloud run services describe my-docs \
--region=us-central1 \
--format='value(status.url)'

# Expected output:
# https://my-docs-abc123xyz-uc.a.run.app

# Test the deployment
curl https://my-docs-abc123xyz-uc.a.run.app

Step 6: Configure custom domain (optional)

# Map custom domain
gcloud run domain-mappings create \
--service=my-docs \
--domain=docs.acme.com \
--region=us-central1

# Follow the instructions to add DNS records at your domain registrar

Step 7: Enable IAP for authentication (optional)

# Enable IAP on the Cloud Run service
gcloud iap web enable \
--resource-type=cloud-run \
--service=my-docs \
--region=us-central1

# Add users to IAP access list
gcloud iap web add-iam-policy-binding \
--resource-type=cloud-run \
--service=my-docs \
--region=us-central1 \
--member=user:jane@acme.com \
--role=roles/iap.httpsResourceAccessor

8.4 Option B: Deploy to Vercel (Fastest Setup)

Vercel provides the fastest deployment with automatic preview URLs for every Git push.

Prerequisites:

Step 1: Connect Git repository

# Push your code to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/your-org/my-docs.git
git push -u origin main

Step 2: Import to Vercel

  1. Go to vercel.com/new
  2. Click "Import Git Repository"
  3. Select your repository
  4. Configure project settings:
Framework Preset: Vite
Build Command: npm run build
Output Directory: dist
Install Command: npm install
  1. Click "Deploy"

Step 3: Configure environment variables (optional)

If you need environment variables (e.g., API keys):

  1. Go to Project Settings → Environment Variables
  2. Add variables:
VITE_API_BASE_URL=https://api.acme.com
VITE_ANALYTICS_ID=G-XXXXXXXXXX
  1. Redeploy

Step 4: Configure custom domain

  1. Go to Project Settings → Domains
  2. Add your domain: docs.acme.com
  3. Add DNS records at your registrar:
Type: CNAME
Name: docs
Value: cname.vercel-dns.com
  1. Wait for DNS propagation (~5-10 minutes)
  2. Vercel automatically provisions SSL certificate

Step 5: Enable preview deployments

Every Git push creates a unique preview URL:

git checkout -b feature/new-guide
# Edit docs/guides/new-guide.md
git add .
git commit -m "Add new guide"
git push origin feature/new-guide

Vercel comments on the PR with a preview URL: https://my-docs-git-feature-new-guide-yourorg.vercel.app

8.5 Option C: Deploy to Netlify

Netlify provides similar features to Vercel with additional form handling and serverless functions.

Step 1: Create netlify.toml configuration

# netlify.toml
[build]
command = "npm run build"
publish = "dist"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/*.html"
[headers.values]
Cache-Control = "no-cache, no-store, must-revalidate"

Step 2: Deploy via Netlify CLI

# Install Netlify CLI
npm install -g netlify-cli

# Login
netlify login

# Initialize site
netlify init

# Build and deploy
netlify deploy --prod

Step 3: Configure custom domain

# Add custom domain
netlify domains:add docs.acme.com

# Netlify provides DNS records to add at your registrar

8.6 Option D: Self-Hosted (Nginx/Apache)

For on-premises or custom hosting.

Prerequisites:

  • Linux server (Ubuntu, CentOS, etc.)
  • Nginx or Apache installed
  • Domain pointing to server IP
  • SSL certificate (Let's Encrypt recommended)

Step 1: Build and transfer files

# Build locally
npm run build

# Transfer to server (via scp, rsync, or Git)
rsync -avz dist/ user@server:/var/www/my-docs/

Step 2: Configure Nginx

# /etc/nginx/sites-available/my-docs
server {
listen 80;
server_name docs.acme.com;

# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name docs.acme.com;

# SSL certificates (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/docs.acme.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/docs.acme.com/privkey.pem;

root /var/www/my-docs;
index index.html;

# SPA routing
location / {
try_files $uri $uri/ /index.html;
}

# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}

Step 3: Enable site and reload Nginx

# Enable site
sudo ln -s /etc/nginx/sites-available/my-docs /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx

Step 4: Obtain SSL certificate (Let's Encrypt)

# Install Certbot
sudo apt-get install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d docs.acme.com

# Auto-renewal is configured by default
sudo certbot renew --dry-run

8.7 CDN Caching Configuration

For optimal performance, configure CDN caching:

Google Cloud CDN (Cloud Run):

gcloud compute backend-services update my-docs \
--global \
--enable-cdn \
--cache-mode=CACHE_ALL_STATIC \
--default-ttl=3600 \
--max-ttl=86400

Cloudflare CDN:

Cache Rules:
- *.js, *.css: Cache Everything, Edge TTL 1 year
- *.html: Bypass cache
- *.md, *.json: Edge TTL 1 hour

Vercel CDN:

Vercel automatically caches static assets. To customize:

// vercel.json
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
]
}

9. Setting Up Access Control

Control who can access your documentation site.

9.1 Access Control Options

MethodSecurity LevelUse CaseSetup Time
None (public)LowOpen-source docs, public APIs0 min
Basic AuthLowInternal staging sites5 min
GCP IAPHighEnterprise, regulated industries30 min
NDA-GatedHighCustomer portals, partner docs60 min (custom)
SAML/SSOHighEnterprise SSO integrationVaries

9.2 Local Development: Bypass Mode

During local development, authentication is typically bypassed:

// doc-site.config.js
auth: {
enabled: false,
provider: "none",
}

9.3 Basic Authentication (Environment Variable)

Simple username/password auth for staging sites.

Step 1: Configure basic auth

// doc-site.config.js
auth: {
enabled: true,
provider: "basic",
config: {
username: process.env.BASIC_AUTH_USER,
password: process.env.BASIC_AUTH_PASS,
},
}

Step 2: Set environment variables

# Vercel
vercel env add BASIC_AUTH_USER
vercel env add BASIC_AUTH_PASS

# Google Cloud Run
gcloud run services update my-docs \
--update-env-vars BASIC_AUTH_USER=admin,BASIC_AUTH_PASS=secret123

Step 3: Add authentication middleware

// middleware/basic-auth.js
export function basicAuth(req, res, next) {
const auth = req.headers.authorization;
if (!auth) {
res.setHeader('WWW-Authenticate', 'Basic realm="Docs"');
return res.status(401).send('Authentication required');
}

const [username, password] = Buffer.from(auth.split(' ')[1], 'base64')
.toString()
.split(':');

if (username === process.env.BASIC_AUTH_USER &&
password === process.env.BASIC_AUTH_PASS) {
return next();
}

res.status(401).send('Invalid credentials');
}

9.4 GCP Identity-Aware Proxy (IAP)

IAP provides OAuth 2.0 authentication with Google/corporate accounts.

Prerequisites:

  • Cloud Run service deployed
  • Domain configured
  • OAuth consent screen configured

Step 1: Enable IAP

# Enable IAP API
gcloud services enable iap.googleapis.com

# Create Backend Service for Cloud Run
gcloud compute backend-services create my-docs-backend \
--global \
--load-balancing-scheme=EXTERNAL_MANAGED \
--protocol=HTTPS

# Enable IAP on backend service
gcloud iap web enable \
--resource-type=backend-services \
--service=my-docs-backend

Step 2: Configure OAuth consent screen

  1. Go to console.cloud.google.com/apis/credentials
  2. Click "Configure Consent Screen"
  3. Choose "Internal" (for Workspace) or "External"
  4. Fill in:
  5. Save

Step 3: Create OAuth client

# Create OAuth client
gcloud iap oauth-brands create \
--application_title="My Docs" \
--support_email=your-email@acme.com

# Create OAuth client credentials
gcloud iap oauth-clients create \
BRAND_NAME \
--display_name="My Docs Client"

Step 4: Add authorized users

# Add individual users
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=my-docs-backend \
--member=user:jane@acme.com \
--role=roles/iap.httpsResourceAccessor

# Add entire domain (Google Workspace)
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=my-docs-backend \
--member=domain:acme.com \
--role=roles/iap.httpsResourceAccessor

# Add group
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=my-docs-backend \
--member=group:docs-users@acme.com \
--role=roles/iap.httpsResourceAccessor

Step 5: Verify IAP is active

# Try accessing without auth (should redirect to Google login)
curl https://docs.acme.com

# Expected output:
# <HTML><HEAD><TITLE>IAP Authentication</TITLE>...

9.5 NDA-Gated Access (CODITECT Custom Auth)

BIO-QMS uses CODITECT's custom NDA-gated authentication for investor/partner access.

Architecture:

User → IAP → Cloud Run → React App → CODITECT Auth API

Token Verification

Access Decision

Configuration:

// doc-site.config.js
auth: {
enabled: true,
provider: "coditect-auth",
config: {
authEndpoint: "https://api.coditect.ai/v1/auth/verify",
ndaRequired: true,
allowedRoles: ["investor", "partner", "customer"],
},
}

Token verification flow:

  1. User visits site → redirected to CODITECT login
  2. User signs NDA → receives JWT token
  3. React app sends token with each request
  4. Backend verifies token signature and claims
  5. Access granted/denied based on role

9.6 Token Management and Revocation

Token storage (client-side):

// Store token in localStorage
localStorage.setItem('auth_token', token);

// Include in API requests
fetch('/api/data', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`,
},
});

Token revocation (server-side):

# Revoke user access (IAP)
gcloud iap web remove-iam-policy-binding \
--resource-type=backend-services \
--service=my-docs-backend \
--member=user:former-employee@acme.com \
--role=roles/iap.httpsResourceAccessor

# List all authorized users
gcloud iap web get-iam-policy \
--resource-type=backend-services \
--service=my-docs-backend

10. Maintaining Your Site

Keep your documentation site up to date and performant.

10.1 Updating @coditect/doc-viewer

Check for updates regularly:

# Check current version
npm list @coditect/doc-viewer

# Check for updates
npm outdated

# Update to latest version
npm update @coditect/doc-viewer

# Or update to specific version
npm install @coditect/doc-viewer@1.2.0

After updating, test thoroughly:

  1. Run npm run dev and verify local site works
  2. Test search, navigation, dark mode
  3. Check dashboards for breaking changes
  4. Run npm run build and verify production build
  5. Deploy to staging before production

10.2 Regenerating publish.json After Adding Documents

Every time you add, remove, or modify documents, regenerate the manifest:

# Regenerate manifest
npm run generate-manifest

# Or automatically as part of build
npm run build

The manifest includes:

  • Document paths and IDs
  • Frontmatter metadata (title, audience, category)
  • Full-text search index (stripped markdown)
  • Category statistics

Manifest size considerations:

  • BIO-QMS: 133 documents → 1.7 MB publish.json
  • Generic: 10 documents → ~100 KB publish.json
  • The manifest is gzipped by CDN (typically 10-20% of original size)

10.3 Version Pinning Strategy

Lock dependencies to prevent breaking changes:

// package.json
{
"dependencies": {
"@coditect/doc-viewer": "1.2.0", // Exact version (no ^)
"react": "19.2.4",
"vite": "7.3.1"
}
}

Use npm shrinkwrap for stricter locking:

# Generate package-lock.json
npm install

# Create npm-shrinkwrap.json (committed to Git)
npm shrinkwrap

Audit dependencies for vulnerabilities:

# Check for vulnerabilities
npm audit

# Auto-fix non-breaking vulnerabilities
npm audit fix

# View detailed audit report
npm audit --json > audit-report.json

10.4 Breaking Change Migration Guides

When @coditect/doc-viewer has breaking changes, migration guides are published at:

https://docs.coditect.ai/doc-viewer/migrations/

Example migration: v1.0 → v2.0

# Migration Guide: v1.0 → v2.0

## Breaking Changes

1. **Configuration format changed**
- Before: `doc-viewer.config.js`
- After: `doc-site.config.js`

2. **Frontmatter field renamed**
- Before: `type: 'doc'`
- After: `type: 'reference'`

3. **Dashboard component signature**
- Before: `export default function Dashboard(props) {}`
- After: `export default function Dashboard({ data }) {}`

## Migration Steps

1. Rename config file:
```bash
mv doc-viewer.config.js doc-site.config.js
  1. Update frontmatter in all docs:

    find docs -name "*.md" -exec sed -i '' 's/type: doc/type: reference/g' {} \;
  2. Update dashboard components (manual)

  3. Test and redeploy


### 10.5 Monitoring Deployment Health

**Google Cloud Run monitoring:**

```bash
# View logs
gcloud run logs read my-docs --limit 100

# View metrics
gcloud run services describe my-docs \
--region=us-central1 \
--format='value(status.traffic[0].percent)'

# Set up alerts
gcloud alpha monitoring policies create \
--notification-channels=CHANNEL_ID \
--display-name="Docs High Error Rate" \
--condition-threshold-value=0.05 \
--condition-threshold-duration=300s

Vercel monitoring:

  1. Go to Project → Analytics
  2. View metrics:
    • Page views
    • Unique visitors
    • Response times
    • Error rates
  3. Set up alerts for:
    • 5xx errors > 1%
    • p95 response time > 500ms

Uptime monitoring (external):

Use a service like UptimeRobot, Pingdom, or Google Cloud Monitoring:

# Create uptime check (Google Cloud)
gcloud monitoring uptime create https-check \
--display-name="Docs Site Uptime" \
--resource-type=uptime-url \
--monitored-resource=https://docs.acme.com \
--period=60 \
--timeout=10s

11. Reference Implementation: BIO-QMS

Learn from the production BIO-QMS documentation site.

11.1 BIO-QMS Overview

CODITECT Bioscience QMS Platform is a comprehensive documentation site showcasing all features of the Doc Viewer:

MetricValueDetails
Total Documents13383 markdown + 50 JSX + session logs
Categories14Executive, Business, Market, Technical, Compliance, etc.
Audience Segments8Executive, Business, Technical, Contributor, Compliance, Operations, Customer, Research
Dashboards26Interactive React components
Search Index Size500,000+ wordsFull-text searchable
DeploymentGoogle Cloud RunWith IAP authentication
URLInternalNDA-gated access only

11.2 Document Organization: 83 Markdown Documents

Executive (6 docs):

  • 00-executive-summary.md — C-level overview
  • 01-strategic-rationale.md — Why build this?
  • 02-investment-thesis.md — ROI and market opportunity
  • 03-go-to-market-strategy.md — GTM plan
  • 04-competitive-advantage.md — Moats and differentiation
  • 05-risk-assessment.md — Risks and mitigations

Market (20 docs):

  • TAM/SAM/SOM analysis
  • Competitive landscape
  • Market segmentation
  • Buyer personas
  • Pricing strategy

Architecture (6 docs):

  • System architecture
  • Data model ERD
  • API specification
  • State machine FSM
  • Agent orchestration
  • Technology stack

Compliance (10 docs):

  • FDA 21 CFR Part 11 compliance
  • HIPAA security controls
  • SOC 2 Type II readiness
  • GxP validation approach
  • Audit trail specification
  • Electronic signature requirements

Operations (14 docs):

  • Deployment guide
  • Monitoring and alerting
  • Incident response runbook
  • Backup and recovery
  • Scaling strategy
  • Security hardening

11.3 Interactive Dashboards: 26 JSX Components

Business Category (8 dashboards):

  1. Executive Decision Brief — One-page C-level summary with key metrics, risk matrix, and go/no-go recommendation
  2. Strategic Fit Dashboard — Product-market fit analysis with scoring matrix
  3. Market Opportunity Dashboard — TAM/SAM/SOM visualizations, competitor radar chart, market signals timeline
  4. Market Impact Analyzer — Market dynamics, buyer journey, value chain
  5. TAM/SAM/SOM Visualizer — Interactive segmentation with drill-down
  6. Revenue Model Dashboard — Pricing tiers, 5-year projections, unit economics
  7. Investor Pitch Dashboard — Pitch deck data points with charts
  8. Business Case Calculator — ROI calculator with sensitivity analysis

Compliance Category (4 dashboards):

  1. Comprehensive Compliance Dashboard — FDA, HIPAA, SOC 2 status cards
  2. Regulatory Compliance Tracker — Requirement checklist with evidence links
  3. Compliance Value Chain — Process flow with control points
  4. Compliance ROI Calculator — Cost of non-compliance vs. compliance

System Category (7 dashboards):

  1. Tech Architecture Analyzer — Component dependency graph
  2. WO Unified System Dashboard — System overview with key metrics
  3. WO State Machine Visualizer — FSM diagram with transitions and guards
  4. WO Data Model Explorer — Entity relationship diagram (ERD)
  5. Data Model ERD Explorer — Interactive ERD with table details
  6. WO Lifecycle Simulator — Step-through state transitions
  7. WO Ecosystem Map — External integrations and data flows
  8. Agent Orchestration Visualizer — Multi-agent workflow diagram

Planning Category (7 dashboards):

  1. CODITECT Impact Dashboard — Productivity gains from framework
  2. CODITECT Integration Playbook — Integration timeline and milestones
  3. Competitive Comparison — Feature matrix with scoring
  4. Implementation Planner — Deployment phases and timeline
  5. Product Roadmap Visualizer — Gantt chart with dependencies
  6. Project Command Center — Real-time project status (live data)
  7. Project Status Dashboard — Sprint progress, velocity, burndown

11.4 Compliance-Specific Features

BIO-QMS includes several compliance-focused features:

1. Audit Trail Logging

Every document access is logged:

// Log document view
logAuditEvent({
event: 'document_viewed',
document_id: docId,
user: currentUser,
timestamp: new Date().toISOString(),
ip_address: req.ip,
user_agent: req.headers['user-agent'],
});

2. NDA-Gated Access

Visitors must sign an NDA before accessing:

// Check NDA status
if (!user.nda_signed) {
redirectToNDASignature();
}

3. Version Control

Documents include version history:

---
title: 'Work Order State Machine'
version: 2.0
updated: '2026-02-13'
previous_versions:
- version: 1.0
date: '2026-01-15'
changes: 'Initial specification'
---

4. Print Audit Watermarks

PDF exports include audit watermarks:

@media print {
@page {
@bottom-center {
content: "Confidential | Printed by " attr(data-user) " on " attr(data-date);
font-size: 8pt;
color: #999;
}
}
}

11.5 Architecture Decisions

Why BIO-QMS chose specific patterns:

DecisionRationale
Client-side onlyNo backend = lower regulatory burden (no server PHI/PII storage)
Google Cloud RunAuto-scaling, IAP auth, audit logging built-in
JSX dashboardsInteractive visualizations for executive audience
Full-text search133 documents require instant search (MiniSearch handles client-side)
Mermaid diagramsState machines and workflows are critical to compliance validation
Dark modeNight shift workers (manufacturing, labs) need low-light mode
Presentation modeInvestor pitches and executive briefings require slide deck format

12. Troubleshooting & FAQ

Common issues and solutions.

12.1 Common Setup Issues

Issue: npm install fails with 404 Not Found for @coditect/doc-viewer

Cause: GitHub Packages authentication not configured.

Solution:

# Create ~/.npmrc with GitHub token
echo "@coditect:registry=https://npm.pkg.github.com" >> ~/.npmrc
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_PAT" >> ~/.npmrc

# Retry install
npm install

Issue: npm run dev fails with Error: Cannot find module 'vite'

Cause: Dependencies not installed.

Solution:

# Install dependencies
npm install

# Clear cache and reinstall
rm -rf node_modules package-lock.json
npm install

Issue: Port 5173 already in use

Cause: Another Vite dev server is running.

Solution:

# Find and kill the process
lsof -ti:5173 | xargs kill -9

# Or use a different port
npm run dev -- --port 3000

12.2 Build Failures and Fixes

Issue: npm run build fails with Rollup failed to resolve import

Cause: Missing dependency or incorrect import path.

Solution:

# Check import paths in error message
# Example: "Failed to resolve import 'lucide-react'"

# Install missing dependency
npm install lucide-react

# Rebuild
npm run build

Issue: Build succeeds but site is blank in production

Cause: Vite base path not configured for subdirectory deployment.

Solution:

// vite.config.js
export default defineConfig({
base: '/docs/', // If deploying to https://example.com/docs/
// ...
});

Issue: Images not loading after build

Cause: Images not copied to dist/ directory.

Solution:

// vite.config.js
import { viteStaticCopy } from 'vite-plugin-static-copy';

export default defineConfig({
plugins: [
viteStaticCopy({
targets: [
{ src: 'docs/images', dest: 'docs' },
{ src: 'public/images', dest: '.' },
],
}),
],
});

12.3 Search Not Working

Issue: Search returns no results

Cause: publish.json not generated or outdated.

Solution:

# Regenerate manifest
npm run generate-manifest

# Verify publish.json exists
ls -lh public/publish.json

# Check document count
cat public/publish.json | jq '.total_documents'

Issue: Search is slow with 100+ documents

Cause: MiniSearch index not optimized.

Solution:

// Reduce index size by excluding body_text from search
// scripts/generate-publish-manifest.js

documents.push({
id: relPath,
title: fm.title,
// ...
body_text: "", // Exclude body text, search title/summary only
});

Issue: Search doesn't find specific terms

Cause: Search query syntax or fuzzy matching threshold.

Solution:

// Adjust search options in SearchPanel.jsx

const results = miniSearch.search(query, {
prefix: true, // Enable prefix matching
fuzzy: 0.2, // Lower = stricter (0.0 - 1.0)
boost: { title: 2 }, // Boost title matches
});

12.4 Markdown Rendering Issues

Issue: Frontmatter not parsed

Cause: Incorrect YAML syntax or missing --- delimiters.

Solution:

---
title: 'My Document' # Must have quotes if contains special chars
type: guide # No quotes needed for simple strings
keywords: # Arrays must use list format
- keyword1
- keyword2
---

# Content starts here

Issue: Code blocks not highlighted

Cause: Language not specified or not supported.

Solution:

```javascript  <!-- Specify language -->
const x = 10;
```

Supported languages: highlight.js language list

Issue: Math equations not rendering

Cause: KaTeX syntax error or missing CSS.

Solution:

<!-- Inline math -->
$E = mc^2$

<!-- Block math -->
$$
\int_{a}^{b} f(x) \, dx
$$

Verify KaTeX CSS is imported:

// viewer.jsx
import "katex/dist/katex.min.css";

Issue: Mermaid diagrams not rendering

Cause: Syntax error or Mermaid not initialized.

Solution:

```mermaid
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[End]
B -->|No| D[Loop]
```

Verify Mermaid is initialized:

// viewer.jsx
import mermaid from "mermaid";

mermaid.initialize({
startOnLoad: true,
theme: 'default',
});

12.5 Deployment Troubleshooting

Issue: Vercel deployment fails with "Command failed"

Cause: Build command or output directory incorrect.

Solution:

// vercel.json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"framework": "vite"
}

Issue: Google Cloud Run deployment returns 502 Bad Gateway

Cause: Container listening on wrong port or not responding to health checks.

Solution:

# Dockerfile
EXPOSE 8080 # Cloud Run expects port 8080

CMD ["nginx", "-g", "daemon off;"]
# nginx.conf
server {
listen 8080; # Must match EXPOSE port
# ...
}

Issue: Custom domain shows "Site Not Found"

Cause: DNS records not configured or not propagated.

Solution:

# Check DNS propagation
dig docs.acme.com

# Verify CNAME record
# Expected output:
# docs.acme.com. 300 IN CNAME cname.vercel-dns.com.

# Wait for propagation (up to 48 hours, typically 5-10 minutes)

12.6 Performance Optimization Tips

Issue: Slow initial page load

Solution:

  1. Enable compression:
# nginx.conf
gzip on;
gzip_types text/css application/javascript application/json;
gzip_min_length 1000;
  1. Code splitting:
// Lazy load large dashboard components
const Dashboard = lazy(() => import('./dashboards/large-dashboard.jsx'));
  1. Image optimization:
# Compress images (macOS)
brew install imagemagick
find docs/images -name "*.png" -exec mogrify -quality 85 {} \;

Issue: Search is slow

Solution:

// Debounce search input
const [query, setQuery] = useState("");
const debouncedQuery = useDebounce(query, 300);

useEffect(() => {
if (debouncedQuery.length >= 2) {
const results = miniSearch.search(debouncedQuery);
setResults(results);
}
}, [debouncedQuery]);

13. Getting Support

Get help when you need it.

13.1 Documentation Resources

ResourceURLDescription
Official Docsdocs.coditect.ai/doc-viewerComplete reference documentation
API Referencedocs.coditect.ai/doc-viewer/apiComponent API and props
Migration Guidesdocs.coditect.ai/doc-viewer/migrationsVersion upgrade guides
Examplesgithub.com/coditect-ai/doc-viewer-examplesSample projects and templates

13.2 GitHub Issues

Report bugs and request features:

  1. Go to github.com/coditect-ai/doc-viewer/issues
  2. Search existing issues to avoid duplicates
  3. Click "New Issue"
  4. Choose template:
    • Bug Report: Something isn't working
    • Feature Request: New functionality
    • Documentation: Docs improvements
  5. Fill in required fields:
    • Title: Short, descriptive summary
    • Description: Detailed explanation
    • Steps to Reproduce (for bugs)
    • Expected vs. Actual Behavior
    • Environment: Node version, OS, browser
    • Screenshots (if applicable)
  6. Add labels: bug, enhancement, documentation, etc.
  7. Submit

Example bug report:

**Title:** Search returns no results for documents with dashes in filename

**Description:**
When searching for content from documents with dashes in the filename
(e.g., `getting-started.md`), no results are returned. Documents without
dashes work fine.

**Steps to Reproduce:**
1. Create document `docs/getting-started.md`
2. Add content with keyword "installation"
3. Run `npm run generate-manifest`
4. Search for "installation"
5. No results returned

**Expected Behavior:**
Document should appear in search results.

**Actual Behavior:**
No results returned. Console shows warning:
`Invalid document ID: getting-started`

**Environment:**
- Node: v18.19.0
- @coditect/doc-viewer: 1.2.0
- OS: macOS 14.2
- Browser: Chrome 120

**Screenshots:**
[Attach screenshot of search panel]

13.3 Slack Channel

Join the CODITECT community:

  1. Request invite: coditect.ai/slack-invite
  2. Join channels:
    • #doc-viewer — General discussion
    • #doc-viewer-support — Technical support
    • #doc-viewer-announcements — Release notes
  3. Introduce yourself in #introductions

Slack etiquette:

  • Search history before asking (FAQ may be answered)
  • Use threads to keep channels organized
  • Share code snippets with backticks: `code`
  • Use code blocks for longer snippets: ```code```
  • Tag @support for urgent issues

13.4 Email Support

For enterprise customers:

Include in your email:

  • Subject: [Doc Viewer] Short description
  • Account ID or organization name
  • Detailed description of issue
  • Steps to reproduce
  • Environment details
  • Error logs (if applicable)

13.5 Feature Requests

Suggest new features:

  1. Go to github.com/coditect-ai/doc-viewer/discussions
  2. Click "New Discussion"
  3. Category: "Feature Requests"
  4. Title: Feature name
  5. Description:
    • Problem: What problem does this solve?
    • Solution: How should it work?
    • Alternatives: Other approaches considered?
    • Examples: Similar features in other tools?
  6. Community votes on requests (👍 reactions)
  7. Top requests prioritized in roadmap

Popular feature requests:

  • Multi-language support (i18n)
  • PDF export with custom branding
  • Versioned documentation (v1.0, v2.0 tabs)
  • Collaborative commenting
  • Analytics integration (Google Analytics, Plausible)

Conclusion

You now have a comprehensive understanding of the CODITECT Doc Viewer platform. From initial setup to production deployment, this guide has covered:

  • 5-minute quick start with scaffolding CLI
  • Content authoring with markdown and JSX dashboards
  • Configuration for branding, navigation, and features
  • Deployment to Vercel, Google Cloud Run, Netlify, or self-hosted
  • Access control with basic auth, IAP, or custom NDA gates
  • Maintenance with version updates and monitoring
  • Reference implementation (BIO-QMS) with 133 documents and 26 dashboards
  • Troubleshooting for common issues

Next Steps:

  1. Create your first documentation site: npx @coditect/create-doc-site my-docs
  2. Add 10 documents from your existing documentation
  3. Customize theme to match your brand
  4. Deploy to staging (Vercel free tier)
  5. Share with team for feedback
  6. Deploy to production with custom domain

Resources:

Welcome to the CODITECT Doc Viewer community!


Document Metadata

  • Version: 1.0.0
  • Status: Active
  • Word Count: ~10,500 words
  • Sections: 13 major sections
  • Code Examples: 75+
  • Tables: 40+
  • Diagrams: 3 ASCII art diagrams

Related Documents:

Feedback:

If you have suggestions for improving this guide, please:

  1. Open an issue: github.com/coditect-ai/doc-viewer/issues
  2. Email: docs-feedback@coditect.ai
  3. Slack: #doc-viewer channel

Copyright 2026 AZ1.AI Inc. All rights reserved.