# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Pokemon TCG card database and inventory management app. Users search cards, track market prices, and manage their collections. Closed beta. ## Commands ```bash npm run dev # Start dev server (binds 0.0.0.0:4321) npm run build # Production build → ./dist/ npm run preview # Preview production build ``` No test framework or linter is configured. Utility scripts in `scripts/` are run directly with `tsx` (e.g., `npx tsx scripts/reindex.ts`). ## Tech Stack - **Astro 5** (SSR mode, Node.js standalone adapter) - **PostgreSQL** via Drizzle ORM (schema in `pokemon` namespace, snake_case DB columns) - **Typesense** for full-text card search - **Clerk** for authentication - **HTMX** for dynamic interactions (no SPA framework) - **Bootstrap 5** with custom SCSS overrides, dark theme - **Chart.js** for price history charts ## Architecture ### Data Flow TCGPlayer source data → `tcg_cards` → denormalized `cards` (per variant) → `skus` (per condition/language) → `price_history` / `sales_history`. User collections stored in `inventory` table linked to Clerk userId. PostgreSQL is source of truth. Typesense mirrors card/sku/inventory data for search. Both must be kept in sync — see `src/pages/api/inventory.ts` for the sync pattern (write to PG, then upsert/delete in Typesense). ### Key Directories - `src/pages/` — Astro routes and API endpoints - `src/pages/partials/` — HTMX partial responses (HTML fragments returned to `hx-post` targets) - `src/pages/api/` — JSON/file API endpoints (`upload.ts` for CSV, `inventory.ts` for CRUD) - `src/components/` — Reusable `.astro` components - `src/db/` — Drizzle schema (`schema.ts`), relations (`relations.ts`), DB connection (`index.ts`), Typesense client (`typesense.ts`) - `scripts/` — Data ingestion and indexing utilities (not part of the app runtime) ### Authentication Clerk middleware in `src/middleware.ts` protects routes via `createRouteMatcher`. Auth context accessed via `Astro.locals.auth()` in pages/API routes. ### Database Schema Drizzle config uses `casing: 'snake_case'` — define schema fields in camelCase, they map to snake_case columns automatically. Migrations live in `./drizzle/`. Schema is scoped to the `pokemon` PostgreSQL schema. ### Frontend Patterns Pages use HTMX for interactivity — forms POST to `/partials/*` endpoints that return HTML fragments. No client-side routing. View Transitions API enabled for page navigation animations. Card modals and inventory forms are HTMX-driven with `hx-post`, `hx-target`, and `hx-swap` attributes.