# Repository Guidelines ## Scope This repository contains the Vite and React single-page frontend for the Agent-driven supply-network WebGIS. Runtime TypeScript lives under `src/`. The application uses React 19, TypeScript, Tailwind CSS, MapLibre GL, deck.gl, SWR, Vitest, and Playwright. Keep this project browser-first. Do not add Next.js APIs, `"use client"` directives, or general backend-for-frontend routes. Agent reasoning and tool execution belong in `next-tjwater-agent`. ## Source Layout - `src/app/` owns application startup, providers, and shell composition. - `src/features/workbench/` owns supply sources, layers, SCADA overlays, scenarios, feature adapters, GeoServer configuration, and workbench interactions. - `src/features/agent/` owns Agent protocol clients, sessions, typed frontend actions, validated UI envelopes, recommendations, and Agent panels. - `src/features/map/core/` owns domain-neutral map controls, legends, notices, and reusable map presentation primitives. - `src/shared/` owns reusable UI, AI presentation elements, runtime configuration, and feature-independent utilities. - `src/mocks/` owns MSW handlers and fixtures. - `src/test/` owns shared Vitest setup and repository-wide invariant tests. - `tests/browser/` owns product-level Playwright regressions. - `public/` contains static supply-network and SCADA assets plus the runtime-config placeholder. - `server/` contains the same-origin Edge TTS adapter used by Vite and the production container. Do not recreate a catch-all `src/lib/` directory. Put feature-independent helpers in `src/shared/`; put supply-network and GeoServer logic in the owning `workbench` module. Do not create empty placeholder directories. Add a directory with its first source file. ## Dependency Direction and Public APIs Keep dependencies moving toward generic code: ```text app -> workbench, map/core, shared workbench -> agent, map/core, shared agent -> map/core, shared map/core -> shared shared -> external packages only ``` - `src/app` may import the `workbench` and `map/core` public APIs plus shared startup configuration. - `workbench` may import `agent`, `map/core`, and `shared`. - `agent` may import generic `map/core` presentation helpers and `shared`, but it must not import `workbench`. - `map/core` must not know supply layer IDs, SCADA models, workbench state, or Agent workflows. - `shared` must not import from `app`, `features`, or `mocks`. - Runtime feature code must not import from `app` or `mocks`. Use a feature's `index.ts` as its public API for cross-feature imports. Add an intentional public export when another feature needs a symbol. Use relative imports within the same feature. Do not introduce cross-feature deep imports or barrels for private implementation files. ## Component and Module Design - Use TypeScript and React function components. Export explicit types at feature and adapter boundaries. - Use two-space indentation and kebab-case filenames. Use PascalCase for components and types, camelCase for functions and values, and `useXxx` for hooks. - Keep application and page components focused on composition. Extract state, effects, network flows, resize behavior, and map orchestration into focused hooks, controllers, or child components. - Keep MapLibre sources, layers, camera helpers, feature queries, and event handling outside presentational components. Map mutations belong in typed controllers or map helpers. - Keep Agent rendering schema-driven. Validate Agent output before it reaches React. Model map actions as typed data that can be previewed, confirmed, applied, and rolled back. - Keep reusable UI free of supply-network terminology and workflow state. The owning feature decides business behavior. - Prefer one source of truth. Search for an existing utility, config wrapper, style token, or domain type before adding another. ## Supply-Domain Boundary This repository models a supply network. Pipes, junctions, valves, reservoirs, tanks, pumps, pressure, flow, water age, demand, isolation, and continuity of supply belong in `workbench`. Do not introduce drainage-network layer IDs, assets, terminology, export filenames, configuration prefixes, fixtures, or operating assumptions. Drainage concepts such as conduits, orifices, outfalls, manholes, sewage, stormwater, and overflow risk do not belong here. `next-tjwater-drainage-frontend` may be consulted for generic architecture patterns only. Never copy its domain constants, source catalogs, map styles, icons, mocks, product copy, environment variables, or defaults into this repository. The supply-domain invariant test in `src/test/supply-domain.test.ts` must remain green. ## Runtime and Server Boundaries Browser configuration is injected through `/runtime-config.js` and validated in `src/shared/config/env.ts`. Use `TJWATER_*` variables. Do not add `DRAINAGE_*`, `VITE_*`, or legacy `NEXT_PUBLIC_*` browser configuration. Browser-safe GeoServer reads may happen directly when CORS is enabled. Agent requests go to the configured Agent service. The local `server/` exception is limited to the same-origin Edge TTS network adapter; do not turn it into a general API layer or add free-form proxy routes. ## Tests - Co-locate focused Vitest tests with the module under test using `*.test.ts` or `*.test.tsx`. - Put repository-wide invariants and shared setup in `src/test/`. - Put new product and interaction Playwright tests in `tests/browser/`. `src/app/app.e2e.ts` is retained migration coverage, not a location to copy. - Name tests after behavior. Cover pure map calculations, adapters, protocol validation, and state transitions without requiring a browser when possible. - Add focused Playwright coverage for visible behavior, responsive layout, runtime configuration, keyboard and pointer interaction, or map integration. ## Commands and Verification Use `pnpm` from this repository. ```bash pnpm dev # start Vite on http://127.0.0.1:5173 pnpm lint # run ESLint pnpm typecheck # run TypeScript without emitting files pnpm test # run Vitest pnpm test:browser # run Playwright pnpm build # typecheck, build the SPA, and bundle the TTS adapter ``` Match verification to the change: - Documentation-only changes: run `git diff --check` and verify referenced paths and commands. - TypeScript logic or component changes: run `pnpm lint`, `pnpm typecheck`, and `pnpm test`. - Visible UI, responsive, configuration, or map interaction changes: also run focused `pnpm test:browser` coverage. - Dependency, Vite, container, runtime integration, or release changes: also run `pnpm build`. Do not report a check as passing unless it ran in the current worktree. If a required browser or external service is unavailable, report the skipped layer and reason. ## Security and Repository Hygiene Do not commit secrets, `.env.local`, generated `dist/` or `dist-server/`, dependency folders, Playwright artifacts, session dumps, tokens, or logs. Keep server-only targets and credentials in untracked environment files. Treat Agent output, UI envelopes, feature identifiers, URLs, and runtime configuration as untrusted input. Validate at system boundaries, keep credentials out of browser-visible values, and use typed adapters instead of free-form command or request construction. Preserve unrelated work in a dirty checkout. Do not clean, reset, move, or rewrite user changes while completing a scoped task.