Live ESP32-CAM video feed, student photo enrollment, timetable-driven automatic attendance marking (with manual override), and a live people-count — see appwrite-setup.md for provisioning the backing Appwrite project, and docs/ESP32_CAM_INTEGRATION.md for hardware wiring/flashing and the firmware↔backend HTTP contract.
- Backend: FastAPI on Appwrite Cloud — Databases for records, Storage for images, Auth for identity. Face recognition runs in-process via InsightFace (ArcFace embeddings), matched by cosine distance against each session's class roster.
- Frontend: React + TypeScript + Vite + Tailwind CSS.
- Firmware:
firmware/CameraWebServer/— Arduino sketch for the AI-Thinker ESP32-CAM (live MJPEG stream + periodic capture upload).
- Python 3.11+
- Node.js 20+ / npm
- An Appwrite Cloud project (free tier is enough)
- Arduino IDE + ESP32 board package (for flashing the camera)
cd backend
python -m venv .venv
./.venv/Scripts/activate # Windows
pip install -r requirements.txtCopy the root .env.example to .env (repo root, one level above
backend/) and fill in your Appwrite endpoint, project ID, database ID, API
key, and seed admin credentials. Then create the schema and the first admin:
python -m scripts.provision_appwrite
python -m app.seed_adminBoth are safe to re-run. See appwrite-setup.md for what they create and the permissions they apply.
Run the API:
python -m uvicorn app.main:app --reload --port 8000Visit http://localhost:8000/api/health to confirm it's up, and
http://localhost:8000/docs for the full REST surface.
cd frontend
npm install
npm run devVisit http://localhost:5173.
Follow docs/ESP32_CAM_INTEGRATION.md start to finish — wiring, flashing, registering the device in the admin panel, and the exact HTTP contract the firmware uses.
- The browser talks to Appwrite two ways: some admin pages read and write
collections directly with the JS SDK (
frontend/src/lib/db.ts), and the rest go through the FastAPI REST API. Requests to FastAPI carry a short-lived Appwrite JWT so the backend can enforce admin/teacher roles. - Roles live in Appwrite user labels (
admin/teacher), not in a collection. - Appwrite has no joins, aggregates, or cascading deletes. Reports fetch and
aggregate in Python (
app/api/routes/attendance.py), and parent deletes clear their children explicitly (app/services/cascade.py).
- This is a prototype pipeline: no liveness detection (a printed photo can be recognized), and plaintext HTTP is fine on a trusted LAN but needs TLS before any wider exposure. See docs/ESP32_CAM_INTEGRATION.md §9 for the full list.
- Enrollment photos and capture frames are biometric data. They live in a
private Appwrite Storage bucket; the
student_photosandface_embeddingscollections are server-only and never readable from the browser.