Files
agentbox-test/AGENTS.md
T
agentbox 2cd435daf2
CI / test-and-package (push) Successful in 36s
Add cron container and per-household timezone for auto-reminders
- docker-compose.yml: meal-cron service loops send_reminders_cron.py every 60s
- send_reminders_cron.py: checks each household's local time, sends ntfy
  reminders at 10:00 (lunch) and 16:00 (dinner), guarded against duplicates
- models.py: timezone, last_lunch_reminder, last_dinner_reminder on households
- meals.py: /admin/timezone route for admins to set household timezone
- dashboard: timezone selector (20 common zones) in Account Settings
- i18n: 5 new translation keys for timezone strings
- Dockerfile: copy send_reminders_cron.py
- tests: 4 new timezone tests (admin set, non-admin denied, default UTC, auth)
- docs: updated AGENTS.md
2026-08-01 06:23:33 +00:00

4.6 KiB

AGENTS.md — Meal Tracker

Overview

Flask web app for tracking household meal attendance. Users register into households, then mark yes/no for lunch & dinner each day. A dashboard shows all members' responses. SQLite backend, Docker deployment behind Caddy reverse proxy.

  • Repo: https://gitea.ct.cozytren.ch/romane/agentbox-test
  • Production: https://meals.ct.cozytren.ch
  • Auto-deploy: watch-for-updates.sh polls for new commits every 20s, rebuilds via docker compose, redeploys. Push-to-deploy in ~1 min.

Files — What Goes Where

File Role
app.py Flask factory (create_app()), registers blueprints and i18n
auth.py Auth blueprint: /login, /register, /logout. Session-based.
meals.py Meals blueprint: /dashboard, /respond, /history, /delete-account, /admin/*, /ntfy-settings, /ntfy-test, /api/ntfy-callback
models.py All DB access. SQLite via sqlite3. 4 tables: households, users, meal_periods, responses. Ntfy helpers in # Ntfy / notifications section.
i18n.py Translation module. t(key) helper for en/fr/de. Detects Accept-Language, session override via ?lang=. All user-visible strings flow through t().
ntfy.py Ntfy notification helpers. send_meal_reminder() sends push with Home/Out HTTP action buttons. send_test_notification() verifies config.
templates/ Jinja2: base.html (nav, lang footer), login.html, register.html, dashboard.html
static/style.css All CSS (no framework)
tests/ Pytest suite (47 tests): conftest.py sets up in-memory DB per test
Dockerfile Python 3.13-alpine. Must list every .py file in the COPY line.
docker-compose.yml Two services: meal-tracker (web) and meal-cron (sends reminders). Both on external caddy network, shared meal-data volume at /data.
watch-for-updates.sh Polls git remote, rebuilds on change. Uses docker compose with env vars from .env.
send_reminders_cron.py Standalone script run every 60s by the meal-cron container. Checks per-household local time against 10:00/16:00 triggers.
doc/index.md Full project documentation
README.md Symlink → doc/index.md

Key Conventions

  • Blueprints: auth_bp and meals_bp registered in app.py. Decorator @login_required on protected routes.
  • Session keys: user_id, username, is_admin, household_id, household_name, lang.
  • i18n: Every user-visible string in templates uses {{ t('English text') }}. In Python, flash(t("message"), "category"). Translations live in TRANSLATIONS dict in i18n.py. English string is the key; only non-English translations stored. When adding new user-facing text, add it to TRANSLATIONS for fr/de.
  • DB: All access through get_db() context manager in models.py. Returns sqlite3.Row objects accessed as dicts. Path via DB_PATH env var (defaults to /data/meals.db in Docker, ./meals.db locally).
  • CSS: No framework. Variables in :root. Use existing utility classes (.btn, .chip, .badge, etc.).
  • Ntfy: Per-user topic URL + Bearer token stored in users table. Callback token auto-generated on first ntfy setup. /api/ntfy-callback is unauthenticated (uses callback token). Send reminders via flask send-reminders [--date] [--meal] [--base-url]. Schedule with cron.

Common Pitfalls

  1. Dockerfile COPY must include every .py file. If you add a new Python module, add it to the COPY line. Missing files cause ModuleNotFoundError → container crash → 502.
  2. meal_type values are lowercase (lunch, dinner) in DB/forms. Templates capitalize them for display: period.meal_type|capitalize.
  3. Past dates are read-only. The respond route rejects dates before today. Dashboard shows badges instead of buttons for other users' rows.
  4. changed_at logic: Set only when flipping between yesno. First answer and not_answered transitions leave it NULL.
  5. Response status values: yes, no, not_answered (stored in DB; CSS classes and display strings derived from these).

Running Locally (no Docker)

pip install -r requirements.txt
python app.py          # or: flask --app 'app:create_app()' run --debug
pytest tests/ -v

Running with Docker

docker compose up -d --build    # needs caddy network
# or standalone:
docker build -t meal-tracker .
docker run -p 5000:5000 meal-tracker

Adding a New Language

  1. Add the language code and name to LANGUAGES in i18n.py.
  2. Add translations for every key in TRANSLATIONS (keys are the English strings).
  3. Add the language to the footer loop in templates/base.html.