# 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 (`
`, `
`, `