# 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.
