# titanaprilian/private-movie architecture

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

- Interactive diagram: https://gitdiagram.com/titanaprilian/private-movie
- Repository: https://github.com/titanaprilian/private-movie

## Overview

Private Movie is a self-hosted media catalog and streaming platform with web and Android TV clients plus an administrative interface. Viewers browse and search the catalog, open series and episodes, then play a selected source; administrators ingest media, enrich catalog data, and manage storage. The backend exposes the API and coordinates domain services, PostgreSQL, and object storage. The README documents TMDB enrichment and scraping capabilities, but their detailed runtime wiring is not sampled, so those links are shown only where supported.

Main entry points: [`apps/backend/src/app.ts`](https://github.com/titanaprilian/private-movie/blob/main/apps/backend/src/app.ts) (HTTP API Server), [`apps/web/src`](https://github.com/titanaprilian/private-movie/tree/main/apps/web/src) (Web Client), [`packages/media-service/src`](https://github.com/titanaprilian/private-movie/tree/main/packages/media-service/src) (Media Service), [`apps/backend/src/modules/episodes`](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/episodes) (Episode Ingest API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_clients["Client Applications"]
  node_web["Web Client"]
  node_tv["Android TV"]
  node_webwatch["Browse And Watch"]
  node_webadmin["Catalog Admin"]
  node_webstorage["Storage Admin"]
  node_tvnav["TV Navigation<br/>[AppNavigation.kt]"]
end

subgraph group_api["Backend API"]
  node_backend["HTTP API Server<br/>[app.ts]"]
  node_auth["Authentication"]
  node_catalogapi["Catalog API"]
  node_episodeapi["Episode Ingest API"]
  node_mediaapi["Media API"]
  node_storageapi["Storage API"]
end

subgraph group_media["Media Services"]
  node_mediaservice["Media Service"]
  node_scraper["Media Scraper"]
  node_seed["Ingestion And Enrichment"]
  node_contracts["API Contracts"]
end

subgraph group_data["Catalog And Storage"]
  node_db[("PostgreSQL Catalog")]
  node_s3service["S3 Storage Service"]
end

node_viewer(("Viewer"))
node_admin(("Administrator"))
node_postgres[("PostgreSQL")]
node_s3[("S3-Compatible Storage")]
node_tmdb["TMDB"]
node_source["Remote Media Sources"]

node_viewer -->|"uses"| node_web
node_viewer -->|"uses"| node_tv
node_admin -->|"uses"| node_web
node_web -->|"offers browsing"| node_webwatch
node_web -->|"offers catalog management"| node_webadmin
node_web -->|"offers storage management"| node_webstorage
node_tv -->|"navigates screens"| node_tvnav
node_webwatch -->|"requests catalog and playback"| node_backend
node_tvnav -->|"requests media data"| node_backend
node_webadmin -->|"submits ingestion"| node_episodeapi
node_webstorage -->|"manages storage"| node_storageapi
node_backend -->|"dispatches routes"| node_auth
node_backend -->|"dispatches routes"| node_catalogapi
node_backend -->|"dispatches routes"| node_episodeapi
node_backend -->|"dispatches routes"| node_mediaapi
node_backend -->|"dispatches routes"| node_storageapi
node_episodeapi -->|"ingests media"| node_mediaservice
node_mediaapi -->|"resolves playback"| node_mediaservice
node_storageapi -->|"manages objects"| node_mediaservice
node_episodeapi -->|"reads episode records"| node_db
node_mediaservice -->|"reads and writes catalog"| node_db
node_db -->|"persists data"| node_postgres
node_mediaservice -->|"uses storage operations"| node_s3service
node_s3service -->|"uploads and retrieves objects"| node_s3
node_contracts -->|"defines shared API types"| node_web
node_contracts -->|"defines shared API types"| node_backend
node_seed -.->|"enriches metadata"| node_tmdb
node_seed -.->|"uses scraping utilities"| node_scraper
node_scraper -.->|"scrapes media sources"| node_source
node_seed -.->|"imports catalog data"| node_db
node_mediaservice -.->|"fetches remote streams"| node_source

click node_web "https://github.com/titanaprilian/private-movie/tree/main/apps/web/src"
click node_tv "https://github.com/titanaprilian/private-movie/tree/main/apps/android-tv/app/src/main/java/com/privatemovie/tv"
click node_webwatch "https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/watch"
click node_webadmin "https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/videos"
click node_webstorage "https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/storage"
click node_tvnav "https://github.com/titanaprilian/private-movie/blob/main/apps/android-tv/app/src/main/java/com/privatemovie/tv/navigation/AppNavigation.kt"
click node_backend "https://github.com/titanaprilian/private-movie/blob/main/apps/backend/src/app.ts"
click node_auth "https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/authentication"
click node_catalogapi "https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/series"
click node_episodeapi "https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/episodes"
click node_mediaapi "https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/media"
click node_storageapi "https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/storage"
click node_mediaservice "https://github.com/titanaprilian/private-movie/tree/main/packages/media-service/src"
click node_scraper "https://github.com/titanaprilian/private-movie/tree/main/packages/media-scraper/src"
click node_seed "https://github.com/titanaprilian/private-movie/tree/main/packages/seed-cli/src"
click node_contracts "https://github.com/titanaprilian/private-movie/tree/main/packages/contracts/src"
click node_db "https://github.com/titanaprilian/private-movie/tree/main/packages/db/src/schema"
click node_s3service "https://github.com/titanaprilian/private-movie/blob/main/packages/media-service/src/internal/s3/s3-storage-service.ts"

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_tv,node_webwatch,node_webadmin,node_webstorage,node_tvnav,node_viewer toneBlue
class node_backend,node_auth,node_catalogapi,node_episodeapi,node_mediaapi,node_storageapi,node_postgres,node_s3 toneAmber
class node_mediaservice,node_scraper,node_seed,node_contracts toneMint
class node_db,node_s3service toneRose
class node_admin,node_tmdb,node_source toneIndigo
```

## Components

### Client Applications

- [Web Client](https://github.com/titanaprilian/private-movie/tree/main/apps/web/src): `apps/web/src`
- [Android TV](https://github.com/titanaprilian/private-movie/tree/main/apps/android-tv/app/src/main/java/com/privatemovie/tv): `apps/android-tv/app/src/main/java/com/privatemovie/tv`
- [Browse And Watch](https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/watch): `apps/web/src/modules/watch`
- [Catalog Admin](https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/videos): `apps/web/src/modules/videos`
- [Storage Admin](https://github.com/titanaprilian/private-movie/tree/main/apps/web/src/modules/storage): `apps/web/src/modules/storage`
- [TV Navigation](https://github.com/titanaprilian/private-movie/blob/main/apps/android-tv/app/src/main/java/com/privatemovie/tv/navigation/AppNavigation.kt): `apps/android-tv/app/src/main/java/com/privatemovie/tv/navigation/AppNavigation.kt`

### Backend API

- [HTTP API Server](https://github.com/titanaprilian/private-movie/blob/main/apps/backend/src/app.ts): `apps/backend/src/app.ts`
- [Authentication](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/authentication): `apps/backend/src/modules/authentication`
- [Catalog API](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/series): `apps/backend/src/modules/series`
- [Episode Ingest API](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/episodes): `apps/backend/src/modules/episodes`
- [Media API](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/media): `apps/backend/src/modules/media`
- [Storage API](https://github.com/titanaprilian/private-movie/tree/main/apps/backend/src/modules/storage): `apps/backend/src/modules/storage`

### Media Services

- [Media Service](https://github.com/titanaprilian/private-movie/tree/main/packages/media-service/src): `packages/media-service/src`
- [Media Scraper](https://github.com/titanaprilian/private-movie/tree/main/packages/media-scraper/src): `packages/media-scraper/src`
- [Ingestion And Enrichment](https://github.com/titanaprilian/private-movie/tree/main/packages/seed-cli/src): `packages/seed-cli/src`
- [API Contracts](https://github.com/titanaprilian/private-movie/tree/main/packages/contracts/src): `packages/contracts/src`

### Catalog And Storage

- [PostgreSQL Catalog](https://github.com/titanaprilian/private-movie/tree/main/packages/db/src/schema): `packages/db/src/schema`
- [S3 Storage Service](https://github.com/titanaprilian/private-movie/blob/main/packages/media-service/src/internal/s3/s3-storage-service.ts): `packages/media-service/src/internal/s3/s3-storage-service.ts`

### Other components

- **Viewer**
- **Administrator**
- **PostgreSQL**
- **S3-Compatible Storage**
- **TMDB**
- **Remote Media Sources**

## Connections

- Viewer → Web Client: uses
- Viewer → Android TV: uses
- Administrator → Web Client: uses
- Web Client → Browse And Watch: offers browsing
- Web Client → Catalog Admin: offers catalog management
- Web Client → Storage Admin: offers storage management
- Android TV → TV Navigation: navigates screens
- Browse And Watch → HTTP API Server: requests catalog and playback
- TV Navigation → HTTP API Server: requests media data
- Catalog Admin → Episode Ingest API: submits ingestion
- Storage Admin → Storage API: manages storage
- HTTP API Server → Authentication: dispatches routes
- HTTP API Server → Catalog API: dispatches routes
- HTTP API Server → Episode Ingest API: dispatches routes
- HTTP API Server → Media API: dispatches routes
- HTTP API Server → Storage API: dispatches routes
- Episode Ingest API → Media Service: ingests media
- Media API → Media Service: resolves playback
- Storage API → Media Service: manages objects
- Episode Ingest API → PostgreSQL Catalog: reads episode records
- Media Service → PostgreSQL Catalog: reads and writes catalog
- PostgreSQL Catalog → PostgreSQL: persists data
- Media Service → S3 Storage Service: uses storage operations
- S3 Storage Service → S3-Compatible Storage: uploads and retrieves objects
- API Contracts → Web Client: defines shared API types
- API Contracts → HTTP API Server: defines shared API types
- Ingestion And Enrichment → TMDB: enriches metadata
- Ingestion And Enrichment → Media Scraper: uses scraping utilities
- Media Scraper → Remote Media Sources: scrapes media sources
- Ingestion And Enrichment → PostgreSQL Catalog: imports catalog data
- Media Service → Remote Media Sources: fetches remote streams
