# chutungduongg/ielts_self_practising_web architecture

> Architecture diagram of the GitHub repository chutungduongg/ielts_self_practising_web, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/chutungduongg/ielts_self_practising_web
- Repository: https://github.com/chutungduongg/ielts_self_practising_web

## Overview

BandPilot is an IELTS practice and classroom platform. Learners choose a skill or full mock, complete timed attempts, and review results; teachers assign frozen test versions and inspect assignment-scoped results. Separate AI workflows provide advisory writing and speaking feedback. The README documents these capabilities, while excerpts show API routing, application startup, and speaking worker behavior. Several UI-to-API and unsampled feature links are therefore omitted rather than inferred.

Main entry points: [`backend/app/api/v1/router.py`](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/router.py) (API router), [`backend/app/main.py`](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/main.py) (FastAPI runtime), [`frontend/src/features/practice/skill-practice.tsx`](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/practice/skill-practice.tsx) (Practice workflows), [`backend/app/services/speaking_ai_worker.py`](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/speaking_ai_worker.py) (Speaking AI scoring)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_practice["Practice and Review"]
  node_web["Web application"]
  node_practice_ui["Practice workflows<br/>[skill-practice.tsx]"]
  node_reading_ui["Reading runner<br/>[reading-runner.tsx]"]
  node_listening_ui["Listening runner"]
  node_speaking_ui["Speaking runner"]
  node_writing_review["Writing review<br/>[writing-review.tsx]"]
  node_attempt_api["Attempt lifecycle API<br/>[attempts.py]"]
  node_attempt_service["Attempt management<br/>[attempts.py]"]
  node_reading_api["Reading API<br/>[reading.py]"]
  node_speaking_api["Speaking API<br/>[speaking.py]"]
  node_writing_api["Writing API<br/>[writing.py]"]
  node_history_analytics["History and analytics<br/>[analytics.py]"]
end

subgraph group_classroom["Classrooms and Governance"]
  node_classroom_ui["Classroom workflows"]
  node_classroom_api["Classroom APIs"]
  node_governance_api["Content governance"]
  node_transfer_api["Test transfer<br/>[transfer.py]"]
end

subgraph group_assessment["AI Assessment"]
  node_writing_ai["Writing AI assessment"]
  node_speaking_transcript["Speaking transcription"]
  node_speaking_ai["Speaking AI scoring"]
  node_asr_provider["Speaking ASR provider<br/>[modal.py]"]
  node_modal_services["Modal AI services<br/>[app.py]"]
end

subgraph group_platform["Application Platform"]
  node_api_router["API router<br/>[router.py]"]
  node_app_runtime["FastAPI runtime<br/>[main.py]"]
  node_database[("PostgreSQL<br/>[database.py]")]
  node_asset_storage["Asset storage<br/>[factory.py]"]
end

node_learner(("Learner"))
node_teacher(("Teacher"))
node_admin(("Administrator"))

node_learner -->|"uses"| node_web
node_teacher -->|"uses"| node_web
node_admin -->|"uses"| node_web
node_learner -->|"starts practice"| node_practice_ui
node_practice_ui -.->|"selects skill"| node_reading_ui
node_practice_ui -.->|"selects skill"| node_listening_ui
node_practice_ui -.->|"selects skill"| node_speaking_ui
node_learner -->|"reviews writing"| node_writing_review
node_api_router -->|"registers"| node_attempt_api
node_api_router -->|"registers"| node_reading_api
node_api_router -->|"registers"| node_speaking_api
node_api_router -->|"registers"| node_writing_api
node_api_router -->|"registers"| node_classroom_api
node_api_router -->|"registers"| node_governance_api
node_api_router -->|"registers"| node_transfer_api
node_app_runtime -->|"mounts"| node_api_router
node_attempt_api -->|"delegates"| node_attempt_service
node_app_runtime -->|"recovers worker"| node_speaking_transcript
node_app_runtime -->|"recovers worker"| node_speaking_ai
node_app_runtime -->|"initializes"| node_asset_storage
node_speaking_transcript -->|"requests transcription"| node_asr_provider
node_speaking_ai -->|"uses transcript"| node_speaking_transcript
node_speaking_ai -.->|"uses model service"| node_modal_services
node_writing_ai -.->|"uses model service"| node_modal_services
node_teacher -->|"manages classes"| node_classroom_ui
node_classroom_ui -.->|"uses classroom APIs"| node_classroom_api
node_admin -->|"reviews content"| node_governance_api
node_database -->|"provides sessions"| node_app_runtime
node_learner -->|"tracks progress"| node_history_analytics

