Documentation Pipeline Architecture
System Overview
typedoc.json
vitest.config.ts
.github/workflows/
.dockerignore
.gitignore
Dockerfile
README.md"] end subgraph generated["β Not Committed (gitignore)"] dist["dist/ (Vite build)"] coverage["coverage/ (Test coverage)"] publicdocs["public-docs/ (Generated docs)"] nodemodules["node_modules/"] end subgraph generated2["Generated by npm run docs:all"] publicdocs2["public-docs/index.html
public-docs/architecture/*.html
public-docs/typedoc/
public-docs/coverage/
public-docs/templates/*.css"] end end main --> deploy["deploy-frontend.yml"] main --> docspipe["docs-pipeline.yml"] deploy --> vercel["VERCEL PRODUCTION
https://stockease-...vercel.app/"] docspipe --> ghpages["GITHUB PAGES gh-pages
https://keglev.github.io/stockease-frontend/"] vercel --> vContent["β dist/ production app
β .md files
β Test files
β Documentation source"] ghpages --> ghContent["β public-docs/index.html
β Architecture HTML
β TypeDoc API
β Coverage reports
β Source files
β node_modules"] style main fill:#e1f5ff style vercel fill:#c8e6c9 style ghpages fill:#fff9c4 style vContent fill:#c8e6c9 style ghContent fill:#fff9c4
File Generation Pipeline
Create public-docs/
βββ architecture/
βββ typedoc/
βββ coverage/"] arch --> archconv["Pandoc
Converts markdown β HTML
Uses template
Applies CSS
Adds TOC"] archconv --> archout["Output:
public-docs/architecture/"] typedoc --> typedocconv["TypeDoc
Generates from source code
βββ index.html
βββ Search
βββ API docs
βββ Modules"] typedocconv --> typedocout["Output:
public-docs/typedoc/"] coverage --> covconv["Vitest
Generates coverage report
βββ index.html
βββ Coverage data"] covconv --> covout["Output:
public-docs/coverage/"] landing --> landingconv["Node.js
Converts docs/index.md β index.html
Uses template + CSS
Creates landing page"] landingconv --> landingout["Output:
public-docs/index.html"] cleanout --> final["public-docs/ Final Output
βββ index.html
βββ architecture/ (all sections)
βββ typedoc/ (API docs)
βββ coverage/ (test reports)
βββ templates/ (CSS)"] archout --> final typedocout --> final covout --> final landingout --> final final --> ghpages["Publish to gh-pages
via peaceiris/actions-gh-pages@v3"] ghpages --> deployed["GitHub Pages
https://keglev.github.io/stockease-frontend/"] style docall fill:#bbdefb style final fill:#c8e6c9 style deployed fill:#fff9c4
Workflow Decision Tree
Always runs
Irrelevant of paths"] push --> checkdocs["docs-pipeline.yml
Conditional path-based"] checkdeploy --> deploy1["1. Test npm test"] deploy1 --> deploy2["2. Build npm run build"] deploy2 --> deploy3["3. Docker verify"] deploy3 --> deploy4["4. Deploy to Vercel"] deploy4 --> deployout["Output: dist/ β Vercel
Duration: 3-5 minutes"] checkdocs --> fileschanged{{"Changed files
include:
docs/**
src/**
*.json config
vitest.config.ts"}} fileschanged -->|YES| docsbuild["1. Build arch docs
2. Generate TypeDoc
3. Generate coverage
4. Build landing page
5. Publish to gh-pages"] fileschanged -->|NO| docsskip["SKIP"] docsbuild --> docsout["Output: public-docs/ β gh-pages
Duration: 2-4 minutes"] style push fill:#bbdefb style deployout fill:#c8e6c9 style docsout fill:#fff9c4 style docsskip fill:#ffccbc
Security & Isolation
main branch
complete source"] p2[".dockerignore
excludes:
docs/
*.md
**/__tests__
.github/
Coverage files"] p3["Docker copies:
src/
public/
config files only"] p4["Builds:
dist/
production bundle"] p5["Result:
Lean image
no docs"] p6["Deployed to:
Vercel"] end subgraph doc["Documentation Pipeline docs-pipeline.yml"] d1["Input:
main branch
only when relevant
files change"] d2["Generates:
public-docs/
temporary"] d3["Runs:
npm run docs:all
Pandoc markdownβHTML
TypeDoc sourceβAPI docs
Vitest coverageβreports
Landing index.mdβHTML"] d4["Publishes:
public-docs/βgh-pages
only"] d5["Result:
Clean documentation
site"] d6["Served at:
GitHub Pages"] end subgraph results["Separation Results"] r1["β No docs in production"] r2["β No code in docs"] r3["β Different deployment"] r4["β Different builds"] r5["β Different access"] end p1 --> p2 --> p3 --> p4 --> p5 --> p6 d1 --> d2 --> d3 --> d4 --> d5 --> d6 p6 --> results d6 --> results style prod fill:#c8e6c9 style doc fill:#fff9c4 style results fill:#e1bee7
Caching & Performance
No cache
checks for updates"] b2["Architecture pages:
Browser cache
mostly static"] b3["TypeDoc pages:
Browser cache
generated once
per src change"] b4["Coverage pages:
Browser cache
generated per
test run"] b5["Static assets CSS JS:
Pandoc-generated CSS
Browser cache
Mermaid.js CDN:
CDN cache"] end subgraph github["GitHub Pages"] g1["Serves static
HTML directly"] g2["Uses HTTP/2"] g3["GZIP compression
enabled"] g4["CDN caching
Cloudflare"] g5["Edge locations
worldwide"] end subgraph vercel["Production Vercel"] v1["React app:
Dynamic
Next.js-like behavior"] v2["Static files:
Vercel edge cache"] v3["API proxying:
Dynamic
to backend"] v4["Auto-scaling:
Serverless functions"] end style browser fill:#c8e6c9 style github fill:#fff9c4 style vercel fill:#f8bbd0
Change Detection Logic
docs-pipeline.yml triggers when:
| Trigger | Action | Result |
|---|---|---|
docs/architecture/*.md changed |
β Rebuild architecture HTML | Docs updated |
src/*.ts or src/*.tsx changed |
β Regenerate TypeDoc | API docs updated |
vitest.config.ts changed |
β Rebuild with new config | Coverage updated |
typedoc.json changed |
β Rebuild with new config | API docs updated |
package.json or package-lock.json
changed |
β Rebuild | Dependencies may affect docs |
Only tests changed *.test.ts |
βοΈ SKIPPED | No docs rebuild needed |
Only linting changed .eslintrc |
βοΈ SKIPPED | No docs rebuild needed |
Only production code src/main.tsx |
βοΈ SKIPPED | No docs rebuild needed |
| Only workflows changed | βοΈ SKIPPED | No docs rebuild needed |
This prevents unnecessary documentation rebuilds when they're not needed.
Link Resolution Logic
Generated HTML uses JavaScript to resolve paths dynamically:
function getRootFrom(pathname) {
// Example paths:
// /stockease-frontend/index.html
// β root = ./
// /stockease-frontend/architecture/overview.html
// β root = ../
// /stockease-frontend/architecture/api/overview.html
// β root = ../../
// Works under any subdomain:
// https://keglev.github.io/stockease-frontend/ β
// https://custom.com/docs/stockease/ β
// https://docs.stockease.example.com/ β
}
CSS Path: ${root} + templates/frontend-docs.css
Home Link: ${root} + index.html
API Link: ${root} + typedoc/index.html
Coverage Link: ${root} + coverage/index.htmlSummary
This architecture provides:
β
Complete Separation: Docs and production
never mix
β
Automated Generation: All docs built on
every relevant change
β
Targeted Triggers: Only runs when
needed
β
Clean Distribution: Each system gets exactly
what it needs
β
Security: No documentation in production
code
β
Performance: Lean images, efficient
pipelines
β
Scalability: GitHub Pages handles docs,
Vercel handles app
β
Maintenance: Single source of truth (main
branch)
Generated: November 12, 2025