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
This commit is contained in:
87
docs/product/reference/project/veect-codebase/README.md
Normal file
87
docs/product/reference/project/veect-codebase/README.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Veect — design-system-native canvas
|
||||
|
||||
> Full product & design specification: [`SPEC.md`](./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
|
||||
|
||||
```bash
|
||||
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 runtime** — `NodeRenderer` 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 elements** — `engine/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 vibe** — `engine/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 bridge** — `engine/ai.ts#complete` throws without a host client; swap in your API.
|
||||
- **Export zip** — `ExportDialog`'s "Download .zip" is presentational; wire it to a bundler
|
||||
endpoint (the code it shows is real — `engine/codegen.ts`).
|
||||
- **Placeholder projects** — `HomePage` lists two static placeholder cards; back with real data.
|
||||
- **Auth** — `SignInPage` 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 1–3 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`).
|
||||
|
||||
Reference in New Issue
Block a user