# AV Planner Plan out AV/network installs: define devices and their ports, wire them together on a canvas, and get a bill of materials (devices + cables, with lengths) for what you'll need to buy. ## Stack - **React 19 + TypeScript + Vite** - **[@xyflow/react](https://reactflow.dev)** (React Flow) for the device/wiring canvas - **Zustand** for app state - **Tailwind CSS v4** for styling ## Architecture ``` src/ domain/ Framework-agnostic types + logic (compatibility rules, BOM math, the built-in connector/cable/device library). No React, no React Flow — safe to unit test or reuse from a future backend. data/ Storage abstraction. `DiagramRepository` is the interface the rest of the app codes against; `SupabaseDiagramRepository` is the active implementation, with `LocalStorageDiagramRepository` kept as a reference/fallback. Swapping storage means adding one new implementation of that interface, not touching state/UI code. state/ Zustand store (`diagramStore`) — the single source of truth for the current diagram. Auto-saves to the repository (debounced) on every change. components/ canvas/ React Flow wiring surface: custom device node, custom cable edge, connection validation. palette/ Device library sidebar + the "new custom device" editor. inspector/ Right-panel editors for the selected device or cable. bom/ Bill-of-materials view. layout/ App shell, top bar, panels. ``` ### Data model - **PortType** — a connector kind (HDMI, XLR, Cat5e/6, ...). Two ports can be wired together only if their PortTypes share a compatibility `family`. - **DeviceTemplate** — a reusable device shape (its ports), shown in the palette. Built-ins live in `domain/library.ts` and seed the public catalog; custom ones are your own private catalog entries (or submitted for public review). - **Device** — an instance placed on the canvas, with its own copy of ports (editing an instance never mutates its template). - **CableType** — a physical cable spec, scoped to a PortType family. - **Connection** — a wire between two ports, referencing a CableType and an optional user-entered distance (there's no floor plan / scale model, so length is a manual estimate per connection). - **Diagram** — devices + connections. This is the one object persisted (auto-saved to Supabase, or explicitly exported/imported as JSON); the catalog (PortType/CableType/DeviceTemplate/category) is shared and global, not part of any one diagram. ## Development ```bash npm install npm run dev # start the dev server npm run build # typecheck + production build npm run lint # oxlint ```