commit cc15338ad9a28a49caaf39596cd083a051cb5281 Author: ianshaloom Date: Wed Mar 4 09:31:18 2026 +0300 feat: initial commit — storefront, convex backend, and shared packages Completes the first milestone of The Pet Loft ecommerce platform: - apps/storefront: full customer-facing Next.js app with HeroUI (cart, checkout, orders, wishlist, product detail, shop, search, auth) - convex/: serverless backend with schema, queries, mutations, actions, HTTP routes, Stripe/Shippo integrations, and co-located tests - packages/types, packages/utils, packages/convex: shared workspace packages Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..87422e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# Dependencies +node_modules +.pnp +.pnp.js + +# Build outputs +.next +dist +build +out + +# Turbo +.turbo + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Misc +.DS_Store +*.pem +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# TypeScript +*.tsbuildinfo + +# Convex +convex/_generated diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6bd4af3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,153 @@ +# 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 (`
`, `
`, `