click node_web "https://github.com/chutungduongg/ielts_self_practising_web/tree/main/frontend/src/app"
click node_practice_ui "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/practice/skill-practice.tsx"
click node_reading_ui "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/reading/reading-runner.tsx"
click node_listening_ui "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/listening/listening-runner.tsx"
click node_speaking_ui "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/speaking/speaking-runner.tsx"
click node_writing_review "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/writing/writing-review.tsx"
click node_attempt_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/attempts.py"
click node_attempt_service "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/attempts.py"
click node_reading_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/reading.py"
click node_speaking_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/speaking.py"
click node_writing_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/writing.py"
click node_history_analytics "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/analytics.py"
click node_classroom_ui "https://github.com/chutungduongg/ielts_self_practising_web/tree/main/frontend/src/features/classrooms"
click node_classroom_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/classroom_assignments.py"
click node_governance_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/content_governance.py"
click node_transfer_api "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/transfer.py"
click node_writing_ai "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/writing_ai_worker.py"
click node_speaking_transcript "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/speaking_transcript_worker.py"
click node_speaking_ai "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/speaking_ai_worker.py"
click node_asr_provider "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/providers/speaking_asr/modal.py"
click node_api_router "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/router.py"
click node_app_runtime "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/main.py"
click node_database "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/core/database.py"
click node_asset_storage "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/storage/factory.py"
click node_modal_services "https://github.com/chutungduongg/ielts_self_practising_web/blob/main/deploy/modal/app.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web,node_practice_ui,node_reading_ui,node_listening_ui,node_speaking_ui,node_writing_review,node_attempt_api,node_attempt_service,node_reading_api,node_speaking_api,node_writing_api,node_history_analytics toneBlue
class node_classroom_ui,node_classroom_api,node_governance_api,node_transfer_api toneAmber
class node_writing_ai,node_speaking_transcript,node_speaking_ai,node_asr_provider,node_modal_services toneMint
class node_api_router,node_app_runtime,node_database,node_asset_storage toneRose
class node_learner,node_teacher,node_admin toneIndigo
```

## Components

### Practice and Review

- [Web application](https://github.com/chutungduongg/ielts_self_practising_web/tree/main/frontend/src/app): `frontend/src/app`
- [Practice workflows](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/practice/skill-practice.tsx): `frontend/src/features/practice/skill-practice.tsx`
- [Reading runner](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/reading/reading-runner.tsx): `frontend/src/features/reading/reading-runner.tsx`
- [Listening runner](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/listening/listening-runner.tsx): `frontend/src/features/listening/listening-runner.tsx`
- [Speaking runner](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/speaking/speaking-runner.tsx): `frontend/src/features/speaking/speaking-runner.tsx`
- [Writing review](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/frontend/src/features/writing/writing-review.tsx): `frontend/src/features/writing/writing-review.tsx`
- [Attempt lifecycle API](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/attempts.py): `backend/app/api/v1/attempts.py`
- [Attempt management](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/attempts.py): `backend/app/services/attempts.py`
- [Reading API](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/reading.py): `backend/app/api/v1/reading.py`
- [Speaking API](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/speaking.py): `backend/app/api/v1/speaking.py`
- [Writing API](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/writing.py): `backend/app/api/v1/writing.py`
- [History and analytics](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/analytics.py): `backend/app/api/v1/analytics.py`

### Classrooms and Governance

- [Classroom workflows](https://github.com/chutungduongg/ielts_self_practising_web/tree/main/frontend/src/features/classrooms): `frontend/src/features/classrooms`
- [Classroom APIs](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/classroom_assignments.py): `backend/app/api/v1/classroom_assignments.py`
- [Content governance](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/content_governance.py): `backend/app/api/v1/content_governance.py`
- [Test transfer](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/transfer.py): `backend/app/api/v1/transfer.py`

### AI Assessment

- [Writing AI assessment](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/writing_ai_worker.py): `backend/app/services/writing_ai_worker.py`
- [Speaking transcription](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/speaking_transcript_worker.py): `backend/app/services/speaking_transcript_worker.py`
- [Speaking AI scoring](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/services/speaking_ai_worker.py): `backend/app/services/speaking_ai_worker.py`
- [Speaking ASR provider](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/providers/speaking_asr/modal.py): `backend/app/providers/speaking_asr/modal.py`
- [Modal AI services](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/deploy/modal/app.py): `deploy/modal/app.py`

### Application Platform

- [API router](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/api/v1/router.py): `backend/app/api/v1/router.py`
- [FastAPI runtime](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/main.py): `backend/app/main.py`
- [PostgreSQL](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/core/database.py): `backend/app/core/database.py`
- [Asset storage](https://github.com/chutungduongg/ielts_self_practising_web/blob/main/backend/app/storage/factory.py): `backend/app/storage/factory.py`

### Other components

- **Learner**
- **Teacher**
- **Administrator**

## Connections

- Learner → Web application: uses
- Teacher → Web application: uses
- Administrator → Web application: uses
- Learner → Practice workflows: starts practice
- Practice workflows → Reading runner: selects skill
- Practice workflows → Listening runner: selects skill
- Practice workflows → Speaking runner: selects skill
- Learner → Writing review: reviews writing
- API router → Attempt lifecycle API: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Reading API: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Speaking API: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Writing API: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Classroom APIs: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Content governance: registers (evidence: `backend/app/api/v1/router.py`)
- API router → Test transfer: registers (evidence: `backend/app/api/v1/router.py`)
- FastAPI runtime → API router: mounts (evidence: `backend/app/main.py`)
- Attempt lifecycle API → Attempt management: delegates (evidence: `backend/app/api/v1/attempts.py`)
- FastAPI runtime → Speaking transcription: recovers worker (evidence: `backend/app/main.py`)
- FastAPI runtime → Speaking AI scoring: recovers worker (evidence: `backend/app/main.py`)
- FastAPI runtime → Asset storage: initializes (evidence: `backend/app/main.py`)
- Speaking transcription → Speaking ASR provider: requests transcription (evidence: `backend/app/services/speaking_transcript_worker.py`)
- Speaking AI scoring → Speaking transcription: uses transcript (evidence: `backend/app/services/speaking_ai_worker.py`)
- Speaking AI scoring → Modal AI services: uses model service
- Writing AI assessment → Modal AI services: uses model service
- Teacher → Classroom workflows: manages classes
- Classroom workflows → Classroom APIs: uses classroom APIs
- Administrator → Content governance: reviews content
- PostgreSQL → FastAPI runtime: provides sessions (evidence: `backend/app/core/database.py`)
- Learner → History and analytics: tracks progress
