# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Full-stack marketplace application with two domains: a **classified listings marketplace** (buy/sell items) and a **rental platform** (apartments, houses, cars, bicycles). Includes admin/moderation tools, Stripe payments, real-time chat via Socket.io, and subscription tiers. ## Architecture - **Monorepo** using npm workspaces (`client/` and `server/`) - **Client**: React 19 + TypeScript + Vite + Tailwind CSS 4 (port 5173) - **Server**: Express + TypeScript + Prisma ORM + PostgreSQL (port 3000) - **Real-time**: Socket.io for messaging and notifications - **Payments**: Stripe (listings, rentals, subscriptions, promotions) - **Auth**: JWT access tokens (15min) + httpOnly refresh token cookies (7 days), bcrypt passwords - **Validation**: Zod schemas on server (`server/src/validators/`), TypeScript on client - **State management**: React Context API (AuthContext), no Redux/Zustand - **Client path alias**: `@/*` maps to `client/src/*` ## Commands ### Development ```bash docker start marketplace-postgres # Start PostgreSQL (required) npm run dev # Run client + server together npm run dev:client # Client only (port 5173) npm run dev:server # Server only (port 3000) ``` ### Database ```bash npm run db:generate --workspace=server # Regenerate Prisma client npm run db:push --workspace=server # Push schema to DB (no migration) npm run db:migrate --workspace=server # Create and apply migration npm run db:seed --workspace=server # Seed test data npm run db:studio --workspace=server # Open Prisma Studio GUI ``` Schema location: `server/prisma/schema.prisma` ### Build & Lint ```bash npm run build # Build both client and server npm run lint # ESLint (client only) ``` ### Testing (QA Suite) ```bash bash tests/run-all.sh # Run all 12 stages locally bash tests/stage-02-auth.sh # Run single stage BASE_URL=https://marketplace.173.212.212.157.sslip.io bash tests/run-all.sh # Against production ``` Tests location: `tests/` — 12 stage scripts, `tests/lib/common.sh` shared library. Requires: bash, curl, jq. ### Seed Data | Email | ID | Role | Landlord | Key data | |-------|-----|------|----------|----------| | alice.chen@example.com | user-alice | SUPER_ADMIN | No | Listings 01,06,11. Offers, bookings, PRO subscription | | bob.martinez@example.com | user-bob | ADMIN | No | Listings 08,10,15 | | carol.nguyen@example.com | user-carol | MODERATOR | No | Listings 02,05,12. Blocked user-david | | david.kim@example.com | user-david | USER | Yes (verified) | Rentals 01,02,06,07. Listings 04,07,13 | | eva.johnson@example.com | user-eva | USER | Yes | Rentals 03,04,05. Listings 03,09,14 | All passwords: `password123` **Key IDs**: listings `listing-01`..`listing-15` | rentals `rental-01`..`rental-07` | bookings `booking-01`..`booking-04` | offers `offer-01`..`offer-10` ## Database: PostgreSQL via Docker Container: `marketplace-postgres` | Image: `postgres:17-alpine` | Volume: `marketplace-pgdata` Connection string: `postgresql://marketplace:marketplace_dev@localhost:5432/marketplace` If container was deleted, recreate: ```bash docker run -d --name marketplace-postgres \ -e POSTGRES_USER=marketplace -e POSTGRES_PASSWORD=marketplace_dev -e POSTGRES_DB=marketplace \ -p 5432:5432 -v marketplace-pgdata:/var/lib/postgresql/data \ --restart unless-stopped postgres:17-alpine ``` ## Key Server Patterns - **Routes**: `server/src/routes/` — RESTful endpoints, admin routes nested under `routes/admin/` - **Middleware**: `authenticate` (required auth), `optionalAuth` (anonymous OK), `requireRole` (role check), `checkBanned`, `validate` (Zod) - **Prisma client**: imported from `server/src/config/database.ts` - **Environment config**: `server/src/config/env.ts` - **File uploads**: Multer to `server/uploads/`, served statically - **User roles**: USER, MODERATOR, ADMIN, SUPER_ADMIN — role hierarchy enforced via `requireRole` middleware ## Key Client Patterns - **Router**: `client/src/router.tsx` — React Router v7 with `createBrowserRouter` - **Auth guards**: `` wraps protected routes, `` checks roles - **API client**: `client/src/api/client.ts` — fetch wrapper that handles auth headers and token refresh - **UI components**: `client/src/components/ui/` — Button, Input, Modal, Card, Badge, DataTable, etc. - **Pages organized by domain**: root pages, `pages/admin/`, `pages/landlord/` ## Chrome DevTools MCP (Browser Testing) Chrome DevTools MCP is configured for automated browser testing. It launches an isolated, telemetry-free Chrome instance. - **Config location**: `~/.claude.json` → `mcpServers.chrome-devtools` (NOT `~/.claude/settings.json`) - **Binary**: `/opt/homebrew/bin/chrome-devtools-mcp` (installed globally via npm) - **Chrome profile**: `/tmp/chrome-mcp-profile` (isolated, no Google account) - **Key flags**: `--isolated` (auto-launches Chrome), `--disable-sync`, `--disable-background-networking` - **Usage**: Available automatically when Claude Code starts. Use `take_snapshot`, `click`, `fill`, `navigate_page`, `take_screenshot` etc. - **If MCP won't start**: Kill zombie processes (`pkill -f chrome-devtools-mcp`), remove lock (`rm /tmp/chrome-mcp-profile/SingletonLock`), restart Claude Code ## Key Env Vars (server/.env) - `DATABASE_URL` — PostgreSQL connection string - `JWT_SECRET` / `JWT_REFRESH_SECRET` — Token signing - `GOOGLE_MAPS_API_KEY` — Location autocomplete - `STRIPE_SECRET_KEY` / `STRIPE_PUBLISHABLE_KEY` — Payments (optional for dev) - `CLIENT_URL` — CORS origin (default: http://localhost:5173)