# teerin27/subtitle-cefr-recommender-movie architecture

> Architecture diagram of the GitHub repository teerin27/subtitle-cefr-recommender-movie, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/teerin27/subtitle-cefr-recommender-movie
- Repository: https://github.com/teerin27/subtitle-cefr-recommender-movie

## Overview

CEFR Cinema is intended to recommend movies suited to an English learner’s proficiency: analyze subtitle difficulty, generate collaborative-filtering candidates, then rerank for level fit and explain recommendations. The checked-in runtime is still a walking skeleton: the web page calls a hello endpoint, and the API exposes that endpoint plus health. The README documents the broader ML workflow, but its modeling and recommendation implementation is not present in the sampled source; those links are documented product flow, not verified runtime calls.

Main entry points: [`api/app/routers/hello.py`](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/routers/hello.py) (Hello endpoint), [`ml`](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml) (Level-aware reranking), [`api/app/main.py`](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/main.py) (App factory), [`web/app/page.tsx`](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/app/page.tsx) (Home page)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web interface"]
  node_home["Home page<br/>[page.tsx]"]
  node_api_client["API client<br/>[api.ts]"]
  node_web_contract["Web contract<br/>[types.ts]"]
end

subgraph group_api["API service"]
  node_app_factory["App factory<br/>[main.py]"]
  node_settings["Runtime settings<br/>[config.py]"]
  node_hello_route["Hello endpoint<br/>[hello.py]"]
  node_hello_schema["Hello response<br/>[hello.py]"]
  node_health_route["Health endpoint<br/>[health.py]"]
  node_health_schema["Health response<br/>[health.py]"]
end

subgraph group_data["Data ingestion"]
  node_movie_data[("MovieLens data")]
  node_subtitle_data[("Subtitle data")]
  node_download["Corpus download<br/>[download.py]"]
  node_subtitle_index["Subtitle indexing"]
end

subgraph group_recommendations["Recommendation workflow"]
  node_difficulty["Difficulty analysis"]
  node_candidate_generation["Candidate generation"]
  node_reranking["Level-aware reranking"]
  node_explanations["Recommendation reasons"]
end

node_learner(("Learner"))

node_learner -->|"uses"| node_home
node_home -->|"calls"| node_api_client
node_api_client -->|"requests"| node_hello_route
node_app_factory -->|"loads"| node_settings
node_app_factory -->|"registers"| node_hello_route
node_app_factory -->|"registers"| node_health_route
node_hello_route -->|"reads"| node_settings
node_hello_route -->|"returns"| node_hello_schema
node_health_route -->|"returns"| node_health_schema
node_movie_data -.->|"provides ratings"| node_candidate_generation
node_subtitle_data -.->|"provides subtitles"| node_difficulty
node_download -.->|"acquires corpus"| node_subtitle_data
node_subtitle_index -.->|"prepares subtitles"| node_difficulty
node_difficulty -.->|"supplies level"| node_reranking
node_candidate_generation -.->|"supplies candidates"| node_reranking
node_reranking -.->|"supports reasons"| node_explanations
node_reranking -.->|"returns recommendations"| node_home

click node_home "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/app/page.tsx"
click node_api_client "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/lib/api.ts"
click node_web_contract "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/lib/types.ts"
click node_app_factory "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/main.py"
click node_settings "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/config.py"
click node_hello_route "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/routers/hello.py"
click node_hello_schema "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/schemas/hello.py"
click node_health_route "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/routers/health.py"
click node_health_schema "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/schemas/health.py"
click node_movie_data "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/data/raw/movielens"
click node_subtitle_data "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/data/raw/opensubtitles"
click node_download "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/ml/ingestion/download.py"
click node_subtitle_index "https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/ml/ingestion/opensubtitles_index.py"
click node_difficulty "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml"
click node_candidate_generation "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml"
click node_reranking "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml"
click node_explanations "https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml"

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_home,node_api_client,node_web_contract toneBlue
class node_app_factory,node_settings,node_hello_route,node_hello_schema,node_health_route,node_health_schema toneAmber
class node_movie_data,node_subtitle_data,node_download,node_subtitle_index toneMint
class node_difficulty,node_candidate_generation,node_reranking,node_explanations toneRose
class node_learner toneIndigo
```

## Components

### Web interface

- [Home page](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/app/page.tsx): `web/app/page.tsx`
- [API client](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/lib/api.ts): `web/lib/api.ts`
- [Web contract](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/web/lib/types.ts): `web/lib/types.ts`

### API service

- [App factory](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/main.py): `api/app/main.py`
- [Runtime settings](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/config.py): `api/app/config.py`
- [Hello endpoint](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/routers/hello.py): `api/app/routers/hello.py`
- [Hello response](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/schemas/hello.py): `api/app/schemas/hello.py`
- [Health endpoint](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/routers/health.py): `api/app/routers/health.py`
- [Health response](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/api/app/schemas/health.py): `api/app/schemas/health.py`

### Data ingestion

- [MovieLens data](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/data/raw/movielens): `data/raw/movielens`
- [Subtitle data](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/data/raw/opensubtitles): `data/raw/opensubtitles`
- [Corpus download](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/ml/ingestion/download.py): `ml/ingestion/download.py`
- [Subtitle indexing](https://github.com/teerin27/subtitle-cefr-recommender-movie/blob/main/ml/ingestion/opensubtitles_index.py): `ml/ingestion/opensubtitles_index.py`

### Recommendation workflow

- [Difficulty analysis](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml): `ml`
- [Candidate generation](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml): `ml`
- [Level-aware reranking](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml): `ml`
- [Recommendation reasons](https://github.com/teerin27/subtitle-cefr-recommender-movie/tree/main/ml): `ml`

### Other components

- **Learner**

## Connections

- Learner → Home page: uses (evidence: `web/app/page.tsx`)
- Home page → API client: calls (evidence: `web/app/page.tsx`)
- API client → Hello endpoint: requests (evidence: `web/lib/api.ts`)
- App factory → Runtime settings: loads (evidence: `api/app/main.py`)
- App factory → Hello endpoint: registers (evidence: `api/app/main.py`)
- App factory → Health endpoint: registers (evidence: `api/app/main.py`)
- Hello endpoint → Runtime settings: reads (evidence: `api/app/routers/hello.py`)
- Hello endpoint → Hello response: returns (evidence: `api/app/routers/hello.py`)
- Health endpoint → Health response: returns (evidence: `api/app/routers/health.py`)
- MovieLens data → Candidate generation: provides ratings (evidence: `README.md`)
- Subtitle data → Difficulty analysis: provides subtitles (evidence: `README.md`)
- Corpus download → Subtitle data: acquires corpus
- Subtitle indexing → Difficulty analysis: prepares subtitles
- Difficulty analysis → Level-aware reranking: supplies level (evidence: `README.md`)
- Candidate generation → Level-aware reranking: supplies candidates (evidence: `README.md`)
- Level-aware reranking → Recommendation reasons: supports reasons (evidence: `README.md`)
- Level-aware reranking → Home page: returns recommendations (evidence: `README.md`)
