Single-repo app: React (Vite) UI + Express API. No microservices; production ships as one Node process serving API + static dist/.
flowchart LR
UI[src/ React] -->|POST /api/scan| API[server/ Express]
UI -->|POST /api/watch| API
API --> NVD[NVD]
API --> OSV[OSV]
API --> GH[GitHub Advisories]
API --> KEV[CISA KEV]
API --> RSS[RSS feeds]
| Path | Role |
|---|---|
src/ |
UI: tabs, hooks, i18n (6 locales), charts |
server/ |
API routes, feed services, OpenAPI |
shared/ |
API contract types + constants (client + server) |
extended-docs/ |
Canonical product documentation (MkDocs) |
docs/ |
ADRs, deploy guides, self-hosted ops, legacy short MkDocs |
tests/ |
Node tests: server/, client/, integration/, e2e/ (~257 specs) |
scripts/ |
Docs screenshots, OpenAPI sync, brand icon sync/check |
Brand icons: canonical tree is public/icons/brands/. Docs copies are synced via npm run icons:sync and verified in CI with npm run icons:check.
| examples/ | Sample stack JSON |
| .github/workflows/ | CI (path-filtered), security, deploy, release, ops |
| UI | src/ — SetupWizard.tsx, scanCache.ts, hooks (useVulnScan, useWatch) |
| Middleware | server/middleware/rateLimit.ts — separate scan/watch buckets; validate exempt |
First-run setup wizard gates the dashboard until cve-radar:setup-complete. Legacy cve-intel:* keys migrate once on boot (src/lib/storageMigration.ts). Scan cache (src/lib/scanCache.ts) persists last results stack-keyed in localStorage.
- Legacy:
/api/health,/api/scan,/api/watch, … - Versioned mirror:
/api/v1/*(same handlers) - Spec:
server/openapi/spec.json(copied to extended-docs for API Explorer)
| Mode | Command | Server entry |
|---|---|---|
| Development | make dev |
tsx watch server/index.ts + Vite :5173 |
| Local prod | make start |
node dist-server/index.js + serves dist/ |
| Docker | docker compose up |
Same as local prod inside image |
- Extended docs ch. 08:
extended-docs/docs/content/en/08-architecture.md - ADRs:
docs/adr/ - OpenAPI workflow:
docs/OPENAPI.md