Skip to main content

File-Based Routing (TanStack Router)

Both apps use TanStack Router’s file-based routing. The router tree is auto-generated by the Vite plugin — you only create/delete/rename files in src/routes/.
Never manually edit src/routeTree.gen.ts. It’s auto-generated on every save. Editing it will be overwritten immediately.

Route File Naming Conventions

Creating a New Route

Route with Dynamic Parameter

Accessing Router Context


Server State (TanStack Query)

All data fetched from the backend lives in TanStack Query. Never store API data in Zustand — that’s for local UI state only.

Standard Query Hook Pattern

Standard Mutation Pattern

Polling for Live Data

Used for scan status updates:

Query Keys Convention

Use arrays to namespace query keys by feature:

Client State (Zustand)

Use Zustand for UI state that doesn’t come from the server: modal open/closed, selected tab, pending selections.

Store Pattern

Rule of Thumb: Zustand vs Query


Forms (react-hook-form + Zod)

All forms use react-hook-form with Zod validation via @hookform/resolvers.

Standard Form Pattern

Reusable Validation Schemas

Common schemas are in packages/common/src/utils/validations.ts. Import from there:

API Service Pattern

API calls live in src/model/ (service files). They are plain async functions, not hooks — hooks live in src/store/server/.

Authentication

Auth token is read from the access_token cookie on every request:

Styling (Tailwind CSS)

Tailwind Prefix

All utilities use the wy- prefix to avoid conflicts with third-party styles:

Conditional Classes

Use clsx and tailwind-merge together:

Theme Colours

Defined in each app’s tailwind.config.js:
Dark mode uses CSS variables (HSL-based), toggled via a dark class on <html>.

Component Development Rules

  1. Shared = goes in packages/common — never duplicate across apps
  2. App-specific = stays in apps/<name>/src/components/
  3. Use Radix UI via packages/common/src/components/shadcn/ — never install Radix directly in an app
  4. No inline styles — Tailwind classes only
  5. All icons from packages/common/src/components/icons/ — add new icons there if missing
  6. Forms always use Zod resolver — no manual validation logic