System Architecture¶
High-Level Overview¶
LinguaAI follows a modular monolith pattern on the backend, with a Flutter cross-platform frontend communicating via REST and WebSocket connections.
┌──────────────────────────────────────────────────────────────────┐
│ Flutter Client │
│ (iOS / Android / Web) │
│ │
│ AuthService ──► REST (HTTP/S) ──────────────────────────────┐ │
│ OCR Service (on-device) │ │
│ WebSocket client ──► wss://... ────────────────────────────┐ │ │
└────────────────────────────────────────────────────────────-─┼-┼──┘
│ │
┌────────────────────────▼-▼──┐
│ FastAPI Backend │
│ │
│ /api/auth/* (auth module) │
│ /api/dictionary/* (dictionary) │
│ /api/flashcards/* (flashcards) │
│ /api/gamification/* (gamification)│
│ /api/lessons/* (lessons) │
│ /api/users/* (users) │
│ /api/learn/* (planned) │
│ /ws/speak (planned) │
│ │
│ core/security.py │
│ core/database.py │
└──────────────┬───────────────┘
│
┌──────────────▼───────────────┐
│ Supabase │
│ │
│ auth.users (managed) │
│ public.profiles │
│ public.field_specific │
└──────────────────────────────┘
Backend Architecture¶
The backend is a FastAPI modular monolith — all feature modules live in a
single process but are physically separated into their own directories under
app/modules/.
Application Entry Point (app/main.py)¶
Instantiates the FastAPI application with a title, description, and version.
Adds
CORSMiddlewarepermitting all origins (tighten in production).Registers all feature routers under the
/apiprefix.Exposes:
GET /— Servesindex.html(root welcome page).GET /health— Database connectivity health check.
Core Layer (app/core/)¶
File |
Responsibility |
|---|---|
|
Reads |
|
Creates a single global |
|
|
|
Rotating file handler (5 MB, 3 backups) + console handler.
All modules use |
Module Layer (app/modules/)¶
Each module is self-contained and follows the same internal structure:
modules/<feature>/
├── __init__.py
├── router.py # FastAPI APIRouter with route definitions
├── service.py # Business logic (static/class methods)
├── schemas.py # Pydantic request/response models and enums
└── models.py # ORM-like dataclasses + repository pattern
Key patterns:
Protected routes use
Depends(get_current_user)fromcore/security.py.The Supabase client is imported from
core/database.py— one instance, shared.Routes are
async; tests useasyncio_mode = strict.Business logic lives entirely in
service.py; routers are thin.
Authentication Flow¶
Email / Password¶
Client FastAPI Supabase Auth
│ │ │
│ POST /api/auth/signup │ │
│────────────────────────►│ │
│ │ auth.sign_up() │
│ │──────────────────────────►│
│ │◄──────────────────────────│
│ │ upsert profiles row │
│ │ create_access_token() │
│◄────────────────────────│ │
│ TokenResponse (JWT) │ │
Google OAuth — Web¶
Client FastAPI Google / Supabase
│ │ │
│ POST /api/auth/google/url │
│────────────────────────►│ supabase.auth.get_url() │
│ │──────────────────────────►│
│◄────────────────────────│ { url } │
│ redirect browser │ │
│──────────────────────────────────────────────────►│
│◄──────────────────────────────────────────────────│ code
│ POST /api/auth/google/callback (code) │
│────────────────────────►│ exchange_code() │
│ │──────────────────────────►│
│◄────────────────────────│ TokenResponse │
Google OAuth — Mobile (Native)¶
Flutter FastAPI Google
│ │ │
│ google_sign_in SDK ───────────────────────────► │
│◄─────────────────────────────── id_token ─────────│
│ POST /api/auth/google/token (id_token) │
│────────────────────────►│ sign_in_with_id_token() │
│◄────────────────────────│ TokenResponse │
Token Lifecycle¶
JWT tokens use HS256 and expire after 24 hours (1440 minutes).
The client stores the access token and refresh token in
SharedPreferences.POST /api/auth/refreshexchanges a refresh token for a new access token.POST /api/auth/logoutinvalidates the session on the Supabase side.
Real-time Pronunciation Scoring (Planned)¶
The speaking module will expose a WebSocket endpoint that:
Accepts a WebSocket connection authenticated by a query-parameter JWT.
Receives binary audio chunks streamed from the Flutter client.
Passes chunks to a Whisper (ASR) model for transcription.
Computes phoneme-level pronunciation scores via a HuggingFace model.
Streams JSON score payloads back to the client in real time.
Security Considerations¶
Concern |
Mitigation |
|---|---|
Password storage |
bcrypt with salt; plain-text passwords never persisted. |
Token signing |
HS256 JWT; secret must be at least 32 random characters. |
Database access |
Supabase Row Level Security (RLS) restricts reads/writes per user. |
Service role key |
Only used server-side; never sent to the Flutter client. |
CORS |
Currently |
Logging |
Tokens and passwords are never written to log files. |