5be8da96f26f51e19a3d28ece9de82952df6176f
All checks were successful
Deploy / deploy (push) Successful in 2m39s
When HTMX boosted forms submit via POST, the browser URL wasn't being
updated correctly. This caused window.location.reload() after event
deletion to reload the action URL (e.g., /actions/feed-given) instead
of the display URL (e.g., /feed), resulting in a 405 Method Not Allowed.
The fix adds a render_page_post() helper that returns FT components
with an HttpHeader("HX-Push-Url", push_url). This tells HTMX to update
the browser history to the correct URL after successful form submission.
Updated routes:
- /actions/feed-given -> push /feed
- /actions/feed-purchased -> push /feed
- /actions/product-collected -> push /
- /actions/product-sold -> push /
- /actions/animal-move -> push /move
- /actions/animal-cohort -> push /actions/cohort
- /actions/hatch-recorded -> push /actions/hatch
- /actions/animal-tag-add -> push /actions/tag-add
- /actions/animal-tag-end -> push /actions/tag-end
- /actions/animal-attrs -> push /actions/attrs
- /actions/animal-outcome -> push /actions/outcome
- /actions/animal-status-correct -> push /actions/status-correct
🤖 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%