71e4c2c22d37987a31c3266079973df8bce12d7c
The last pipeline run failed on \`npx wrangler deploy\` with npm unable to find wrangler@4.144.0 — a transient registry propagation gap right after that version's release, not an actual config problem (it installs fine moments later, confirmed locally). Both wrangler and the supabase CLI were being fetched fresh via bare npx on every single pipeline run instead of coming from the lockfile like every other dependency, which is exactly what left CI exposed to whatever npm's registry happens to be doing at that moment. Pinning them means npm ci resolves the exact locked version every time, and npx picks up the local install instead of hitting the registry at all. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
Diagrav
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 (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.tsand 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
npm install
npm run dev # start the dev server
npm run build # typecheck + production build
npm run lint # oxlint
Languages
TypeScript
79.7%
PLpgSQL
16.3%
HTML
1.6%
JavaScript
1.3%
CSS
1.1%