82 lines
5.0 KiB
Markdown
82 lines
5.0 KiB
Markdown
# 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/](mykindlebox/) — a `client/` (React + Vite) and a `server/` (Express + SQLite/Drizzle). See [memory-bank/progress.md](memory-bank/progress.md) for the phase-by-phase build log. The source-of-truth design docs are:
|
|
|
|
- [memory-bank/app-design-document.md](memory-bank/app-design-document.md) — full product spec: pages, components, data models, UX decisions
|
|
- [memory-bank/tech-stack.md](memory-bank/tech-stack.md) — the chosen stack (summarized below)
|
|
- [memory-bank/architecture.md](memory-bank/architecture.md) — current architecture + database schema
|
|
|
|
### Commands
|
|
|
|
Backend (`mykindlebox/server`):
|
|
|
|
- `npm run dev` — start the API on port 3001 with `tsx watch` (hot reload)
|
|
- `npm run build` — typecheck + compile to `dist/`
|
|
- `npm start` — run the compiled server (`node dist/index.js`)
|
|
- There is no test suite yet (`npm test` is a placeholder).
|
|
|
|
Frontend (`mykindlebox/client`):
|
|
|
|
- `npm run dev` — Vite dev server on port 5173 (proxies `/api` and `/uploads` to `localhost:3001`)
|
|
- `npm run build` — production build to `dist/`
|
|
- `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). `MYKINDLEBOX_PORT` in `mykindlebox/.env` overrides the host port. Auth is account-based (first visit shows a one-time account-creation screen; more users added in Settings) — the old `MYKINDLEBOX_PASSWORD`/`AUTH_PASSWORD` env var is retired and ignored.
|
|
|
|
### Conventions
|
|
|
|
- The REST API speaks **snake_case** at the boundary; Drizzle columns are camelCase. `server/utils/case.ts` converts both directions — don't hand-write conversions.
|
|
- The client talks to the API over **relative URLs** (`/api`, `/uploads`). Never reintroduce a hardcoded `http://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 self-hosted with **shared-herd user accounts** (users are separate logins to the same rabbitry — see `memory-bank/FEATURE_User_Accounts.md`; everyone equal, no roles). Out of scope: multi-tenancy (per-user herds), public listing pages, 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 | User accounts, shared herd (scrypt + SQLite sessions, 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 `status` field, not cached counters.
|
|
- Mobile bottom nav's "Add" tab opens the rabbit entry flow directly.
|
|
</content>
|
|
</invoke>
|