Frontend test project for freight auctions. Single-page React application driven by an
OpenAPI contract (docs/openapi.auctions.v0.json), mocked end-to-end with MSW.
| Concern | Choice |
|---|---|
| UI library | React + TypeScript |
| Build tool | Vite |
| Routing | TanStack Router (code-based, typed validateSearch) |
| Server state | TanStack Query (handwritten hooks, generated SDK isolated) |
| Forms | React Hook Form |
| Validation | Zod |
| Mock API | MSW (single in-memory runtime store) |
| Client UI state | URL search params + local useState (see note below) |
| Notifications | Sonner (toasts for bet mutation feedback) |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Architecture | Feature-Sliced Design |
| Codegen | Hey API → src/shared/api/generated/ |
| Formatter / linter | oxfmt + oxlint, plus Steiger for FSD boundaries |
pnpm install
pnpm dev # http://localhost:5173MSW intercepts every API call in development — no backend is required. The worker boots before
createRoot, so no app fetch leaks to the network.
pnpm dev # vite dev server
pnpm build # tsc -b && vite build
pnpm preview # preview the production build
pnpm typecheck # tsc -b / --noEmit
pnpm lint # oxlint
pnpm lint:fsd # steiger FSD boundary checks
pnpm fmt # oxfmt (writes)
pnpm fmt:check # oxfmt (check only)
pnpm check # typecheck + lint
pnpm codegen # regenerate OpenAPI SDK + types from docs/openapi.auctions.v0.json
pnpm test # vitest watch
pnpm test:run # vitest run (CI mode) — logic + MSW-handler integration tests
pnpm test:e2e # playwright — browser smokes (auto-starts vite on :5175)SMOKE_PORT / SMOKE_BASE override the dev port and base URL for pnpm test:e2e. Filter by file
or test name with pnpm test:e2e e2e/route.spec.ts or --grep "pagination".
docs/
openapi.auctions.v0.json # contract source of truth
sdd/ # task decomposition (SDD-001..031) and decisions
src/
app/ # router, providers, route definitions
pages/ # shell + content page slices
features/auction-filters/ # URL filter contract + form
entities/auction/ # VM mappers, query hooks, badges, describe/labels
shared/api/ # generated SDK (isolated) + adapters + MSW
shared/ui/ # shadcn primitives
shared/lib/ # generic helpers
e2e/ # playwright browser smokes (run via `pnpm test:e2e`)
AGENTS.md # rules for any AI/agent working in this repo
AI_USAGE.md # what was done with AI, decisions, risks, limitations
Three layers of automated checks; each layer owns a distinct concern.
Fast loop, runs locally on every save and mirrors the CI matrix in .github/workflows/ci.yml. Adding a gate here should also land in the workflow and vice versa.
| Layer | Command | What it asserts |
|---|---|---|
| Format | pnpm fmt:check |
oxfmt — verifies formatting without writing; the only formatting gate (no fmt in check) |
| Types | pnpm typecheck |
tsc -b across app + tests; catches contract drift between OpenAPI codegen, DTOs, and consumers |
| Lint | pnpm lint |
oxlint — React hooks, accessibility, import order |
| FSD boundaries | pnpm lint:fsd |
steiger — shared/api/generated isolation, public/private slices, import direction |