Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| client | ||
| server | ||
| README.md | ||
| docker-compose.yml | ||
README.md
MyKindlebox
A self-hosted rabbitry (rabbit breeding herd) management web app — track your rabbits, their pedigrees, litters, and genetics. Self-hosted, with simple user accounts sharing one herd, and designed to replace a legacy PHP herd-management site.
The core differentiator: adding a rabbit starts from a pedigree tree, not a blank form. The 3-generation ancestor tree (sire/dam and their sires/dams) is the primary data-entry surface, with inline autocomplete against your existing herd and graceful fallback to freeform text for bought-in or unknown ancestors.
Features
- Pedigree-first rabbit entry — build the ancestor tree first, then fill in details; unknown ancestors can be stored as plain text so entry is never blocked by missing records.
- Herd management — name, sex, DOB, weight, and status
(
active/for_sale/on_hold/sold/deceased/other). - Litters — record kindle dates and kit counts; the kit list is derived live from Rabbit records (no separate Kit table).
- Genetics — per-rabbit loci (
A/B/C/D/E/En/V) and a session-only pairing calculator for predicting offspring. - Dashboard — herd counts derived live from rabbit status.
- Pedigree printing, CSV import/export, and a configurable weight display (decimal lbs or lb + oz).
- PWA-ready with a mobile bottom nav, installable on phones/tablets.
Tech stack
| Layer | Choice |
|---|---|
| Frontend | React 19 + Vite (PWA-ready) |
| Routing | React Router v7 |
| State | React Query (server sync) |
| Styling | Tailwind CSS |
| Backend | Node.js + Express 5 (REST API) |
| Database | SQLite via Drizzle ORM (single-file DB) |
| Auth | User accounts, shared herd (scrypt + DB sessions) |
| Hosting | Docker Compose (Nginx + Node + SQLite volume) |
Project layout
mykindlebox/
├── client/ React + Vite frontend
├── server/ Express + SQLite/Drizzle API
└── docker-compose.yml Production stack (nginx + node + volume)
Development
Run the backend and frontend in two terminals.
Backend (server/):
cd server
npm install
npm run dev # API on http://localhost:3001 (tsx watch, hot reload)
Other scripts: npm run build (typecheck + compile to dist/),
npm start (run compiled server), npm test.
Frontend (client/):
cd client
npm install
npm run dev # Vite dev server on http://localhost:5173
The dev server proxies /api and /uploads to localhost:3001. Other
scripts: npm run build, npm run lint, npm test.
The client talks to the API over relative URLs (
/api,/uploads) so the app works over LAN and as an installed PWA — never hardcode a host.
Deployment (Docker Compose)
From the mykindlebox/ directory:
docker compose up --build
The app is served on http://localhost:8080 — nginx serves the built client
and reverse-proxies /api + /uploads to the Node server. The SQLite database
and uploaded photos live in the server-data Docker volume.
To serve on a different host port, set MYKINDLEBOX_PORT (e.g. in a .env file
next to docker-compose.yml):
MYKINDLEBOX_PORT=3000
Then re-run docker compose up -d — the app is served on that port instead of
8080. (Only the host side changes; inside the compose network nginx still
listens on 80.)
Updating an existing deployment
Compose builds from whatever is checked out on the host, so pull first, then rebuild. Run from the repo root on the server:
# 1. Back up the database (schema migrations run automatically on startup)
cd mykindlebox
docker compose cp server:/app/data ./data-backup-$(date +%F)
# 2. Pull the latest code
cd ..
git checkout main
git pull
git log --oneline -1 # confirm you're on the commit you expect
# 3. Rebuild and restart both services
cd mykindlebox
docker compose up --build -d
Verify both containers were recreated:
docker compose ps
Both client and server should show a recent CREATED time (seconds or
minutes ago), and server should reach (healthy) within ~15 seconds. If
either still shows an old CREATED time, Compose reused a cached image — force
it:
docker compose build --no-cache server # or client
docker compose up -d --force-recreate server
The client and server must be from the same version; a new client against an
old server will fail on login and newer pages. If the server never becomes
healthy, check docker compose logs server --tail 50.
Finally, hard-refresh the browser (Ctrl+Shift+R). On an installed phone PWA,
fully close and reopen the app to pick up the new build. Once everything looks
right, the data-backup-* folder can be deleted.
Authentication
The app uses user accounts — everyone shares the same herd; accounts are separate logins with their own theme and weight-display preference. On first launch the app shows a one-time create your account screen; add more people later under Settings → Users. Passwords are hashed (scrypt) and sessions last 30 days, surviving server restarts.
Upgrading from the password-only version? The old
MYKINDLEBOX_PASSWORDenv var is no longer used — remove it from your.env. On your next visit you'll see the one-time account-creation screen; your herd data is untouched.
Data & backups
The herd database (server/data/), uploaded photos, and .env files are
gitignored — they are never committed. In production they persist in the
server-data volume; back that volume up to preserve your data. A quick
snapshot from a running stack:
docker compose cp server:/app/data ./data-backup-$(date +%F)