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

14 KiB
Raw Blame History

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

{
  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

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