# Plan

## Goal

Build a Vite + TypeScript + Vitest single-page force-directed graph explorer that handles a
synthetic graph of 5,000 nodes and about 10,000 edges, renders through Canvas, exposes the required
`src/lib/graph-core.ts` acceptance API, and provides a performance hook for the benchmark harness.

## Architecture

- `src/lib/graph-core.ts`
  - Pure, DOM-free acceptance module.
  - Implements `neighbors`, `searchNodes`, `filterByGroup`, and a reusable axis-aligned `QuadTree`.
  - Keeps deterministic, easy-to-test behavior for hidden tests.
- `src/lib/graph-generator.ts`
  - Deterministic clustered graph generator using a seeded PRNG.
  - Produces community labels, initial positions, and a sparse edge set with local community links
    plus cross-community bridges.
- `src/lib/simulation.ts`
  - Force-directed layout core using typed arrays for positions, velocities, forces, group ids, and
    edge endpoints.
  - Barnes-Hut quadtree for repulsion, spring forces for edges, mild center gravity, velocity
    damping, and temperature decay.
  - Exposes stepping, visible graph metadata, picking helpers, and snapshot data for rendering.
- `src/lib/view-transform.ts`
  - Small pure world/screen transform utilities for pan, zoom, and fit-to-graph behavior.
- `src/render/canvas-renderer.ts`
  - Canvas renderer separated from simulation.
  - Draws filtered edges/nodes, group colors, highlights, hover/click neighborhoods, labels at high
    zoom, and a minimap.
- `src/App.tsx`
  - React shell for controls and status only: search, group filter, simulation sliders, stats.
  - Owns canvas event wiring for pan, zoom, hover, click, and focus.
- `tests/`
  - Unit tests for the acceptance API, quadtree range behavior, graph generation invariants, and a
    small simulation sanity step.

## Libraries

- `vite`, `typescript`, `vitest`: required stack and objective harness contract.
- `react`, `react-dom`: lightweight UI shell; graph rendering stays in Canvas instead of DOM.
- `@vitejs/plugin-react`: Vite React build integration.
- `eslint`, `typescript-eslint`, `@eslint/js`: required by the shared ESLint flat config.

No graph layout dependency is planned. The layout is implemented directly so the benchmark can audit
the data structures, typed arrays, and Barnes-Hut strategy.

## Performance Approach

- Store the simulation in typed arrays to avoid per-frame object churn.
- Build a Barnes-Hut tree each simulation tick and use theta-based approximation for repulsion.
- Keep edge iteration linear in edge count.
- Render nodes and edges to a single Canvas; no node DOM elements.
- Throttle expensive UI-derived sets by recomputing only when search/filter/click state changes.
- Expose `window.__buildoff.warmup()` and `window.__buildoff.workload()` so the harness can measure
  the actual 5k/10k workload.

## UX Approach

- First screen is the actual explorer, not a marketing page.
- Dense operational layout: compact top controls, full-bleed graph canvas, status panel overlays.
- Pan by dragging empty space, zoom by wheel at cursor, hover/click to highlight a node and its
  neighbors.
- Search by id or label, group filter through a select, live sliders for repulsion/link distance.
- Community coloring plus labels when zoomed in; minimap for orientation.

## Risks

- Barnes-Hut implementation needs enough accuracy to visibly settle without spending too much time
  rebuilding the tree.
- Canvas drawing 10k edges every frame can dominate runtime; the renderer may skip faint filtered
  edges or reduce label work based on zoom to protect frame rate.
- React state updates must stay out of the animation hot path; mutable refs will hold the simulation
  and interaction state.
- Shared `tsconfig.json` has `noUnusedLocals` and strict mode, so implementation must keep types
  explicit and avoid dead helpers.
