# savblack/plot architecture

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

- Interactive diagram: https://gitdiagram.com/savblack/plot
- Repository: https://github.com/savblack/plot

## Overview

PLOT is a movie and TV discovery and tracking product with web and mobile clients sharing platform-independent domain logic. Users search titles, manage watchlists and custom lists, record viewing history, and use calendar, profile, and social features. Supabase supplies authentication and persistence; TMDB supplies media data. Documented integrations include Plex and Trakt synchronization. The graph emphasizes these runtime paths and the marketing site; source excerpts were partial, so uncertain screen-to-hook wiring is omitted.

Main entry points: [`apps/web/src/App.jsx`](https://github.com/savblack/plot/blob/main/apps/web/src/App.jsx) (App shell), [`apps/web/src/main.jsx`](https://github.com/savblack/plot/blob/main/apps/web/src/main.jsx) (Web app), [`packages/core/useUnifiedSearch.js`](https://github.com/savblack/plot/blob/main/packages/core/useUnifiedSearch.js) (Unified search), [`apps/mobile/hooks/useTraktSync.ts`](https://github.com/savblack/plot/blob/main/apps/mobile/hooks/useTraktSync.ts) (Trakt sync)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_clients["Product clients"]
  node_web["Web app<br/>[main.jsx]"]
  node_webshell["App shell<br/>[App.jsx]"]
  node_searchui["Search view<br/>[SearchView.jsx]"]
  node_historyui["History view<br/>[HistoryView.jsx]"]
  node_calendarui["Calendar view<br/>[CalendarView.jsx]"]
  node_mobile["Mobile app<br/>[_layout.tsx]"]
  node_mobiletabs["App screens<br/>[_layout.tsx]"]
  node_website["Marketing site<br/>[_middleware.js]"]
end

subgraph group_shared["Shared domain"]
  node_search["Unified search"]
  node_history["History import<br/>[importPipeline.js]"]
  node_watchlist["Watchlist data<br/>[useWatchlist.js]"]
  node_calendar["Calendar data<br/>[useUpcoming.js]"]
  node_broadcast["Broadcast guide"]
  node_traktclient["Trakt sync<br/>[useTraktSync.ts]"]
end

subgraph group_backend["Backend services"]
  node_mediafn["Media sync<br/>[index.ts]"]
  node_traktfn["Trakt sync function<br/>[index.ts]"]
end

subgraph group_external["External services"]
  node_supabase[("Supabase")]
  node_tmdb["TMDB"]
  node_plex["Plex"]
  node_trakt["Trakt"]
  node_analytics["Product analytics"]
end

node_viewer(("Viewer"))

node_viewer -->|"uses"| node_web
node_viewer -->|"uses"| node_mobile
node_web -->|"renders"| node_webshell
node_webshell -->|"renders"| node_searchui
node_webshell -->|"renders"| node_historyui
node_webshell -->|"renders"| node_calendarui
node_mobile -->|"opens"| node_mobiletabs
node_web -->|"uses shared logic"| node_search
node_web -->|"uses shared logic"| node_history
node_mobile -->|"uses shared logic"| node_history
node_searchui -->|"queries"| node_search
node_search -->|"searches titles"| node_tmdb
node_search -->|"searches users"| node_supabase
node_history -->|"reads and writes"| node_supabase
node_calendarui -->|"displays"| node_calendar
node_webshell -->|"uses"| node_watchlist
node_webshell -->|"uses"| node_broadcast
node_traktclient -->|"reads integration"| node_supabase
node_traktclient -.->|"authorizes"| node_trakt
node_traktclient -->|"calls"| node_traktfn
node_traktfn -->|"syncs data"| node_trakt
node_traktfn -->|"persists integration"| node_supabase
node_mediafn -->|"syncs titles"| node_plex
node_mediafn -->|"reads and writes"| node_supabase
node_website -.->|"serves site APIs"| node_supabase
node_web -->|"tracks events"| node_analytics

click node_web "https://github.com/savblack/plot/blob/main/apps/web/src/main.jsx"
click node_webshell "https://github.com/savblack/plot/blob/main/apps/web/src/App.jsx"
click node_searchui "https://github.com/savblack/plot/blob/main/apps/web/src/components/SearchView.jsx"
click node_historyui "https://github.com/savblack/plot/blob/main/apps/web/src/components/HistoryView.jsx"
click node_calendarui "https://github.com/savblack/plot/blob/main/apps/web/src/components/CalendarView.jsx"
click node_mobile "https://github.com/savblack/plot/blob/main/apps/mobile/app/_layout.tsx"
click node_mobiletabs "https://github.com/savblack/plot/blob/main/apps/mobile/app/(app)/_layout.tsx"
click node_website "https://github.com/savblack/plot/blob/main/apps/website/functions/_middleware.js"
click node_search "https://github.com/savblack/plot/blob/main/packages/core/useUnifiedSearch.js"
click node_history "https://github.com/savblack/plot/blob/main/packages/core/importPipeline.js"
click node_watchlist "https://github.com/savblack/plot/blob/main/packages/core/useWatchlist.js"
click node_calendar "https://github.com/savblack/plot/blob/main/packages/core/useUpcoming.js"
click node_broadcast "https://github.com/savblack/plot/blob/main/packages/core/useBroadcastGuide.js"
click node_traktclient "https://github.com/savblack/plot/blob/main/apps/mobile/hooks/useTraktSync.ts"
click node_mediafn "https://github.com/savblack/plot/blob/main/supabase/functions/media-sync/index.ts"
click node_traktfn "https://github.com/savblack/plot/blob/main/supabase/functions/trakt-sync/index.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_webshell,node_searchui,node_historyui,node_calendarui,node_mobile,node_mobiletabs,node_website,node_viewer toneBlue
class node_search,node_history,node_watchlist,node_calendar,node_broadcast,node_traktclient toneAmber
class node_mediafn,node_traktfn toneMint
class node_supabase,node_tmdb,node_plex,node_trakt,node_analytics toneRose
```

## Components

### Product clients

- [Web app](https://github.com/savblack/plot/blob/main/apps/web/src/main.jsx): `apps/web/src/main.jsx`
- [App shell](https://github.com/savblack/plot/blob/main/apps/web/src/App.jsx): `apps/web/src/App.jsx`
- [Search view](https://github.com/savblack/plot/blob/main/apps/web/src/components/SearchView.jsx): `apps/web/src/components/SearchView.jsx`
- [History view](https://github.com/savblack/plot/blob/main/apps/web/src/components/HistoryView.jsx): `apps/web/src/components/HistoryView.jsx`
- [Calendar view](https://github.com/savblack/plot/blob/main/apps/web/src/components/CalendarView.jsx): `apps/web/src/components/CalendarView.jsx`
- [Mobile app](https://github.com/savblack/plot/blob/main/apps/mobile/app/_layout.tsx): `apps/mobile/app/_layout.tsx`
- [App screens](https://github.com/savblack/plot/blob/main/apps/mobile/app/(app)/_layout.tsx): `apps/mobile/app/(app)/_layout.tsx`
- [Marketing site](https://github.com/savblack/plot/blob/main/apps/website/functions/_middleware.js): `apps/website/functions/_middleware.js`

### Shared domain

- [Unified search](https://github.com/savblack/plot/blob/main/packages/core/useUnifiedSearch.js): `packages/core/useUnifiedSearch.js`
- [History import](https://github.com/savblack/plot/blob/main/packages/core/importPipeline.js): `packages/core/importPipeline.js`
- [Watchlist data](https://github.com/savblack/plot/blob/main/packages/core/useWatchlist.js): `packages/core/useWatchlist.js`
- [Calendar data](https://github.com/savblack/plot/blob/main/packages/core/useUpcoming.js): `packages/core/useUpcoming.js`
- [Broadcast guide](https://github.com/savblack/plot/blob/main/packages/core/useBroadcastGuide.js): `packages/core/useBroadcastGuide.js`
- [Trakt sync](https://github.com/savblack/plot/blob/main/apps/mobile/hooks/useTraktSync.ts): `apps/mobile/hooks/useTraktSync.ts`

### Backend services

- [Media sync](https://github.com/savblack/plot/blob/main/supabase/functions/media-sync/index.ts): `supabase/functions/media-sync/index.ts`
- [Trakt sync function](https://github.com/savblack/plot/blob/main/supabase/functions/trakt-sync/index.ts): `supabase/functions/trakt-sync/index.ts`

### External services

- **Supabase**
- **TMDB**
- **Plex**
- **Trakt**
- **Product analytics**

### Other components

- **Viewer**

## Connections

- Viewer → Web app: uses
- Viewer → Mobile app: uses
- Web app → App shell: renders
- App shell → Search view: renders
- App shell → History view: renders
- App shell → Calendar view: renders
- Mobile app → App screens: opens
- Web app → Unified search: uses shared logic
- Web app → History import: uses shared logic
- Mobile app → History import: uses shared logic
- Search view → Unified search: queries
- Unified search → TMDB: searches titles
- Unified search → Supabase: searches users
- History import → Supabase: reads and writes
- Calendar view → Calendar data: displays
- App shell → Watchlist data: uses
- App shell → Broadcast guide: uses
- Trakt sync → Supabase: reads integration
- Trakt sync → Trakt: authorizes
- Trakt sync → Trakt sync function: calls
- Trakt sync function → Trakt: syncs data
- Trakt sync function → Supabase: persists integration
- Media sync → Plex: syncs titles
- Media sync → Supabase: reads and writes
- Marketing site → Supabase: serves site APIs
- Web app → Product analytics: tracks events
