386 lines
14 KiB
Markdown
386 lines
14 KiB
Markdown
# 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.
|