MyKindlebox/memory-bank/app-design-document.md

386 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MyKindlebox — App Design Document
**Version:** 1.0
**Status:** Draft
**Last Updated:** 2026-06-19
---
## Overview
MyKindlebox is a self-hosted rabbitry management web application. It replaces the existing Kindlebox PHP app at `belowland.com/rabbitsite` with a modern, responsive React/Node stack while preserving all the core domain knowledge baked into the original — particularly the genetics system and pedigree-aware entry flow.
The defining improvement over the current site: **adding a new rabbit starts from a pedigree template, not a blank form.** The pedigree tree is the primary data entry surface.
---
## Goals
- Make herd entry fast — one rabbit in under 60 seconds for known bloodlines
- Maintain the full genetics model (A/B/C/D/E/En/V loci)
- Track litters, kits, weights, ages, and sale status in one place
- Mobile-friendly for barn use (phone in hand, cage in front of you)
- Self-hostable with a simple Docker or Node+SQLite setup
---
## Out of Scope (v1)
- Multi-user/multi-rabbitry support
- Public-facing listing pages
- Show tracking (planned for a future release)
- Payments or invoicing
---
## Tech Stack
| Layer | Choice | Notes |
|---|---|---|
| Frontend | React + Vite | PWA-ready |
| Routing | React Router v7 | |
| State | Zustand + React Query | Local UI state + server sync |
| Styling | Tailwind CSS | Custom theme tokens |
| Backend | Node.js + Express | REST API |
| Database | SQLite (via Drizzle ORM) | Single-file DB, easy backup |
| Auth | Single-user session token | Self-hosted, no OAuth complexity |
| Hosting | Docker Compose | Nginx + Node + SQLite volume |
---
## Visual Design
### Design Direction
The palette pulls from the working barn — weathered cedar, hay, and deep forest green. Not the typical dark-green-navbar rabbitry website, but a warm neutral base with earthy sage accents and a muted amber highlight. Typography pairs **DM Sans** (headings, data labels) with **Inter** (body, forms) — legible at small sizes and clean on mobile.
The signature element: the **pedigree entry tree** rendered as an actual interactive branching diagram, not a flat form. It should feel like filling out a paper pedigree slip, but faster.
### Color Tokens
| Token | Hex | Usage |
|---|---|---|
| `--surface` | `#F7F3EC` | Page background |
| `--surface-raised` | `#FFFFFF` | Cards, modals |
| `--surface-sunken` | `#EDE8DE` | Input backgrounds, zebra rows |
| `--border` | `#D4C9B4` | Dividers, input borders |
| `--text-primary` | `#1C1A16` | Body text |
| `--text-secondary` | `#6B6354` | Labels, secondary info |
| `--accent` | `#4A6741` | Primary actions (sage green) |
| `--accent-hover` | `#3A5233` | Button hover |
| `--accent-warm` | `#C47D2E` | Highlights, status badges |
| `--danger` | `#B34040` | Delete, warnings |
### Typography Scale
```
Display: DM Sans, 700, 28px / 32px
Heading: DM Sans, 600, 20px / 24px
Subhead: DM Sans, 500, 15px / 20px
Body: Inter, 400, 14px / 21px
Label: Inter, 500, 12px / 16px, uppercase, 0.05em tracking
Data: Inter, 400 / 600, 13px / 18px (tabular nums)
```
---
## Information Architecture
```
/ Dashboard
/herd Herd view (all / bucks / does / other / kits)
/herd/:id Rabbit detail page
/herd/add Add rabbit (pedigree-first form)
/herd/:id/edit Edit rabbit
/litters Litter list
/litters/:id Litter detail (kit list)
/litters/add Record a new litter
/genetics Genetics calculator
/settings App settings (rabbitry name, backup/restore)
```
---
## Navigation
Persistent left sidebar on desktop (240px), bottom nav bar on mobile (5 tabs).
**Sidebar items:**
- Dashboard
- Herd *(with sub-filter: All / Bucks / Does / Kits / Other)*
- Litters
- Genetics Calculator
- Settings
**Mobile bottom nav:** Dashboard · Herd · Litters · Add · Settings
The **Add** tab in mobile nav opens the Rabbit entry flow directly — primary action is always one tap away.
---
## Pages & Components
### Dashboard
Replaces the current dashboard's plain link grid with a live stats bar + action surface.
**Stats bar (top):**
```
┌─────────────┬─────────────┬─────────────┬─────────────┐
│ Herd 14 │ Bucks 7 │ Does 7 │ Kits 20 │
├─────────────┼─────────────┼─────────────┼─────────────┤
│ For Sale 21 │ On Hold 0 │ Sold 69 │ Others 586 │
└─────────────┴─────────────┴─────────────┴─────────────┘
```
Each stat card is a link to the corresponding filtered herd view.
**Quick actions:**
- Add Rabbit
- Record Litter
- View Recent Activity (last 5 added/modified)
**Recent litters widget:** shows the 3 most recent litters with kit count, date, and sire/dam names.
---
### Herd View (`/herd`)
Filterable grid/list of rabbits. Default: card grid, 2-col mobile / 3-col tablet / 4-col desktop.
**Rabbit Card:**
```
┌────────────────────────────┐
│ [photo or breed silhouette]│
│ Jim Bean │
│ Broken Black Tort • Buck │
│ 5y 2m • 3.09 lbs │
│ 6 litters • 18 kits │
└────────────────────────────┘
```
**Filters (top bar):** Gender tabs (All / Bucks / Does / Kits / Other) + sort (Name / Age / Recent / Weight) + search input.
**List view toggle:** compact table view with name, color, sex, age, weight, litter count. Better for large herds.
---
### Rabbit Detail (`/herd/:id`)
Two-column layout on desktop, stacked on mobile.
**Left column:**
- Photo (upload or breed silhouette placeholder)
- Core stats: name, farm, sex, DOB, age, weight, ear number, location
- Registration / GC numbers
- Color with genetics breakdown (loci pills)
- Status badge: Active / For Sale / On Hold / Sold / Deceased
**Right column:**
- Pedigree tree (full 4-generation visual — root + 3 ancestor generations, 15 nodes — read-only, each ancestor with a DB record is a clickable link)
- Litter history table (for bucks and does — all litters they appear in)
**Action bar:** Edit · Add Litter · Mark For Sale · Archive
---
### Add / Edit Rabbit (`/herd/add`, `/herd/:id/edit`)
**This is the core differentiator.** The entry form is organized as a pedigree tree first.
#### Entry Flow
**Step 1 — Pedigree Template**
The user sees a 4-generation pedigree tree with empty nodes (root + 3 ancestor generations: parents, grandparents, great-grandparents). Each node is an inline autocomplete input. Typing searches existing rabbits in the DB and lets you select one, which auto-fills that branch.
```
┌─ Sire's Sire's Sire
┌─ Sire's Sire ─┤
│ └─ Sire's Sire's Dam
┌─ Sire ────┤
│ │ ┌─ Sire's Dam's Sire
│ └─ Sire's Dam ──┤
│ └─ Sire's Dam's Dam
[New Rabbit]─┤
│ ┌─ Dam's Sire's Sire
│ ┌─ Dam's Sire ──┤
│ │ └─ Dam's Sire's Dam
└─ Dam ─────┤
│ ┌─ Dam's Dam's Sire
└─ Dam's Dam ───┤
└─ Dam's Dam's Dam
```
- Selecting an existing rabbit for Sire auto-fills their sire/dam into the next generation if known.
- "Other" and "Unknown" remain as options, just like the original site.
- Clicking any empty ancestor node offers: **Search existing** · **Enter manually** · **Unknown**
**Step 2 — Rabbit Details**
Once the pedigree is set (or skipped), a standard form collects:
| Field | Input Type | Notes |
|---|---|---|
| Name | Text | Required |
| Farm / Prefix | Text | Pre-filled from settings default |
| Sex | Segmented control | Buck / Doe / Unknown |
| Date of Birth | Date picker | |
| Weight | Number + unit toggle (lbs/oz or kg) | |
| Ear Number | Text | |
| Location | Text / select | Cage/hutch label |
| Status | Select | Active / For Sale / On Hold / Sold |
| Color Name | Text | e.g. "Broken Black Tort" |
| Photo | File upload | Optional |
**Step 3 — Genetics**
Collapsible section. Renders the same A/B/C/D/E/En/V loci selectors from the original, but as a clean pill-group toggle UI instead of a dropdown list.
```
A Locus [AA Agouti] [aᵗa Tan] [aa Self]
B Locus [BB] [bb]
…
```
The selected loci auto-generate a color description string (read-only) that can be used as the color field suggestion.
**Step 4 — Review & Save**
Summary card showing all entered data before commit. One "Save Rabbit" button.
---
### Litter List (`/litters`)
Replaces the plain HTML table with a filterable card list.
**Litter Card:**
```
┌──────────────────────────────┐
│ Ragnar × Venus │
│ May 16, 2025 • 1 kit │
│ [View Kits] [Edit] │
└──────────────────────────────┘
```
Filters: year, sire, dam, kit count range. Sort by date (default desc).
---
### Litter Detail (`/litters/:id`)
- Sire + Dam links at top (with ages at time of litter)
- Kindle date, expected wean date, actual wean date
- Kit table: each kit row links to its full Rabbit record — name, sex, color, ear number, status, weight
- "Add Kit" button opens the Add Rabbit flow with sire, dam, and DOB pre-filled from the litter
---
### Genetics Calculator (`/genetics`)
Same functionality as the existing calculator. Modernized as an interactive two-panel form:
- Left: Parent A genotype selectors
- Right: Parent B genotype selectors
- Center: Offspring probability table (live-updating as you change inputs)
---
## Data Models
### Rabbit
```typescript
{
id: number
name: string
farm: string | null
sex: 'buck' | 'doe' | 'unknown'
dob: string | null // ISO date
weight_lbs: number | null
ear_number: string | null
location: string | null
status: 'active' | 'for_sale' | 'on_hold' | 'sold' | 'deceased' | 'other'
color_name: string | null
photo_path: string | null
registration_number: string | null
gc_number: string | null
sire_id: number | null // FK → Rabbit
dam_id: number | null // FK → Rabbit
// Genetics loci
locus_a: string | null // 'AA' | 'aᵗa' | 'aa'
locus_b: string | null
locus_c: string | null
locus_d: string | null
locus_e: string | null
locus_en: string | null
locus_v: string | null
created_at: string
updated_at: string
}
```
### Litter
```typescript
{
id: number
sire_id: number | null // FK → Rabbit
dam_id: number | null // FK → Rabbit
kindle_date: string // ISO date
kit_count: number
notes: string | null
created_at: string
}
```
> Kits are standard Rabbit records linked back to their litter via `sire_id` / `dam_id`. No separate Kit table. The Litter detail page queries all Rabbit records whose sire/dam match the litter's parents and whose DOB matches the kindle date.
---
## Key UX Decisions
### Pedigree-first entry over blank forms
The original site's Add Rabbit form is a flat list of fields. Connecting a rabbit to its lineage is an afterthought. In MyKindlebox, the pedigree tree *is* the form. This mirrors how breeders actually think about a new animal — always in the context of its parents.
### Inline ancestor lookup with graceful fallback
The pedigree tree nodes use an autocomplete that searches the existing rabbit DB. If the ancestor isn't in the system (bought-in or historical), users can type freeform text for the ancestor's name and it stores as a text reference rather than a FK. This avoids blocking entry on having complete records.
### Genetics section is collapsible and optional
Not every breeder uses the full loci system. The genetics section defaults to collapsed on add; open on edit for rabbits that already have genetics data.
### Weight in lb+oz or decimal lbs
The original uses decimal lbs. The app will support both entry modes (3 lbs 2 oz or 3.13 lbs) because breeders use both on show tables.
### Rabbit status drives herd counts
The Dashboard stat cards ("For Sale", "On Hold", etc.) are driven entirely by the `status` field on the Rabbit record. Changing status anywhere instantly updates the counts.
---
## Future Considerations (v2+)
- **Show tracking** — log ARBA show entries and placements per rabbit; mobile-optimized for live entry at shows
- **Health log** — vet visits, treatments, notes per rabbit
- **Breeding calendar** — planned breeding dates, expected kindle dates, reminders
- **Export** — CSV export of herd, printable pedigree PDF generation
- **Photo gallery** — multiple photos per rabbit, breed standard comparison overlay
- **Public herd page** — optional read-only share link for buyers browsing available rabbits
---
## Resolved Decisions
1. **Kit records** — Kits are created as full Rabbit records immediately when added to a litter. No separate "kit row" stage; every kit is a first-class herd entry from birth.
2. **Genetics calculator pairings** — Session-only. Pairings are not persisted to the DB.
3. **Weight storage** — Stored internally as a decimal float in lbs. Display and entry format (decimal lbs vs lb+oz) is controlled by a user setting in the app and converted on read/write.
4. **Backup/restore** — Manual export button in Settings. Exports a JSON or SQLite snapshot; no scheduled automation.