Files
the-pet-loft/CLAUDE.md
ianshaloom cc15338ad9 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 <noreply@anthropic.com>
2026-03-04 09:31:18 +03:00

5.9 KiB
Raw Permalink Blame History

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:

# 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)
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:

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 <Link> (never @heroui/react Link)
Content images next/image <Image> (never raw <img>)

Preserve semantic HTML (<main>, <header>, <footer>, <article> per product card, <ol> for breadcrumbs) even when composing Hero UI components around them.

PetPaws Branding (Storefront)

Typography:

  • Headings (h1h3): Fraunces serif — font-[family-name:var(--font-fraunces)]
  • Body / UI: DM Sans — font-sans (default)

Key colors:

Token Hex Usage
Deep Teal #236f6b Header/footer bg, price text
Brand Teal #38a99f Primary buttons, links, focus rings
Sunny Amber #f4a13a High-priority CTAs ("Add to Cart")
Playful Coral #f2705a Discount badges, sale text, alerts
Forest Black #1a2e2d Body text (never pure #000000)
Ice White #f0f8f7 Page background

Prefer CSS variables or Tailwind arbitrary values over raw hex. Do not mix coral and amber in the same component.

Shared Packages

import type { Product, Order, User } from "@repo/types";
import { formatPrice, slugify, formatDate } from "@repo/utils";
import { ConvexClientProvider } from "@repo/convex";  // wraps app layouts

Both apps' next.config.js transpile @repo/* packages.

Testing

Tests are co-located with source files (convex/*.test.ts). Vitest runs in edge-runtime using convex-test. Environment variables for tests are not required — convex-test mocks the Convex runtime.

Environment Variables

Each app has its own .env.local (copy from .env.example). Required vars:

  • NEXT_PUBLIC_CONVEX_URL — from Convex dashboard
  • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY / CLERK_SECRET_KEY
  • STRIPE_SECRET_KEY / NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  • SHIPPO_API_KEY

Convex backend env vars (set in Convex Dashboard): CLERK_JWT_ISSUER_DOMAIN, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, SHIPPO_API_KEY.