66d404efbcab5af84d32a18c127afade56e2b08b
All checks were successful
Deploy / deploy (push) Successful in 2m38s
- Add CSS for all form fields (input, textarea, select) in dark mode with -webkit-text-fill-color for iOS Safari compatibility - Add padding-bottom to event detail panel so delete button is visible above bottom nav on mobile - Display notes field in ProductCollected and ProductSold event details 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
AnimalTrack
Event-sourced animal tracking for poultry farm management. Built with FastHTML, MonsterUI, and SQLite.
Features
- Egg Collection - Quick capture of daily egg counts by location
- Feed Tracking - Record purchases and distribution with cost tracking
- Animal Registry - Track cohorts, movements, and lifecycle events
- Historical Queries - Point-in-time resolution using interval projections
- Event Sourcing - Full audit trail with edit/delete support
Development Setup
Prerequisites
Quick Start
# Clone the repo
git clone <repo-url>
cd animaltrack
# Enter dev environment
direnv allow # or: nix develop
# Run the server
animaltrack serve
The server starts at http://localhost:3366 (3366 = EGG in leetspeak).
CLI Commands
# Run database migrations
animaltrack migrate
# Load seed data (users, locations, species, products, feed types)
animaltrack seed
# Start the web server
animaltrack serve [--port 3366] [--host 0.0.0.0]
# Create a new migration
animaltrack create-migration "add users table"
Running Tests
pytest tests/ -v
Deployment
Docker
Build the Docker image using Nix:
nix build .#dockerImage
docker load < result
Run the container:
docker run -d \
-p 8080:3366 \
-v /data/animaltrack:/var/lib/animaltrack \
-e CSRF_SECRET="your-secret-here" \
-e TRUSTED_PROXY_IPS="10.0.0.1,10.0.0.2" \
gitea.v.paler.net/ppetru/animaltrack:latest
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
CSRF_SECRET |
Yes | - | Secret for CSRF token generation |
DB_PATH |
No | animaltrack.db |
SQLite database path |
PORT |
No | 3366 |
Server port |
AUTH_HEADER_NAME |
No | X-Oidc-Username |
Header containing username from reverse proxy |
TRUSTED_PROXY_IPS |
No | (empty) | Comma-separated IPs that can set auth headers |
CSRF_COOKIE_NAME |
No | csrf_token |
CSRF cookie name |
SEED_ON_START |
No | false |
Run seeds on startup |
LOG_LEVEL |
No | INFO |
Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
METRICS_ENABLED |
No | true |
Enable Prometheus metrics at /metrics |
DEV_MODE |
No | false |
Bypasses auth, sets default user for development |
BASE_PATH |
No | / |
URL base path for reverse proxy setups |
Reverse Proxy Configuration
AnimalTrack expects authentication to be handled by a reverse proxy (e.g., Authelia, Authentik, oauth2-proxy). The proxy should:
- Authenticate users via OIDC/OAuth2
- Forward the username in
X-Oidc-Usernameheader (configurable viaAUTH_HEADER_NAME) - Be listed in
TRUSTED_PROXY_IPSto be trusted
Example Caddy configuration:
animaltrack.example.com {
forward_auth authelia:9091 {
uri /api/verify?rd=https://auth.example.com
copy_headers Remote-User Remote-Groups Remote-Email
header_up X-Oidc-Username {http.auth.resp.Remote-User}
}
reverse_proxy animaltrack:3366
}
Data Persistence
Mount a volume to /var/lib/animaltrack for the SQLite database:
-v /path/on/host:/var/lib/animaltrack
The database file will be created at $DB_PATH (default: /var/lib/animaltrack/animaltrack.db in Docker).
Health Check
GET /healthz- Returns 200 if database is writable, 503 otherwiseGET /metrics- Prometheus metrics (whenMETRICS_ENABLED=true)
Architecture
- Event Sourcing - All state changes are events. Events are immutable.
- Projections - Materialized views updated synchronously in transactions.
- Interval Tables - Track animal locations, tags, and attributes over time.
- ULID IDs - Time-ordered, sortable, unique identifiers.
- Integer Timestamps - Milliseconds since Unix epoch for all timestamps.
- Integer Money - All prices stored as cents for precision.
License
Proprietary - All rights reserved.
Description
Languages
Python
99.3%
Nix
0.6%
JavaScript
0.1%