Unifies the new LangGraph-driven course-plan/media flow with robust provider fallbacks, admin AI provider settings, editable book-style materials, and strict entity isolation across LMS/course-plan APIs. Adds admin-only entity membership management in the Entities UI so users can switch linked entities directly from the platform. Made-with: Cursor
EnCoach — Adaptive AI Learning Platform
EnCoach is a smart learning environment for individual and collaborative learning, fully integrated with AI and equipped with intelligent, professional-grade exercises, assessments, and e-exams.
This repository hosts the full stack:
- Backend — Odoo 19 + ~30
encoach_*modules (Python 3.12, PostgreSQL 16) - Frontend — React 18 + Vite + TypeScript single-page app
- AI layer — OpenAI + pgvector RAG, quality-gate validation, IELTS validator
- Ops — Docker Compose, JWT auth with refresh tokens, Prometheus-compatible metrics, dynamic OpenAPI 3.0 spec
Canonical trees:
backend/(all server code) andfrontend/(all client code). The legacynew_project/directory is deprecated — seenew_project/DEPRECATED.md.
1. Quickstart
Docker (recommended)
docker compose up -d
# Odoo: http://localhost:8069
# Frontend: cd frontend && npm install && npm run dev (http://localhost:8080)
Create a new Odoo database on first visit, then install the encoach_api
module to pull in every encoach_* dependency.
Source
Prerequisites: Python 3.12, PostgreSQL 16, Node 20, npm 10.
# Backend
./setup.sh # creates venv, installs requirements.txt
./run.sh # starts Odoo on :8069
# Frontend
cd frontend
npm install
npm run dev # starts Vite on :8080, proxies /api → :8069
See MANUAL-RUN.md for a step-by-step walkthrough and
CONNECT-POSTGRES.md for database wiring.
2. Repository layout
odoo19/
├── backend/
│ └── custom_addons/
│ ├── encoach_api/ REST base + JWT + OpenAPI + metrics
│ ├── encoach_core/ Users, entities, roles, permissions
│ ├── encoach_taxonomy/ Subject → Domain → Topic
│ ├── encoach_ai/ OpenAI wrapper, cefr_mapper, validator
│ ├── encoach_ai_course/ AI course/exam generation pipelines
│ ├── encoach_ai_grading/ AI grading (writing/speaking/math/IT)
│ ├── encoach_ai_media/ TTS (Polly), STT (Whisper), ELAI
│ ├── encoach_vector/ pgvector store + RAG embeddings
│ ├── encoach_exam_template/ Canonical exam + student attempt models
│ ├── encoach_scoring/ Score computation, CEFR mapping
│ ├── encoach_quality_gate/ Automated content-quality checks
│ ├── encoach_ielts_validation/ IELTS-specific validators
│ ├── encoach_adaptive/ Adaptive engine, style matcher
│ ├── encoach_lms_api/ OpenEduCat bridge + LMS endpoints
│ ├── encoach_branding/ White-label config per entity
│ └── … (other encoach_* modules)
├── frontend/
│ ├── src/
│ │ ├── pages/ Route pages (React.lazy code-split)
│ │ ├── components/ Shared UI (shadcn/ui + custom)
│ │ ├── services/ Thin API wrappers over fetch
│ │ ├── hooks/queries/ React Query hooks + keys
│ │ ├── lib/api-client.ts Fetch + auto JWT refresh
│ │ └── types/ Shared DTO types
│ └── vite.config.ts manualChunks: react, query, charts, radix…
├── docs/
│ ├── PROJECT_SUMMARY.md Release notes & architecture history
│ ├── adr/ Architecture Decision Records
│ └── ENCOACH_*.md SRS, workflows, user stories
├── docker-compose.yml
├── Dockerfile
├── requirements.txt Python deps (pgvector, textstat, etc.)
└── README.md You are here
3. Architecture at a glance
┌────────────────────┐ HTTPS/JWT ┌────────────────────┐
│ React SPA (Vite) │ ───────────────► │ Odoo 19 + FastAPI-style │
│ - React Query │ ◄─────────────── │ controllers (encoach_*) │
│ - next-themes │ X-Request-Id └──────┬─────────────┘
│ - shadcn/ui │ │
└────────────────────┘ ▼
┌──────────────┐
│ PostgreSQL │
│ + pgvector │
└──────┬───────┘
│
▼
┌──────────────┐
│ OpenAI, │
│ Whisper, │
│ Polly… │
└──────────────┘
Every request carries an X-Request-Id and emits structured JSON logs.
Prometheus-compatible counters are exposed at /api/metrics, and the live
OpenAPI 3.0 spec is at /api/openapi.json.
4. Key conventions
- Canonical response envelope — list endpoints return
{ items: T[], total, page, size, data: T[] }(seeencoach_api.controllers.base.paginated_envelope). - CEFR mapping — only
encoach_ai.services.cefr_mapperis canonical. Do not reintroduce localband_to_cefrcopies. - JWT tokens — short-lived access tokens (1h) + revocable refresh tokens
(7d). Only
accesstokens are accepted as Bearer credentials; refresh tokens must go through/api/auth/refresh. Seedocs/adr/0002-jwt-refresh-token-flow.md. - RAG metadata — vector embeddings carry
course_id,subject_id,entity_id,taxonomy,content_hash. Chunking kicks in above 2 000 chars. - Frontend pagination —
PaginatedResponse<T>exposes bothitemsanddata. Read fromitemsin new code. - Frontend theming — tokens live in
frontend/src/index.css(:rootand.dark). Always usehsl(var(--token))instead of raw hex.
5. Health, observability, docs
| Endpoint | Purpose |
|---|---|
GET /api/health |
Liveness (always 200 when server is up) |
GET /api/health/ready |
Readiness (DB + required config) |
GET /api/openapi.json |
Dynamic OpenAPI 3.0 spec generated from @http.route |
GET /api/metrics |
Prometheus-format counters per route |
6. Deployment
Staging and production both use Docker Compose. The staging server rebuilds
automatically from main; never force-push. See
INSTALL-ODOO-SUMMARY.md for bootstrap notes.
| Service | Staging URL |
|---|---|
| Odoo backend | http://5.189.151.117:8069 |
| React frontend | http://5.189.151.117:3000 |
The .env file is never committed. On staging it lives at
/opt/encoach/backend-v2/.env.
7. Further reading
| Document | Description |
|---|---|
docs/PROJECT_SUMMARY.md |
Release notes + architecture history |
docs/adr/ |
Architecture Decision Records (why we built it this way) |
docs/ENCOACH_UNIFIED_SRS.md |
Unified frontend + backend SRS |
docs/ENCOACH_ODOO19_BACKEND_SRS.md |
Backend SRS v3.0 |
docs/ENCOACH_WORKFLOWS_BACKEND_SRS.md |
Backend workflows |
docs/ENCOACH_WORKFLOWS_FRONTEND_SRS.md |
Frontend workflows |
8. Contributing
- Branch from
main— never push direct. Branch protection enforces it. - Run
npx tsc --noEmit -p tsconfig.app.json(frontend) and the module smoke tests before opening a PR. - Every architectural decision should be captured as an ADR under
docs/adr/. Copy0000-template.mdto start one. - Open the PR against
mainand request review from devops (Talal).