---
inclusion: always
---

# Project Structure: Gearious (Web)

A working example of a project-structure steering file. Abridged for sharing.

How the codebase is organized and where new code belongs. Generated code should land in the right place and follow the established import patterns.

**Scope:** Web application only.

## Repository Layout

```
gearious/
├── .env.local            # Local env vars — never committed
├── .env.example          # Template of required vars — committed
├── next.config.ts
├── tailwind.config.ts
├── tsconfig.json
├── package.json
├── supabase/
│   └── migrations/       # Numbered SQL migrations — committed
└── src/
    ├── app/              # Next.js App Router (pages + API routes)
    ├── components/       # React components
    ├── lib/              # Framework-agnostic logic & clients
    ├── stores/           # Zustand stores
    ├── hooks/            # TanStack Query + derived-state hooks
    ├── types/            # TypeScript types
    └── proxy.ts          # Session refresh
```

## `src/app/` — Routing

Route groups separate concerns by auth state:

- **`(auth)/`** — unauthenticated pages (login, signup, OAuth callback).
- **`(app)/`** — the authenticated shell. Layout here holds the nav and auth guard; every page beneath it assumes a signed-in user.
- **Public routes** sit outside `(app)` and `(auth)` — a shared view, a post-deletion landing page, the marketing page. Don't put them behind the auth guard.
- **`api/`** — all backend route handlers.

Public-facing surfaces use React Server Components. Interactive surfaces (the planner, libraries) are Client Components.

### API routes mirror the resource tree

Route handlers live in `src/app/api/` and follow the resource hierarchy, one `route.ts` per endpoint. A new resource gets a folder with `route.ts` for the collection (GET/POST) and `[id]/route.ts` for the single item (GET/PATCH/DELETE). Follow the existing routes' auth-and-validate pattern rather than inventing a new one.

## `src/components/` — Components

Organized by area, not by component type:

- **`ui/`** — shadcn/ui components, CLI-generated. Don't hand-author files here.
- **`layout/`** — sidebar, nav, app shell.
- **Feature folders** matching the app routes (`trip-planner/`, `gear/`, `bikes/`, and so on).
- **`shared/`** — pieces reused across two or more features.

A new feature gets its own folder. Anything reused across two or more features moves to `shared/`.

## `src/lib/` — Logic & Clients

Framework-agnostic logic and third-party client singletons:

- **Balance engine** — the pure calculator. **Imports nothing from the codebase** and must stay that way.
- **Weight utilities** — the *only* place unit conversion lives.
- **Supabase clients** — separate browser, server, and (when required) service-role modules. Never import the service-role client from a Client Component.
- Other helpers (password policy, API error shape) live here so routes and forms share one implementation.

## `src/stores/`, `src/hooks/`, `src/types/`

- **`stores/`** — Zustand for UI/optimistic state only. No server data lives here.
- **`hooks/`** — TanStack Query hooks for server data, plus derived state (e.g. feeding the planner store into the balance engine). All server fetching goes through these, never raw fetches in components.
- **`types/`** — generated database types (never hand-edit) plus application and API types.

## `supabase/migrations/`

Numbered, committed SQL files. **Never edit an existing migration** — always add a new numbered one. Regenerate database types after any schema change.

## Import & Placement Patterns

- Use the **`@/` alias** for all internal imports — no deep relative paths.
- **Conversion math** is imported from the weight helper everywhere; it is never reimplemented inline.
- **Server vs. browser Supabase client**: API routes and Server Components use the server client; Client Components use the browser client. Don't mix them.
- The balance engine is consumed through a hook; components don't call it directly.
- File and folder naming conventions are defined in **tech.md** — follow that table.

## Where New Code Goes

| Adding… | Put it in… |
| --- | --- |
| A new authenticated page | `src/app/(app)/<feature>/page.tsx` |
| A public page | `src/app/` (outside `(app)`), as an RSC |
| A new API endpoint | `src/app/api/<resource>/route.ts` (+ `[id]/route.ts`) |
| A feature component | `src/components/<feature>/` |
| A reused component | `src/components/shared/` |
| Pure calculation / a client singleton | `src/lib/` |
| UI/optimistic state | a Zustand store in `src/stores/` |
| Server data access | a TanStack Query hook in `src/hooks/` |
| A schema change | a new numbered file in `supabase/migrations/`, then regenerate types |
