# AGENTS.md Family chore/reward manager. Flask + TinyDB backend (`backend/`), Vue 3 + TypeScript frontend (`frontend/`). Real-time updates over SSE. ## Commands ### Backend (run from `backend/`) - Activate venv: `source .venv/bin/activate` - Dev server: `python -m flask run --host=0.0.0.0 --port=5000` (entry: `main.py`) - Required env vars: `SECRET_KEY`, `REFRESH_TOKEN_EXPIRY_DAYS`, `DIGEST_TOKEN_SECRET`, `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY` — Flask raises `RuntimeError` on boot if any are missing - Optional: `DB_ENV` / `DATA_ENV` (`prod` | `test` | `e2e`) — picks `data/` vs `test_data/` dir (see `config/paths.py`) - Tests: `pytest tests/` — `conftest.py` forces `DB_ENV=test` and sets dummy secrets. Single test: `pytest tests/test_routine_api.py::test_name` - Python imports assume `backend/` is on `sys.path` (set by `conftest.py` / `flask run` cwd). Run pytest from `backend/`. - Create admin user: `python scripts/create_admin.py` (admin role cannot be set via signup) ### Frontend (run from `frontend/`) - Dev: `npm run dev` (Vite, https://localhost:5173) - Lint: `npm run lint` - Type-check: `npm run type-check` - Unit tests: `npm run test:unit` (Vitest). Single: `npx vitest run path/to/file.spec.ts` - E2E: `npx playwright test` — config auto-starts both `npm run dev` and the Flask backend with `DB_ENV=e2e DATA_ENV=e2e`. Tests live in `e2e/`. - E2E buckets are Playwright projects (see `playwright.config.ts`) targeting directories under `e2e/mode_parent/` ## Architecture ### API routing — the `/api` prefix - Frontend nginx (and Vite dev proxy) strips `/api` before forwarding. **Backend routes must NOT include `/api`.** Backend defines `@app.route('/user')`, frontend calls `/api/user`. - `auth_api` is the only blueprint registered with a prefix: `url_prefix='/auth'` in `main.py:67`. - API errors return `{ error, code }` (codes in `backend/api/error_codes.py`). Frontend extracts them via `parseErrorResponse(res)` in `src/common/api.ts`. ### Models — strict 1:1 parity - Python `@dataclass`es in `backend/models/`. TypeScript interfaces in `frontend/src/common/models.ts`. Any model change requires updating both. - Persistence is TinyDB via the thread-safe `LockedTable` wrapper (`backend/db/db.py`). Operate on model instances with `from_dict()` / `to_dict()` — never raw dicts. ### SSE event bus — mandatory for every mutation - Every backend mutation (add/edit/delete/trigger) **must** call `send_event_for_current_user` from `api/utils.py`. Event types in `backend/events/types/` are mirrored in `frontend/src/common/backendEvents.ts`. - Frontend: register listeners in `onMounted`, clean up in `onUnmounted`. SSE endpoint is `/events`. ### Background schedulers (started in `main.py` at boot) - `start_deletion_scheduler` — runs hourly, deletes accounts marked for deletion after threshold - `start_digest_scheduler` — email digests - `start_state_expiry_scheduler` — expires stale state - `start_chore_expiry_notification_scheduler` — chore expiry notifications ## Frontend conventions - SFC file order: `