Skip to Content
Vektos

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, zeroheightVektos
Question"Does the agent have the right information?""Did the agent write compliant code?"
Works onDocs, MCP (input context)Generated code, CI, PRs (output)
MeasuresWhat agents ask for and what is missingViolations, scores, cost per run, regressions over time
VerificationNone on codeType check, AST, axe, visual diff
NeutralitySells its own MCPIndependent, 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 materialRole
Bank statements, contracts, transfersTask 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 reportsRAG 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

LayerChoiceWhy
MonorepoBun workspaces, ChangesetsFast, packages will be published
LanguageTypeScript 7 (native tsc) for type checkEarly adopter; "wrong code does not compile"
ASToxc-parserTS 7 has no JS compiler API; oxc does not depend on TS
Lint/formatoxlint + tsgolint (type-aware, built on TS 7), oxfmt, @pandacss/eslint-plugin via oxlint JS pluginOne AST toolchain (oxc); Panda-aware rules (prefer-token, no-invalid-token-paths) that Biome cannot run
Design systemArk UI + Panda CSS, strictTokens + strictPropertyValuesZero-runtime, strict tokens, my signature stack
DS docsStorybook 10 (react-vite), addon-docs, addon-a11y, addon-mcpDocumentation agents and people read; its MCP is one of the "standard MCP" context levels in the matrix
AppNext.js (App Router) + React 19RSC, streaming
AIAI SDK 7 (@ai-sdk/mcp client), MCP TypeScript SDK v2 (@modelcontextprotocol/server), zod 4Tool calling, useChat, generative UI
DataPostgres + pgvector (Docker), Drizzle, postgres driverNo RAG framework: chunking, retrieval, reranking by hand. Next runs on Node, so no Bun.SQL
Graderstsc, oxc-parser, oxlint + Panda rules (JSON output), Playwright + axeReal graders, not only LLM
Testsbun 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 set reactDocgen: "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 publish has no trusted publishing. Flow: changeset version → bun pm pack (rewrites workspace:*) → npm publish *.tgz with OIDC. Keep published packages free of internal deps where possible.
  • oxlint JS plugins are alpha. The Panda plugin binds one panda.config per run and resolves include from cwd, so the root oxlint-panda.mjs sets cwd to packages/ds. Its eslint peer is unused.
  • styled-system/* imports rely on tsconfig paths. Works for tsc, Next and Bun; Storybook needs Vite tsconfigPaths. 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. Pin typescript@~7.0.2; 7.1 is not needed.
  • oxc-parser for AST analysis in graders.
  • .d.ts emission for published packages via tsc -b / --emitDeclarationOnly. No bundler-generated declarations (they need the API).
  • Next.js ≥ 16.3 runs the project-local tsc CLI in next build, so TS 7 works as is. The CLI checks the whole tsconfig project, tests included: exclude them or run tsc --noEmit in CI with typescript.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 the next tsconfig 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.md

All 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 contextStandard 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:

  1. AI SDK agent + MCP first: full control, cheap, model/provider switch via flag, reproducible.
  2. 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.

  1. DS: 8 components: Button, Input, Select, FormField, Card, Table, Badge, Dialog.
  2. 5 fintech tasks with synthetic JSON fixtures.
  3. 3 graders: tsc type check, AST token analysis with oxc, axe.
  4. Cost per run via @vektos/pricing: tokens and dollars stored with every result.
  5. Minimal dashboard: run list, run detail with violations, screenshots and cost; compliance per dollar across runs.
  6. RAG + chat right after the first run: DS docs + 2 regulatory PDFs.
  7. No CLI upload, no multi-tenant, no Tailwind until the demo.

7. Phases

WeekDeliverable
0 (½ day) ✅Spike: Bun + TS 7 + Panda + Ark + Next + oxc + oxlint + Storybook. Confirm TS 7 alone is enough
1DS 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"
2Benchmark: 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)
3RAG: 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)
4Chat: tools over the runs (typed, not free SQL) + RAG with checked citations + generative UI ✅ (guide 17)
5Minimal dashboard ✅ (first version, guide 14), README, demo video
LaterProvider 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
LaterToken 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:

#BlockWhat
1APP-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
2DS-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)
3DS-7 · Fintech inputs ✅ (ch. 47)NumberInput, DatePicker, Combobox, SegmentGroup, Steps, FileUpload. Combobox and SegmentGroup replace the rows of filter pills
4APP-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"
5APP-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)
6APP-3 · New pages ✅ (ch. 50)/tasks, /tasks/[id] (the brief, the reference solution, best and worst runs), /models/[id], /rules, /methodology
7APP-4 · The chat for visitors ✅ (ch. 51)Saved example conversations shown read-only ($0), suggested questions, read-only share links
8APP-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
9Rerun 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)
10GenUI-3 · Experiment ✅ (ch. 54)A "spec" mode in the benchmark: the same tasks written as a JSON spec instead of code
11maxOutputTokens, provider seam ✅ (ch. 55)Decide the runner's output cap; models from more than the gateway
12Public repository, free deploy, demo (prepared: ch. 56)
13Regressions ✅ (ch. 58)Versions (design system, graders, output cap), /regressions, bench:regress for CI
14Graders v2 ✅ (ch. 59)axe's best practices, and a free mini-rerun under them: the first comparison on /regressions
15check:app in CI ✅ (ch. 60)Every page of the built app in Chrome, on demo runs (db:seed-demo)
16Task difficulty ✅ (ch. 61)Which tasks are hardest, on the series that ran every task; docs/results.md with the free rerun
17Forms in the GenUI catalog ✅ (ch. 62)Six form components on request; the spec mode covers six tasks; a free rerun
18Context hash ✅ (ch. 63)What the agent received is part of a run's version
19Page profile and stored feedback ✅ (ch. 64)The spec validator checks a whole page; steps keep what a checker answered
20Data binding ✅ (ch. 65)Views that point at their data, as the genui-spec-data level
21A second product ✅ (ch. 66)Domains; five warehouse tasks; a domain filter across the dashboard; a short free rerun
22Domain components ✅ (ch. 67)The warehouse's own components in generated views, against the shared ones
23Behaviour checks ✅ (ch. 68)Graders v3: done includes what a page does after the user acts
24Chat actions ✅ (ch. 69)Forms in chat views that open pages of the app, named by the app
25Labelled options ✅ (ch. 70)A generated select shows labels and sends values
26Postgres 18 ✅ (ch. 71)The laptop and CI on the same major version as Neon
27The 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.

CheckResult
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

  1. Honest comparison between stacks, same effort on both sides.
  2. Multi-tenant isolation in RAG. Must be tested explicitly, evals included.
  3. GDPR. Plan for an EU-region model or the user's own API keys from the start.
  4. Competition. Design-system platforms could add verification. Advantage: specialization and neutrality.
  5. 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.

On this page