Project plan
Why Vektos exists, the thesis, the stack and the week-by-week roadmap.
1. Why
AI coding agents write more and more of the code built with design systems. Vektos measures whether they follow one, how much help they need to, and what that help costs. It has to show hand-written RAG, generative UI, an agent with MCP tools, and evals, on a real question.
2. Thesis
Tools like Supernova give agents the rules. Vektos checks, in CI, whether the agents followed them, and at what price.
A vendor-neutral benchmark with results over time, plus a chat that explains the results by citing design-system rules and regulations.
Compliance is the first metric. Cost per run is the second: every run records tokens in/out/cache and dollar cost per task, model and context level. This answers a question no design-system platform answers: which context gives compliant code at the lowest cost? It is a dimension of the benchmark, not a FinOps product.
Positioning vs. the market
| Supernova, Storybook MCP, Figma MCP, Knapsack, zeroheight | Vektos | |
|---|---|---|
| Question | "Does the agent have the right information?" | "Did the agent write compliant code?" |
| Works on | Docs, MCP (input context) | Generated code, CI, PRs (output) |
| Measures | What agents ask for and what is missing | Violations, scores, cost per run, regressions over time |
| Verification | None on code | Type check, AST, axe, visual diff |
| Neutrality | Sells its own MCP | Independent, compares any context |
Vendor MCPs become one of the context levels in the benchmark matrix, not competitors.
3. Why fintech
Fintech is the domain of the tasks, not a separate project.
| Fintech material | Role |
|---|---|
| Bank statements, contracts, transfers | Task fixtures: synthetic JSON the generated UI must render (transactions table, contract detail, KYC form) |
| Real regulations (EAA 2025, WCAG 2.2, PSD2 SCA, GDPR consent) | RAG corpus: public PDFs, hand-written chunking, citations |
| Design-system docs, rules, traces, audit reports | RAG corpus per tenant |
The bridge: every design-system rule has a regulatory rationale. Chat: "why is this a violation?" → retrieve the rule → cite the EAA article or WCAG criterion → render the correct component.
4. Stack
| Layer | Choice | Why |
|---|---|---|
| Monorepo | Bun workspaces, Changesets | Fast, packages will be published |
| Language | TypeScript 7 (native tsc) for type check | Early adopter; "wrong code does not compile" |
| AST | oxc-parser | TS 7 has no JS compiler API; oxc does not depend on TS |
| Lint/format | oxlint + tsgolint (type-aware, built on TS 7), oxfmt, @pandacss/eslint-plugin via oxlint JS plugin | One AST toolchain (oxc); Panda-aware rules (prefer-token, no-invalid-token-paths) that Biome cannot run |
| Design system | Ark UI + Panda CSS, strictTokens + strictPropertyValues | Zero-runtime, strict tokens, my signature stack |
| DS docs | Storybook 10 (react-vite), addon-docs, addon-a11y, addon-mcp | Documentation agents and people read; its MCP is one of the "standard MCP" context levels in the matrix |
| App | Next.js (App Router) + React 19 | RSC, streaming |
| AI | AI SDK 7 (@ai-sdk/mcp client), MCP TypeScript SDK v2 (@modelcontextprotocol/server), zod 4 | Tool calling, useChat, generative UI |
| Data | Postgres + pgvector (Docker), Drizzle, postgres driver | No RAG framework: chunking, retrieval, reranking by hand. Next runs on Node, so no Bun.SQL |
| Graders | tsc, oxc-parser, oxlint + Panda rules (JSON output), Playwright + axe | Real graders, not only LLM |
| Tests | bun test; retrieval evals with a custom dataset |
Stack compatibility notes (checked 2026-11-07)
- All peer ranges resolve: React 19.3, Next 16.4, Ark 5.40, Panda 2.5, Vite 8.3, Storybook 10.6, AI SDK 7, zod 4.6, Drizzle 0.45 (1.0 is RC; revisit in week 2), Playwright 1.65 (Bun supported since 1.65 / Bun 1.4).
- Storybook defaults to
react-docgen(Babel, no TS API). Never setreactDocgen: "react-docgen-typescript". Props must be declared in the component file for docgen and the MCP to see them. - Publishing: Changesets does not rewrite
workspace:*,bun publishhas no trusted publishing. Flow:changeset version→bun pm pack(rewritesworkspace:*) →npm publish *.tgzwith OIDC. Keep published packages free of internal deps where possible. - oxlint JS plugins are alpha. The Panda plugin binds one
panda.configper run and resolvesincludefrom cwd, so the rootoxlint-panda.mjssetscwdtopackages/ds. Itseslintpeer is unused. styled-system/*imports rely on tsconfigpaths. Works fortsc, Next and Bun; Storybook needs VitetsconfigPaths. Consider subpath imports (#styled-system/*) before publishing@vektos/ds.
TypeScript 7 caveat
TypeScript 7.0 (stable since 2026-07-08, typescript@7, binary tsc) ships the native compiler without the JS compiler API; the API returns in 7.1 with a different shape. Anything that does import "typescript" breaks: typescript-eslint, ts-jest, ts-node, TypeDoc. None of them is in this stack. Therefore:
- TS 7 for type checking (
tsc --noEmit) in graders and CI. Pintypescript@~7.0.2; 7.1 is not needed. - oxc-parser for AST analysis in graders.
.d.tsemission for published packages viatsc -b/--emitDeclarationOnly. No bundler-generated declarations (they need the API).- Next.js ≥ 16.3 runs the project-local
tscCLI innext build, so TS 7 works as is. The CLI checks the wholetsconfigproject, tests included: exclude them or runtsc --noEmitin CI withtypescript.ignoreBuildErrors. - Panda CSS ≥ 2.0 has a native compiler and no longer depends on
ts-morph. - Editor: TypeScript 7 extension for VS Code. No
tsserver, so thenexttsconfig plugin may not load.
Fallback if a tool needs the API: side-by-side aliases ("typescript": "npm:@typescript/typescript6", "@typescript/native": "npm:typescript@^7"), never a downgrade. The plan does not change.
5. Architecture
vektos/
apps/web/ Next.js: dashboard + chat
packages/
ds/ Ark + Panda, 8 components, markdown doc per component
ds-mcp/ MCP server: components, props, examples, tokens, rules
bench/ result schema, tasks, AI SDK runner, graders
pricing/ model price tables, cost per run (published as @vektos/pricing)
rag/ ingest, chunking, embedding, hybrid retrieval, reranking
db/ Drizzle schema, migrations, pgvector
tasks/ 5 fintech tasks + JSON fixtures
corpus/ WCAG 2.2 and the EAA as Markdown, converted from the official HTML (guide 16)
docs/PLAN.mdAll packages are published under the @vektos npm scope.
rag and bench are separate packages: the two hardest parts, testable alone, publishable.
pricing is small on purpose: a price table per model (input, output, cache read/write, per million tokens), a cost(usage, model) function and a date-versioned table so old runs keep their original price. The runner records usage from the AI SDK response and stores both tokens and cost on each run. No dashboard, no forecasting, no billing: those belong to the paused FinOps product.
Chat: two paths
- Numbers (runs, scores, cost, trends): SQL tools such as
query_runs,compare_runs,get_violations,cost_by_context. No number ever comes from the model's memory. - Text (docs, rules, traces, PR comments): RAG, isolated per tenant.
- Read-only tools always available. Tools that modify rules only after explicit approval (human-in-the-loop).
- Mandatory citations: every claim points to the query or document it comes from.
- Tool results render as components (charts, tables, diffs, DS components), not as text.
Benchmark matrix (phase 2)
2 stacks × 3 context levels, same effort on both sides:
| No context | Standard MCP / docs (vendor MCPs) | Optimized context | |
|---|---|---|---|
| Ark + Panda | |||
| shadcn + Tailwind |
Separates two questions: "does the stack matter?" and "does the context matter?". The second one brings clients. Each cell reports score and cost, so the answer is "this context gives +N points for +$X per task".
Runners
Interface Runner with adapters:
- AI SDK agent + MCP first: full control, cheap, model/provider switch via flag, reproducible.
- Claude Code / Codex headless later: credible, it is what teams actually use.
Both consume the same DS MCP server, so the "standard MCP" context is identical.
6. Demo scope (vertical slice)
Only Ark + Panda, only the AI SDK runner.
- DS: 8 components: Button, Input, Select, FormField, Card, Table, Badge, Dialog.
- 5 fintech tasks with synthetic JSON fixtures.
- 3 graders:
tsctype check, AST token analysis with oxc, axe. - Cost per run via
@vektos/pricing: tokens and dollars stored with every result. - Minimal dashboard: run list, run detail with violations, screenshots and cost; compliance per dollar across runs.
- RAG + chat right after the first run: DS docs + 2 regulatory PDFs.
- No CLI upload, no multi-tenant, no Tailwind until the demo.
7. Phases
| Week | Deliverable |
|---|---|
| 0 (½ day) ✅ | Spike: Bun + TS 7 + Panda + Ark + Next + oxc + oxlint + Storybook. Confirm TS 7 alone is enough |
| 1 | DS with 8 components (semantic tokens, light/dark), MCP server. Grader gaps: Panda escape hatch "[#fff]", hand-written .css, template literals, intentional raw values. Semantic adherence: palette colors in components (lint no-primitive-token) and "right token, wrong job" (fg.muted as a background), graded from the token prefix. Fourth DS rule: "style components, not the host page" |
| 2 | Benchmark: 5 tasks, AI SDK runner using MCP, 3 graders, pricing package, results with cost in DB. Agents must not edit panda.config.ts (or a diff on it is a violation) |
| 3 | RAG: ingest, chunking, hybrid retrieval, reranking, retrieval evals. Chunking, full-text, vector, hybrid, reranking and evals ✅ (guide 15, anecdote 10); WCAG 2.2 and the EAA as a second corpus, with a lookup from an axe rule to its criterion ✅ (guide 16) |
| 4 | Chat: tools over the runs (typed, not free SQL) + RAG with checked citations + generative UI ✅ (guide 17) |
| 5 | Minimal dashboard ✅ (first version, guide 14), README, demo video |
| Later | Provider seam: a packages/models package (language, embedding, reranking, reportedCost, ready) so the Vercel AI Gateway is one provider among others and a direct provider or another gateway is configuration, not a migration. Today the coupling is implicit: string model ids go to the AI SDK's default provider (7 call sites), the gateway's cost is parsed twice (gatewayCost in bench, gatewayCostOf in chat) and AI_GATEWAY_API_KEY is checked in 4 places. First version: the gateway provider plus a fake one in tests, no new keys. The gateway_usd columns keep their name in SQL and are mapped to reportedUsd in Drizzle, so no migration |
| Later | Token naming as an experiment: the same models and tasks on today's names (bg, fg, border, accent) and on Practical UI's (text.strong, fill.*, stroke.*). Does the naming change how well an agent follows the design system? The palette already follows Practical UI (guide 01) |
Next steps (decided 2026-11-10)
The design system had 33 governed components (46 after DS-6 and DS-7), the chat composes views (ch. 44). An audit of the app (ch. 45) found it dense and silent about its own result, so the app comes before any paid run. The order, all at $0:
| # | Block | What |
|---|---|---|
| 1 | APP-0 · Identity ✅ (ch. 45) | Three identities tried as Panda themes, mint kept; light table heads, plain links in tables, the page font applied, an icon theme toggle |
| 2 | DS-6 · Overlays and disclosure ✅ (ch. 46) | Menu, Popover, Drawer, Accordion/Collapsible, Portal, Clipboard. Menu and Accordion get governed parts built with createSlotRecipeContext (decisions). The app needs Drawer (mobile navigation), Menu/Popover (compact filters), Accordion (violations) |
| 3 | DS-7 · Fintech inputs ✅ (ch. 47) | NumberInput, DatePicker, Combobox, SegmentGroup, Steps, FileUpload. Combobox and SegmentGroup replace the rows of filter pills |
| 4 | APP-1 · An overview that tells ✅ (ch. 48) | The key result at the top, a heatmap instead of the matrix of badges, one table instead of two, models with few runs hidden by default, a short "What is Vektos" |
| 5 | APP-2 · Runs and a run ✅ (ch. 49) | Compact filters, sortable columns, a sticky head, shorter dates; a run's screenshot and code side by side, highlighted code, two runs compared (from bench:report) |
| 6 | APP-3 · New pages ✅ (ch. 50) | /tasks, /tasks/[id] (the brief, the reference solution, best and worst runs), /models/[id], /rules, /methodology |
| 7 | APP-4 · The chat for visitors ✅ (ch. 51) | Saved example conversations shown read-only ($0), suggested questions, read-only share links |
| 8 | APP-5 · Quality ✅ (ch. 52) | 390 px, heading order, loading skeletons, Open Graph metadata and images, axe and Lighthouse on the app's pages in check:page |
| 9 | Rerun on free models ✅ (ch. 53) | Every task × 5 contexts, with repeats, on the final design-system version (it changes once more, with DS-6 and DS-7) |
| 10 | GenUI-3 · Experiment ✅ (ch. 54) | A "spec" mode in the benchmark: the same tasks written as a JSON spec instead of code |
| 11 | maxOutputTokens, provider seam ✅ (ch. 55) | Decide the runner's output cap; models from more than the gateway |
| 12 | Public repository, free deploy, demo (prepared: ch. 56) | |
| 13 | Regressions ✅ (ch. 58) | Versions (design system, graders, output cap), /regressions, bench:regress for CI |
| 14 | Graders v2 ✅ (ch. 59) | axe's best practices, and a free mini-rerun under them: the first comparison on /regressions |
| 15 | check:app in CI ✅ (ch. 60) | Every page of the built app in Chrome, on demo runs (db:seed-demo) |
| 16 | Task difficulty ✅ (ch. 61) | Which tasks are hardest, on the series that ran every task; docs/results.md with the free rerun |
| 17 | Forms in the GenUI catalog ✅ (ch. 62) | Six form components on request; the spec mode covers six tasks; a free rerun |
| 18 | Context hash ✅ (ch. 63) | What the agent received is part of a run's version |
| 19 | Page profile and stored feedback ✅ (ch. 64) | The spec validator checks a whole page; steps keep what a checker answered |
| 20 | Data binding ✅ (ch. 65) | Views that point at their data, as the genui-spec-data level |
| 21 | A second product ✅ (ch. 66) | Domains; five warehouse tasks; a domain filter across the dashboard; a short free rerun |
| 22 | Domain components ✅ (ch. 67) | The warehouse's own components in generated views, against the shared ones |
| 23 | Behaviour checks ✅ (ch. 68) | Graders v3: done includes what a page does after the user acts |
| 24 | Chat actions ✅ (ch. 69) | Forms in chat views that open pages of the app, named by the app |
| 25 | Labelled options ✅ (ch. 70) | A generated select shows labels and sends values |
| 26 | Postgres 18 ✅ (ch. 71) | The laptop and CI on the same major version as Neon |
| 27 | The database on Neon ✅ (ch. 72) | The public export on Neon, checked table by table; backups of a remote database |
Paid models are off the plan for now. Components take inspiration from @pyck/react for names
and API shapes; the implementations are Vektos's own.
Week 0 outcome (2026-11-08): GO
TS 7 alone is enough. Nothing in the stack needed the TypeScript 7 JS API or a TS 5 fallback.
| Check | Result |
|---|---|
tsc -b on ds, bench, web; .d.ts emitted | ✅ |
strictTokens rejects "#ff0000" / "12px" | ✅ TS2769 |
| oxlint + tsgolint (type-aware) + Panda rules | ✅ prefer-token suggests the matching token |
next build (Turbopack) | ✅ exit 0 clean, exit 1 on a token error |
Storybook 10 (react-vite, Vite 8) build and dev | ✅ ~3s |
react-docgen manifest with props, JSDoc, defaults | ✅ |
addon-mcp docs-show button | ✅ props + stories + import line |
| axe WCAG 2 A/AA on 4 stories | ✅ 0 violations |
oxc grader bun test | ✅ |
Unplanned additions that stayed: Biome → oxc swap, Storybook, root check script, shared editor settings.
Phase 2, after the demo: Claude Code runner, Tailwind adapter, CLI with upload (Codecov-style GitHub Action), cost regression in CI (fail the PR if cost per task rises above a threshold), production backups (managed Postgres + nightly dump to a bucket + monthly restore drill: see guide 12), LLM-as-judge, visual diff (needs a pinned Chromium instead of the system Chrome the page checks use: see guide 11), multi-tenant, "why did it get worse?", rule assistant with human-in-the-loop, on-demand reports.
8. Risks
- Honest comparison between stacks, same effort on both sides.
- Multi-tenant isolation in RAG. Must be tested explicitly, evals included.
- GDPR. Plan for an EU-region model or the user's own API keys from the start.
- Competition. Design-system platforms could add verification. Advantage: specialization and neutrality.
- Cost scope creep. Cost is a metric of the benchmark, not a product: no budgets, forecasts or billing connectors.
9. Name
The project was called "Aurora" for one commit. It was renamed to Vektos in November 2026: Aurora collides with Amazon Aurora, a Postgres-compatible database, which is confusing next to a Postgres stack.