Files
agentic-dev/docs/product/reference/project/veect-codebase
Danijel Martinek 1483a45406 docs(product): commit design references under docs/product/reference/
Copy the founder's design handoff bundle (.proto/design/) into
docs/product/reference/ byte-for-byte so dispatch agents running in git
worktrees can read the HTML prototypes, veect-codebase/ prototype,
upload PNGs, and remaining bundle files (ADR-029: reference only, never
vendored into packages/). Ignore-list entries so whole-codebase auditors
and formatters skip reference material: .prettierignore (byte
preservation through lint-staged), .fallowrc.json ignorePatterns, root
ESLint ignores, and the coverage:diff allowlist in
scripts/coverage/diff.mjs (+ unit test). .DS_Store files skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 14:09:30 +02:00
..

Veect — design-system-native canvas

Full product & design specification: SPEC.md

A React 18 + TypeScript (strict) + Tailwind + shadcn-style codebase for the Veect MVP: a canvas where a designer composes screens from their own tokens and components and gets real React out — constrained AI, a Polish (Impeccable) craft pass, and honest code.

Run

npm i
npm run dev        # vite
npm run typecheck  # tsc --noEmit
npm run lint       # eslint

Architecture — atomic design

src/
  types/        Domain types (VeectNode, DesignSystem, Proposal, PolishIssue…)
  config/       Library manifest + node glyphs + demo fiction (customer identity, imports, team)
  engine/       Pure logic, no React: color math, tree ops, views (responsive variants),
                codegen, parser (code→tree), tw utilities, polish rules, isolation specs,
                upload intake, constrained-AI prompt + sanitizer
  store/        zustand store (navigation, document + labelled restorable history, panels + tabs, chat)
  hooks/        usePanelResize, useAiCompose (AI orchestration)
  lib/          cn(), clamp(), truncate()
  components/
    ui/         shadcn-style primitives (Button, Input, Badge, Select, Panel) — cva + tailwind-merge
    atoms/      Logo, MonoLabel, Swatch
    molecules/  SegmentedControl, Stepper, ChatBubble, ChatComposer, LayerTree, LibraryList,
                TokenEditor, PolishIssueCard, CollapseButton, ZoomControls
    organisms/  ActivityBar, NodeRenderer, BoardCanvas, FrameNode, ChatPanel, BoardSidebar,
                Inspector, PolishTab, IsolationView, CodePanel, ExportDialog, TopBar
    templates/  EditorLayout (activity bar + resizable columns), PageShell
  pages/        SignIn, Home, Onboarding, Editor, Settings, Profile, SystemUpdate

Rules of the split

  • Atoms render one thing, take no store access.
  • Molecules compose atoms, still store-free (props in, events out).
  • Organisms own a slice of store state and one product concern.
  • Templates own layout only. Pages wire organisms to a screen.
  • engine/ is framework-free and unit-testable; nothing in it imports React.

Product invariants encoded here

  • One runtimeNodeRenderer backs canvas and preview; codegen walks the same tree (engine/codegen.ts is deterministic: same tree → same code).
  • The board is React Flow (@xyflow/react, MIT) — frames are custom nodes with .frame-drag-handle name tabs, so the DOM inside stays fully interactive. Scroll pans, ⌘/pinch zooms at the cursor, pane click deselects; the zustand tree remains the single source of truth (React Flow carries only positions + viewport).
  • 0 unregistered elementsengine/ai.ts whitelist-sanitizes model output and refuses anything outside the registry rather than failing open to generic markup.
  • Green is reserved — the LiveDot atom is the only green in the chrome; success states use neutral surfaces + accent check.
  • Craft is a pass, not a vibeengine/polish.ts holds the Impeccable-derived rules; every issue carries a why and a one-click fix expressed in the user's tokens.

Wiring the model

engine/ai.ts#complete expects a host-provided client (the prototype used one); point it at your /api/compose endpoint in production. Everything else runs fully offline.

Handoff notes — deliberate seams

  • Model bridgeengine/ai.ts#complete throws without a host client; swap in your API.
  • Export zipExportDialog's "Download .zip" is presentational; wire it to a bundler endpoint (the code it shows is real — engine/codegen.ts).
  • Placeholder projectsHomePage lists two static placeholder cards; back with real data.
  • AuthSignInPage continues straight through; SSO buttons are visual.
  • Persistence — the zustand store is in-memory; add storage middleware for real sessions.
  • Theme default is dark (index.html data-theme + store); light is one toggle away.

Prototype parity roadmap

Ported for parity with the prototype: activity bar (ActivityBar — toggleable icon groups drive every panel; tabs live in the store), responsive variants (engine/views.ts — one tree rendered at 13 widths per frame, view chips in Layers with eye toggles, Desktop/Tablet/Mobile/All switcher in the top bar, cluster-shift on resize), and the ultra-minimal flat restyle (paper/ink light default + carbon dark, 2px radii, hairline borders instead of shadows — index.css + tailwind.config.ts).