6cdfde822de85b1f14b6b87b14155b109ea10085
Announcements: a Super Admin (or an Admin individually flagged via profiles.can_post_announcements) can post/retire a site-wide banner. Account migration: a Super Admin can move a locked-out user's diagrams, private catalog entries, and submissions to another account, with a migration-history log; ProfileModal adds the self-service half (link a new Google identity via Supabase manual linking, then unlink the old one, while signed in as the account being migrated). Also reworks the top bar's flat button row into grouped dropdown menus (Diagram / Admin / Account) now that there are enough entries to need it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
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 (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%