7.1 KiB
PROJECT BABY MONITOR
OVERVIEW
Baby monitor - self-hosted web app for tracking infant sleep. Dual-stack monorepo: React 19/Vite 6/TypeScript frontend + Python 3.14/FastAPI backend. Optimized for Raspberry Pi 4 (ARM64).
STRUCTURE
./
├── frontend/ # React 19 SPA
│ ├── src/
│ │ ├── api/ # React Query hooks
│ │ ├── components/
│ │ │ ├── stats/ # Charts, grids, trends (8 files - highest density)
│ │ │ └── tracker/ # Sleep session controls
│ │ ├── hooks/ # Custom React hooks
│ │ ├── types/ # TypeScript interfaces
│ │ └── utils/
│ └── tests/ # e2e (Playwright), unit (Vitest)
├── backend/ # FastAPI + SQLModel
│ ├── scripts/ # one-off scripts for migrations / fixes / etc
│ ├── app/
│ │ ├── routers/ # API endpoints
│ │ └── utils/
│ └── tests/ # pytest + asyncio
└── docker-compose.yml
WHERE TO LOOK
| Task | Location | Notes |
|---|---|---|
| Add sleep session | backend/app/crud.py |
create_session, update_session |
| Fetch sleep data | frontend/src/api/ |
React Query hooks for sessions |
| UI components | frontend/src/components/ |
tracker/, stats/ subdirs |
| Backend models | backend/app/models.py |
SQLModel definitions |
| API schemas | backend/app/schemas.py |
Pydantic request/response |
| Settings / env vars | backend/app/config.py |
Pydantic-settings, reads .env |
| Database init | backend/app/database.py |
Engine setup, init_db() |
| Timezone logic | backend/app/utils/time_utils.py |
Historical bug source — handle with care |
CONVENTIONS
- Backend: SQLModel (not pure SQLAlchemy), async aiosqlite, pytest-asyncio.
- Frontend: React 19, TanStack Query v5, Tailwind v4, no ESLint config (yet).
- Python: >=3.14 required. Managed via
uvwith Hatch backend for packaging. - Scripts: All scripts created in the backend folder must be placed explicitly in
backend/scripts/. - CI/CD: Deployment is managed via Gitea workflows (
.gitea/directory). Do not create.github/directories or Makefiles.
ANTI-PATTERNS (CRITICAL GUARDRAILS)
- Type Safety: No type suppression (
as any,@ts-ignore,@ts-expect-error). Type safety is strictly enforced. - Error Handling: No empty catch blocks. Explicit error handling/logging is required.
- Testing Integrity: NEVER delete or comment out failing tests to make a suite "pass". Fix the code or update the test properly.
- Frontend JS Slop: NEVER create
.jsor.jsxfiles for the frontend. Use only TypeScript (.ts,.tsx). Write clean, type-safe code. - Assumption Error: NEVER assume the content of ANY files. ALWAYS read the target file to confirm its structure and implementation before modifying or referencing it.
MANDATORY EXECUTION PROTOCOLS (INJECTABLE)
The following protocols must be strictly adhered to upon injection:
- Read Before Edit: ALWAYS read the entire target file before performing any
editoperation. - Post-Edit Verification: Immediately after an edit, verify that no lines have been duplicated.
- Stability Check: Following any code change, run both backend and frontend services AND the full test suite to ensure system stability.
COMMANDS
Backend Development
cd backend
uv sync
uv run uvicorn app.main:app --reload # runs on http://localhost:8000
# Run all tests
uv run pytest
# Run a specific test file (preferred during debugging)
uv run pytest tests/test_stats.py -v
Frontend Development
cd frontend
npm install
npm run dev # runs on http://localhost:5173
# Unit tests (Vitest)
npm run test
# Unit + e2e tests (Vitest + Playwright)
npm run test:all
# Lint
npm run lint
Docker (production-like, ARM64)
# Full stack — frontend served on http://localhost:8080
docker compose up --build
ENVIRONMENT VARIABLES
Backend reads from backend/.env (optional — all have defaults):
| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
sqlite+aiosqlite:///./data/sleep.db |
SQLite DB path |
CORS_ORIGINS |
http://localhost:5173 |
Allowed CORS origins (comma-separated) |
LOG_LEVEL |
info |
Uvicorn log level |
In Docker the DB is persisted via a bind-mount at ./backend/data/.
🛑 DIRECTORY NAVIGATION & FILE DISCOVERY
Context: This is a full-stack monorepo containing massive generated/dependency folders (node_modules, dist, venv, .venv, __pycache__, etc.). Unrestricted file listings will bloat your context window, crash your session, and cause severe token waste.
- NEVER use
ls -R: This command is strictly forbidden in this repository. - NEVER use
findwithout-maxdepth: Unboundedfindcrawls dependency trees just likels -R. Always add-maxdepth 3or tighter. - Primary Discovery: To map out files or explore the project tree, ALWAYS use
git ls-files. This is your default command and ensures you only interact with human-written source code. - Structural Context: If you explicitly need a visual directory layout to understand architecture, use
treeappended with the mandatory ignore flags:
tree -I 'node_modules|.git|dist|build|__pycache__|venv|.venv|env|.pytest_cache|.mypy_cache|.ruff_cache|*.egg-info'
- Searching Code: If you need to search for text or code blocks across the repo, ALWAYS use
git grep "search_term"instead of standardgrep -rto avoid crawling ignored or minified assets.
🧠 TASK DELEGATION & CONTEXT PRESERVATION
Context: The main OpenCode agent context window is our most critical resource. Executing complex tasks, debugging cross-file issues, or writing massive features directly in the main thread causes severe context bloat, leading to code hallucinations and dropped instructions.
- Delegate Aggressively: For any complex implementation, structural change, or task larger than a single file edit, you MUST invoke a subagent via the Task tool. Act strictly as the architectural orchestrator; let subagents handle the iterative coding labor.
- Scope Narrowly: Give subagents highly specific, isolated, and atomic objectives (e.g., "Read
backend/app/routers/auth.pyand summarize endpoints" or "Write a unit test for the frontend sleep tracker component"). - Strict Summarization: Subagents are STRICTLY FORBIDDEN from passing raw terminal dumps, unedited file blocks, or their internal step-by-step logs back to the main thread.
- Return Format: Subagents must return only clear, actionable results back to the orchestrator: a concise summary of findings, the exact lines of code that require modification, or direct confirmation of a successful execution.
NOTES
- Entry Points:
frontend/src/main.tsx(Frontend) &backend/app/main.py(Backend). - Database: Local SQLite managed via
aiosqlitefor an entirely async-first data layer. - Target Architecture: Built specifically for ARM64 deployment on a Raspberry Pi 4 via Docker.