# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
**The Pet Loft** — a full-stack ecommerce platform for pet supplies. Turborepo monorepo with two Next.js apps, a shared Convex backend, and shared packages.
## Development Commands
Two processes must run simultaneously for full-stack development:
```bash
# Terminal 1 — Convex backend (must run first)
npx convex dev
# Terminal 2 — Next.js apps
npm run dev # Both apps in parallel
npm run dev:storefront # Storefront only (port 3000)
npm run dev:admin # Admin only (port 3001)
```
```bash
npm run type-check # TypeScript check across all workspaces
npm run lint # ESLint via Turbo
npm run test # Vitest watch mode (edge-runtime)
npm run test:once # Run all tests once
npm run test:coverage # Coverage report
npm run build # Build both apps
```
To run a single test file: `npx vitest run convex/carts.test.ts`
## Architecture
### Monorepo Layout
```
apps/storefront/ # Customer store — Next.js + HeroUI (port 3000)
apps/admin/ # Staff dashboard — Next.js + ShadCN (port 3001)
convex/ # Serverless backend: schema, functions, HTTP routes, tests
packages/types/ # Shared TypeScript interfaces (Product, Order, User…)
packages/utils/ # Shared helpers: formatPrice, slugify, formatDate
packages/convex/ # ConvexClientProvider (Clerk + Convex integration)
```
### Backend: Convex
All backend logic lives in `convex/`. The schema defines 11 tables:
- **users** — Clerk-synced; roles: `customer`, `admin`, `super_admin`
- **products** / **productImages** / **productVariants** — catalog with SKUs
- **categories** — hierarchical (parent + topCategory slugs)
- **carts** — guest (`sessionId`) or authenticated (`userId`), 30-day expiry
- **orders** / **orderItems** — price/address snapshots at order time
- **addresses** — shipping/billing with validation flag
- **reviews** / **wishlists** — community features
Business logic is extracted into `convex/model/*.ts` helpers and reused across public functions.
### Auth Flow
1. Clerk handles UI + JWT. `ConvexProviderWithClerk` (from `@repo/convex`) passes the JWT to Convex.
2. `convex/auth.config.ts` trusts the Clerk JWT issuer domain.
3. Convex functions access the user via `ctx.auth.getUserIdentity()`.
4. `convex/model/users.ts` exports `getCurrentUser`, `requireAdmin`, `requireOwnership`.
5. Clerk webhooks sync user changes to the `users` table via `convex/http.ts`.
### Guest Cart & Session
- A guest `sessionId` is generated on first load and stored in a cookie (`apps/storefront/src/lib/session/`).
- All cart/wishlist queries accept either `userId` (signed-in) or `sessionId` (guest).
- On sign-in, `SessionCartMerge` component triggers a merge mutation to fold the guest cart into the user's cart.
### Checkout Flow
1. Address validation — `convex/model/checkout.ts` + Convex address functions
2. Shipping rates — Shippo API via `convex/model/shippo.ts`
3. Payment intent — Stripe via `convex/stripeActions.ts`
4. Order creation — snapshots of items, addresses, and pricing captured in `convex/orders.ts`
5. Stripe webhook — handled in `convex/http.ts`, updates order payment status
## Convex Function Conventions
Always use the new function syntax with explicit validators:
```typescript
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
export const myFunction = query({
args: { id: v.id("products") },
handler: async (ctx, args) => { ... },
});
```
- Use `internalQuery` / `internalMutation` / `internalAction` for private functions.
- HTTP endpoints go in `convex/http.ts` using `httpAction`.
- Use `ctx.runQuery` / `ctx.runMutation` from actions; avoid chaining many calls (race conditions).
- Leverage index-based queries over full table scans.
## Storefront UI Rules
**HeroUI** is the component library for the storefront. Two mandatory overrides:
| Situation | Use |
|-----------|-----|
| Internal navigation | `next/link` `` (never `@heroui/react` `Link`) |
| Content images | `next/image` `` (never raw ``) |
Preserve semantic HTML (``, ``, `