diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b49bcef --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```bash +npm run dev # Start dev server at localhost:3000 +npm run build # Production build (TS errors and ESLint are suppressed — see next.config.mjs) +npm run lint # ESLint check +``` + +No test framework is configured. + +## Environment Variables + +`.env.local` for development: +``` +NEXT_PUBLIC_API_BASE_URL=http://localhost:8080 +BACKEND_BASE_URL=http://localhost:8080 +LAUNCH_ONLY_ROOT=false # Set to "true" to restrict unauthenticated users to root page only +NEXT_PUBLIC_SHORTLINK_BASE_URL=http://localhost:8080 +``` + +In Docker, the Spring Boot service is resolved as `http://battlbuilder-api:8080` (the default in `lib/springProxy.ts` when `SPRING_BASE_URL` is unset). + +## Architecture + +### Two backends +1. **Spring Boot** — primary data backend. All product catalog, builds, auth, merchant/admin data lives here. +2. **Sanity CMS** — content only (guides/blog posts). Project `zal102rv`, dataset `production`. Queries in `lib/sanity.ts`. + +### API proxy pattern +Next.js API routes (`app/api/`) act as a thin proxy to Spring Boot. Client code never calls Spring Boot directly. The helper `lib/springProxy.ts` forwards cookies and auth headers to Spring Boot and handles response serialization. + +### Authentication +- **Session cookie**: `session_token` HTTP-only cookie set by Spring Boot, forwarded by the proxy. +- **Client state**: `AuthContext` (`context/AuthContext.tsx`) hydrates from `localStorage` on mount, then verifies against `/api/auth/me`. +- **Middleware**: `middleware.ts` enforces route protection. Public paths are whitelisted; `/admin/*` requires login; `/builder`, `/builds`, `/vault` are gated only when `LAUNCH_ONLY_ROOT=true`. + +### Route groups +- `app/(app)/` — main consumer app layout (TopNav + Footer) +- `app/(app)/(builder)/` — builder + parts browser (BuilderNav layout) +- `app/(account)/` — account settings pages (AccountChrome sidebar layout) +- `app/admin/` — internal admin tools (AdminLeftNavigation layout) +- `app/api/` — 50 server-side route handlers proxying to Spring Boot + +### Builder domain model +The builder is AR-platform-centric. Key concepts: + +- **`BuilderSlotKey`** (`types/builderSlots.ts`) — the canonical kebab-case category ID (e.g., `"complete-upper"`, `"barrel"`). This is the source of truth for localStorage keys, URL state, and backend part role mapping. +- **`CATEGORY_TO_PART_ROLES` / `PART_ROLE_TO_CATEGORY`** (`lib/catalogMappings.ts`) — bidirectional mapping between `BuilderSlotKey` and backend `partRole` strings. Update here when the backend adds new part roles. +- **`BUILDER_SLOTS`** (`data/builderSlots.ts`) — defines slot groups (LOWER, UPPER, SYSTEM, ACCESSORIES) and satisfaction patterns (e.g., a complete lower satisfies the lower assembly slot). +- **`BuildState`** — `Partial>` stored in `localStorage`. Product IDs are the values. +- **Overlap detection** (`lib/buildOverlaps.ts`) — warns users when they select both a complete assembly and individual sub-parts. + +### Legacy key aliases +`types/builderSlots.ts` exports `normalizeSlotKey()` which maps camelCase legacy keys (e.g., `completeUpper`) to current kebab-case keys. This is needed for backwards-compatible URL/localStorage deserialization. + +### API client pattern +- Client components use `useApi()` hook (`lib/api.ts`) for fetch calls with `credentials: 'include'`. +- Admin-specific API calls live in `lib/api/` (e.g., `adminCategoryMappings.ts`, `adminMerchantMappings.ts`). +- Product catalog helpers are in `lib/catalog.ts`. + +### Sanity content +- `lib/sanity.ts` — Sanity client + GROQ queries for posts. +- `lib/sanityFetch.ts` — low-level HTTPS fetch to Sanity IP (bypasses CDN DNS issues in server/Docker environments). +- Guides at `/guides/[slug]` are the only public Sanity-driven pages.