4.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
IMPORTANT:
Always read memory-bank/@architecture.md before writing any code. Include entire database schema.
Always read memory-bank/@app-design-document.md before writing any code.
After adding a major feature or completing a milestone, update memory-bank/@architecture.md.
Project status
The application is built and lives under mykindlebox/ — a client/ (React + Vite) and a server/ (Express + SQLite/Drizzle). See memory-bank/progress.md for the phase-by-phase build log. The source-of-truth design docs are:
- memory-bank/app-design-document.md — full product spec: pages, components, data models, UX decisions
- memory-bank/tech-stack.md — the chosen stack (summarized below)
- memory-bank/architecture.md — current architecture + database schema
Commands
Backend (mykindlebox/server):
npm run dev— start the API on port 3001 withtsx watch(hot reload)npm run build— typecheck + compile todist/npm start— run the compiled server (node dist/index.js)- There is no test suite yet (
npm testis a placeholder).
Frontend (mykindlebox/client):
npm run dev— Vite dev server on port 5173 (proxies/apiand/uploadstolocalhost:3001)npm run build— production build todist/npm run lint— ESLint
Deployment: docker compose up --build from mykindlebox/ serves the app on port 8080 by default (nginx serves the built client and reverse-proxies /api + /uploads to the Node server). Configure via mykindlebox/.env: MYKINDLEBOX_PORT overrides the host port, and MYKINDLEBOX_PASSWORD requires a login (if unset, auth is disabled).
Conventions
- The REST API speaks snake_case at the boundary; Drizzle columns are camelCase.
server/utils/case.tsconverts both directions — don't hand-write conversions. - The client talks to the API over relative URLs (
/api,/uploads). Never reintroduce a hardcodedhttp://localhost:3001; it breaks LAN/PWA access from other devices.
What MyKindlebox is
A self-hosted rabbitry (rabbit breeding herd) management web app, replacing an existing PHP app (belowland.com/rabbitsite). It is single-user, self-hosted, and out of scope for v1 includes multi-tenancy, public listing pages, show tracking, and payments.
The core differentiator: adding a rabbit starts from a pedigree tree, not a blank form — the 3-generation ancestor tree (sire/dam, their sires/dams) is the primary data-entry surface, with inline autocomplete search against existing herd records and graceful fallback to freeform text for unknown/bought-in ancestors.
Tech stack (planned)
| Layer | Choice |
|---|---|
| Frontend | React + Vite (PWA-ready) |
| Routing | React Router v7 |
| State | Zustand (local UI state) + React Query (server sync) |
| Styling | Tailwind CSS with custom theme tokens |
| Backend | Node.js + Express (REST API) |
| Database | SQLite via Drizzle ORM (single-file DB) |
| Auth | Single-user session token (no OAuth) |
| Hosting | Docker Compose (Nginx + Node + SQLite volume) |
Data model
There are only two core tables — no separate "Kit" table:
- Rabbit: name, sex, dob, weight_lbs, status (
active/for_sale/on_hold/sold/deceased/other),sire_id/dam_id(self-referencing FKs), and genetics loci fields (locus_a/b/c/d/e/en/v). - Litter:
sire_id/dam_id,kindle_date,kit_count,notes.
Kits are full Rabbit records from birth, linked to a litter implicitly via matching sire_id/dam_id/DOB — the Litter detail page derives its kit list by querying Rabbits rather than a join table. When adding features touching litters or kits, preserve this derivation rather than introducing a Kit entity.
Ancestor pedigree nodes that aren't in the DB are stored as freeform text rather than null FKs, so entry is never blocked by incomplete ancestor records.
Weight is stored as a decimal float in lbs internally; lb+oz vs decimal display is a per-user setting applied at the read/write boundary, not stored separately.
The genetics calculator's pairings are session-only and never persisted.
Key UX decisions to preserve
- Pedigree-first entry flow (Step 1: pedigree tree → Step 2: rabbit details → Step 3: genetics loci, collapsible/optional → Step 4: review & save).
- Genetics section defaults collapsed on Add, expanded on Edit if loci data already exists.
- Dashboard herd counts (For Sale/On Hold/Sold/etc.) are derived live from the Rabbit
statusfield, not cached counters. - Mobile bottom nav's "Add" tab opens the rabbit entry flow directly.