Skip to content

Repository files navigation

puffin 🐦

A lightweight baby tracking dashboard for the early days. Track feedings, diapers, and health with a simple, mobile-first interface.

Self-hosted, no accounts, no cloud — just a single SQLite database.

Screenshots

Dashboard Feeding Timer Log Feeding Log Diaper
Dashboard & timeline Live feeding timer Log a feeding Log a diaper change

Features

  • Diaper Tracking — Log pee/poop/both with quick-tap buttons
  • Feeding Tracking — Breast (L/R) and bottle with amount in oz
  • Breastfeeding Timer — Live timer with breast switching, persists across page refreshes, two-step end confirmation
  • Medication & Temperature — Log meds with dosage, temps with F↔C conversion
  • Dashboard — Today's summary, last activity timestamps, 3-day activity timeline
  • Edit & Delete — Tap any timeline entry to edit or remove it
  • Light/Dark Mode — Follows system preference with manual toggle
  • Data Export — CSV and JSON export of all records
  • Mobile-First — Large touch targets, one-handed operation
  • API Docs — Interactive OpenAPI docs at /docs

Docker

Puffin is published as a container image on GitHub Container Registry.

docker run -d \
  --name puffin \
  -p 8000:8000 \
  -v puffin-data:/data \
  -e TZ=America/New_York \
  ghcr.io/pid1/puffin:latest

Then open http://localhost:8000.

Volumes

  • /data — SQLite database (puffin.db). Mount this to persist data across container restarts.

Environment Variables

  • PUFFIN_DB_PATH — Path to the SQLite database file (default: /data/puffin.db). Normally you don't need to change this.
  • TZ — IANA timezone name (e.g. America/New_York) used to decide where one day ends and the next begins (default: UTC). Set this to your local timezone. Without it, an evening log west of UTC is counted as tomorrow — a diaper logged at 21:10 US Central lands on the next UTC day, so it won't show up in today's dashboard counts or timeline until midnight UTC. An unrecognized value falls back to UTC.
  • PUFFIN_BACKUP_KEEP — How many database snapshots to retain per backup (default: 10). Set to 0 to keep every snapshot.

Backups

All your data is a single SQLite file, so there are two safety nets:

  • Automatic pre-migration snapshots. On every startup, before any schema migration runs, the database is copied to <db-dir>/backups/ (i.e. /data/backups in Docker). Migrations rewrite tables in place, so this gives you a rollback point for the one operation most likely to damage data. Old snapshots are pruned to PUFFIN_BACKUP_KEEP.

  • On-demand backups. Run backup (in devenv shell) or python -m puffin.backup to snapshot on demand. Wire it to cron or a systemd timer for regular copies, e.g. a daily line in the container host's crontab:

    0 3 * * * docker exec puffin python -m puffin.backup

To restore, stop the app and copy the chosen backups/*.db file back over puffin.db.

Off-box copies: these snapshots live on the same disk/volume as the database, so they protect against bad migrations and logical corruption but not against losing the disk. For disaster protection, periodically copy backups/ elsewhere, or replicate the database off-box with a tool like Litestream.

Development

Prerequisites

Getting Started

# Enter development environment
devenv shell

# Initialize (install dependencies)
setup

# Start development server
dev

Then open http://localhost:8000.

Available Commands

Run these commands inside devenv shell:

  • setup — Initialize the repo (install deps)
  • dev — Start FastAPI dev server (port 8000)
  • lint — Run ruff linter
  • lint-fix — Run ruff linter with auto-fix
  • format — Run ruff formatter
  • test — Run all tests (Python + JS)
  • seed — Generate 14 days of realistic demo data
  • backup — Snapshot the database into <db-dir>/backups

See AGENTS.md for the complete command reference including background/agent-friendly variants.

Tech Stack

  • Backend: Python 3.13 / FastAPI / SQLAlchemy / SQLite
  • Frontend: Vanilla HTML/CSS/JS
  • Dev Environment: Nix + devenv
  • Package Manager: uv
  • Linter/Formatter: ruff
  • Tests: pytest with httpx TestClient

License

BSD 3-Clause. See LICENSE.

About

A lightweight baby tracking dashboard for the early days. Track feedings, diapers, and health with a simple, mobile-first interface.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages