Add hard-to-guess public URLs (/public/<token>) that show a read-only
meal status dashboard for each household. Only people with the link can
see the data — no login required.
- models.py: public_token + public_enabled columns on households,
get_household_by_public_token(), generate_public_token(),
set_public_enabled()
- meals.py: /public/<token> route, /admin/public-link for
generate/disable/enable/regenerate
- templates/public.html: clean read-only public dashboard
- templates/public-not-found.html: 404 for invalid/disabled links
- templates/dashboard.html: admin UI with copy/regenerate/disable
- static/style.css: public page and URL box styles
- i18n.py: 18 new translation keys (en/fr/de)
- models.py: ORDER BY CASE so lunch always appears before dinner in the
dashboard table (was alphabetical, putting dinner first).
- style.css: add @media (max-width: 600px) with mobile-friendly layout:
stacked navbar, full-width dashboard header, reduced padding/margins,
larger touch targets for chips/buttons, stacked manage forms, and
compact table cells.
The auto-login route needs these fields to populate the session, but the
query only selected id, username, household_id. Added JOIN with
households table and selected is_admin + household_name.
- meal-cron now runs send_reminders_cron.sh (simple wget loop, no DB mount)
- New /api/cron-tick endpoint handles all timezone logic server-side
- base_url captured from request.host_url when user saves ntfy settings,
stored per-user — no APP_BASE_URL env var needed
- Cron endpoint protected by CRON_SECRET shared env var
- Removed send_reminders_cron.py, DB volume from cron container
- tests: 3 new cron-tick + base_url capture tests (69 total)
- 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