Type a new name in the Category or Subcategory dropdown and pick "Add '...'" at the bottom. Custom categories persist (stored as strings on the item) and reappear merged into future dropdowns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moon Base
Property management for the Moon homestead (Eau Claire, WI). A single place to track the food forest, household inventory, and recurring upkeep — built as a Next.js 14 + Prisma + Postgres app, deployed self-hosted on the home NAS.
Live at http://192.168.0.5:8053.
Modules
- Garden — plant registry with care/harvest/observation logs, plant groups, reusable plant types (the "kind" record: care notes, sun/water, bloom & harvest months, pet toxicity), Wikipedia photos, and plants placed on the shared location tree.
- Inventory — durable items that nest (a toolbox holds the tools inside it), with labels, photos + manuals/receipts/warranty docs, value & warranty tracking (with expiry warnings), serial/brand, a sold record, and custom fields (e.g. a vehicle's VIN). Schedule recurring maintenance per item. Import straight from HomeBox via CSV. Shares the same location spine as the garden.
- Animals — pets & livestock with their own logs (feeding, vet, weight, meds) and auto-computed age, placed on the shared location tree; reminders can be linked to an animal.
- Locations — manage the whole place tree (areas, buildings, rooms, storage), nested as deep as you like; everything (plants, items, animals) lives here.
- Reminders — one-off or recurring tasks (every N days / monthly / yearly), optionally linked to a plant, item, or animal.
- REST API (
/api/v1/*) — personal access tokens with per-scope permissions (read plants, log harvests, …) for phone shortcuts, Home Assistant, and automation. - Suggestions — in-app feedback that files issues to Gitea (
@otm/account-panel). - Backup & Restore — download/restore the whole dataset as a zip (admin only).
- Self-update — admins get a "Pull & rebuild" button that updates the running app to the latest pushed version (see Deploy).
Tech
Next.js 14 (App Router) · Prisma · PostgreSQL · NextAuth (credentials) · Tailwind + shadcn/ui · Docker Compose.
Local dev
npm install
cp .env.example .env # fill in DATABASE_URL + NEXTAUTH_SECRET
npx prisma migrate deploy # schema + provisions bonna/tony accounts
npm run db:seed # optional demo data (SEED_MODE=minimal for accounts only)
npm run dev # http://localhost:3000
After schema edits: npx prisma generate then restart. Data backfills for the
location/plant-type refactors: npm run db:backfill-locations,
npm run db:backfill-plant-types.
Auth / first run
Username or email login. Provisioned accounts bonna / tony (role ADMIN)
ship with the default password moonbase! and mustChangePassword=true — the app
forces a password change on first sign-in.
Deploy
The NAS appdata (/mnt/user/appdata/moonbase) is a git checkout of this repo.
Two ways to ship a change:
- In-app (admins): Settings → Updates → Pull & rebuild. A privileged
updatersidecar runsgit pull && docker compose up -d --build appand the UI reloads on the new version. - Manual:
git push origin master ssh root@192.168.0.5 'cd /mnt/user/appdata/moonbase && git pull && docker compose up -d --build'
Do not rsync over the appdata dir — it would fight the checkout. Secrets
(NEXTAUTH_SECRET, GITEA_TOKEN, UPDATER_SECRET) live in a gitignored host
.env next to the compose file, never committed. Migrations apply automatically
on container start. Full deploy walkthrough: docs/git-deploy-guide.md.
Conventions
Every commit bumps APP_VERSION (src/lib/version.ts) + a plain-English entry in
src/lib/changelog.ts (written for Bonna, shown in the footer). AuditEvent on
every mutation. Soft-delete via active=false. Pure logic in src/lib/* with
colocated tests; API routes stay thin. Repo on Gitea: bonna61/Moonbase.