# thepixelpro366/scp-reader architecture

> Architecture diagram of the GitHub repository thepixelpro366/scp-reader, 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/thepixelpro366/scp-reader
- Repository: https://github.com/thepixelpro366/scp-reader

## Overview

SCP Reader is an Android archive reader whose main workflow is browse or search SCP material, open and read an article, and optionally save it or play its narration. The app also supports friend recommendations, article voting, offline downloads, and in-app updates. The graph connects documented capabilities to the relevant source areas; several screen and app-state implementations were not sampled, so uncertain call-level wiring is omitted. The friends backend is represented separately from external services.

Main entry points: [`app/src/main/java/com/foundation/scpreader/AppState.kt`](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/AppState.kt) (App state), [`app/src/main/java/com/foundation/scpreader/MainActivity.kt`](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/MainActivity.kt) (Reader), [`app/src/main/java/com/foundation/scpreader/data/ScpRepository.kt`](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/ScpRepository.kt) (SCP repository), [`app/src/main/java/com/foundation/scpreader/data/NarrationRepository.kt`](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/NarrationRepository.kt) (Narration index)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["Android app"]
  node_reader["Reader<br/>[MainActivity.kt]"]
  node_appstate["App state<br/>[AppState.kt]"]
  node_home["Browse home<br/>[HomeScreen.kt]"]
  node_search["Search archive<br/>[SearchScreen.kt]"]
  node_library["Library<br/>[LibraryScreen.kt]"]
  node_downloads["Downloads<br/>[DownloadsScreen.kt]"]
  node_friendsui["Friends screen<br/>[FriendsScreen.kt]"]
  node_settings["Settings<br/>[SettingsScreen.kt]"]
  node_readerui["Article reader<br/>[ReaderScreen.kt]"]
end

subgraph group_content["Archive and reading"]
  node_scp["SCP repository<br/>[ScpRepository.kt]"]
  node_scraper["Wiki scraper<br/>[ScpScraper.kt]"]
  node_crom["CROM API<br/>[CromApi.kt]"]
  node_voteapi["Wiki voting<br/>[WikidotVoteApi.kt]"]
  node_room[("Article state<br/>[Bookmarks.kt]")]
  node_searchrecent[("Search recents<br/>[SearchRecents.kt]")]
end

subgraph group_media["Offline and playback"]
  node_narration["Narration index"]
  node_youtube["YouTube source<br/>[YouTubeSource.kt]"]
  node_podcast["Podcast source<br/>[PodcastApi.kt]"]
  node_playback["Player controller"]
  node_service["Media service<br/>[PlaybackService.kt]"]
  node_sponsor["SponsorBlock"]
  node_sponsorapi["SponsorBlock API<br/>[SponsorBlockApi.kt]"]
end

subgraph group_social["Friends and updates"]
  node_friendsrepo["Friends repository"]
  node_friendsapi["Friends API<br/>[FriendsApi.kt]"]
  node_worker["Recommendation poll"]
  node_update["Update manager<br/>[UpdateManager.kt]"]
  node_installer["Update installer<br/>[UpdateInstaller.kt]"]
end

subgraph group_backend["Friends backend"]
  node_friendserver["Friends backend<br/>[friends.php]"]
end

node_user(("App user"))
node_wiki{{"SCP Wikidot"}}
node_cromservice{{"CROM service"}}
node_ytservice{{"YouTube"}}
node_podcastservice{{"Apple Podcasts"}}
node_sbservice{{"SponsorBlock service"}}

node_user -->|"opens"| node_reader
node_reader -->|"shows"| node_home
node_reader -->|"shows"| node_search
node_reader -->|"shows"| node_library
node_reader -->|"shows"| node_downloads
node_reader -->|"shows"| node_friendsui
node_reader -->|"shows"| node_settings
node_home -->|"requests browse"| node_appstate
node_search -->|"requests search"| node_appstate
node_library -->|"requests saved items"| node_appstate
node_downloads -->|"manages downloads"| node_appstate
node_friendsui -->|"requests recommendations"| node_appstate
node_settings -->|"changes preferences"| node_appstate
node_readerui -->|"opens article"| node_appstate
node_appstate -->|"requests content"| node_scp
node_scp -->|"fetches pages"| node_scraper
node_scraper -->|"reads articles"| node_wiki
node_scp -->|"requests archive data"| node_crom
node_crom -->|"fetches rankings"| node_cromservice
node_scp -->|"submits votes"| node_voteapi
node_voteapi -->|"rates pages"| node_wiki
node_scp -->|"stores article state"| node_room
node_scp -->|"stores search recents"| node_searchrecent
node_appstate -->|"requests narration"| node_narration
node_narration -->|"discovers episodes"| node_youtube
node_narration -->|"loads fallback episodes"| node_podcast
node_youtube -->|"fetches streams"| node_ytservice
node_podcast -->|"loads feed"| node_podcastservice
node_narration -->|"resolves audio"| node_playback
node_playback -->|"serves media session"| node_service
node_appstate -->|"requests skip segments"| node_sponsor
node_sponsor -->|"fetches segments"| node_sponsorapi
node_sponsorapi -->|"queries segments"| node_sbservice
node_playback -.->|"loads skip segments"| node_sponsor
node_appstate -->|"manages friends"| node_friendsrepo
node_friendsrepo -->|"calls"| node_friendsapi
node_friendsapi -->|"sends requests"| node_friendserver
node_worker -->|"polls recommendations"| node_friendsrepo
node_worker -->|"notifies"| node_user
node_settings -->|"checks releases"| node_update
node_update -->|"passes APK"| node_installer
node_update -->|"reports status"| node_user

click node_reader "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/MainActivity.kt"
click node_appstate "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/AppState.kt"
click node_home "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/HomeScreen.kt"
click node_search "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/SearchScreen.kt"
click node_library "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/LibraryScreen.kt"
click node_downloads "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/DownloadsScreen.kt"
click node_friendsui "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/FriendsScreen.kt"
click node_settings "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/SettingsScreen.kt"
click node_readerui "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/ReaderScreen.kt"
click node_scp "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/ScpRepository.kt"
click node_scraper "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/ScpScraper.kt"
click node_crom "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/CromApi.kt"
click node_voteapi "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/WikidotVoteApi.kt"
click node_room "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/database/Bookmarks.kt"
click node_searchrecent "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/database/SearchRecents.kt"
click node_narration "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/NarrationRepository.kt"
click node_youtube "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/YouTubeSource.kt"
click node_podcast "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/PodcastApi.kt"
click node_playback "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/PlayerController.kt"
click node_service "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/PlaybackService.kt"
click node_sponsor "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/SponsorBlockController.kt"
click node_sponsorapi "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/SponsorBlockApi.kt"
click node_friendsrepo "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/FriendsRepository.kt"
click node_friendsapi "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/FriendsApi.kt"
click node_worker "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/notify/RecommendationWorker.kt"
click node_update "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/update/UpdateManager.kt"
click node_installer "https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/update/UpdateInstaller.kt"
click node_friendserver "https://github.com/thepixelpro366/scp-reader/blob/main/webserver/friends.php"

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_reader,node_appstate,node_home,node_search,node_library,node_downloads,node_friendsui,node_settings,node_readerui,node_user toneBlue
class node_scp,node_scraper,node_crom,node_voteapi,node_room,node_searchrecent toneAmber
class node_narration,node_youtube,node_podcast,node_playback,node_service,node_sponsor,node_sponsorapi toneMint
class node_friendsrepo,node_friendsapi,node_worker,node_update,node_installer toneRose
class node_friendserver,node_wiki,node_cromservice,node_ytservice,node_podcastservice,node_sbservice toneIndigo
```

## Components

### Android app

- [Reader](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/MainActivity.kt): `app/src/main/java/com/foundation/scpreader/MainActivity.kt`
- [App state](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/AppState.kt): `app/src/main/java/com/foundation/scpreader/AppState.kt`
- [Browse home](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/HomeScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/HomeScreen.kt`
- [Search archive](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/SearchScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/SearchScreen.kt`
- [Library](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/LibraryScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/LibraryScreen.kt`
- [Downloads](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/DownloadsScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/DownloadsScreen.kt`
- [Friends screen](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/FriendsScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/FriendsScreen.kt`
- [Settings](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/SettingsScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/SettingsScreen.kt`
- [Article reader](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/ui/screens/ReaderScreen.kt): `app/src/main/java/com/foundation/scpreader/ui/screens/ReaderScreen.kt`

### Archive and reading

- [SCP repository](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/ScpRepository.kt): `app/src/main/java/com/foundation/scpreader/data/ScpRepository.kt`
- [Wiki scraper](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/ScpScraper.kt): `app/src/main/java/com/foundation/scpreader/network/ScpScraper.kt`
- [CROM API](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/CromApi.kt): `app/src/main/java/com/foundation/scpreader/network/CromApi.kt`
- [Wiki voting](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/WikidotVoteApi.kt): `app/src/main/java/com/foundation/scpreader/network/WikidotVoteApi.kt`
- [Article state](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/database/Bookmarks.kt): `app/src/main/java/com/foundation/scpreader/database/Bookmarks.kt`
- [Search recents](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/database/SearchRecents.kt): `app/src/main/java/com/foundation/scpreader/database/SearchRecents.kt`

### Offline and playback

- [Narration index](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/NarrationRepository.kt): `app/src/main/java/com/foundation/scpreader/data/NarrationRepository.kt`
- [YouTube source](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/YouTubeSource.kt): `app/src/main/java/com/foundation/scpreader/network/YouTubeSource.kt`
- [Podcast source](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/PodcastApi.kt): `app/src/main/java/com/foundation/scpreader/network/PodcastApi.kt`
- [Player controller](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/PlayerController.kt): `app/src/main/java/com/foundation/scpreader/playback/PlayerController.kt`
- [Media service](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/PlaybackService.kt): `app/src/main/java/com/foundation/scpreader/playback/PlaybackService.kt`
- [SponsorBlock](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/playback/SponsorBlockController.kt): `app/src/main/java/com/foundation/scpreader/playback/SponsorBlockController.kt`
- [SponsorBlock API](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/SponsorBlockApi.kt): `app/src/main/java/com/foundation/scpreader/network/SponsorBlockApi.kt`

### Friends and updates

- [Friends repository](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/data/FriendsRepository.kt): `app/src/main/java/com/foundation/scpreader/data/FriendsRepository.kt`
- [Friends API](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/network/FriendsApi.kt): `app/src/main/java/com/foundation/scpreader/network/FriendsApi.kt`
- [Recommendation poll](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/notify/RecommendationWorker.kt): `app/src/main/java/com/foundation/scpreader/notify/RecommendationWorker.kt`
- [Update manager](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/update/UpdateManager.kt): `app/src/main/java/com/foundation/scpreader/update/UpdateManager.kt`
- [Update installer](https://github.com/thepixelpro366/scp-reader/blob/main/app/src/main/java/com/foundation/scpreader/update/UpdateInstaller.kt): `app/src/main/java/com/foundation/scpreader/update/UpdateInstaller.kt`

### Friends backend

- [Friends backend](https://github.com/thepixelpro366/scp-reader/blob/main/webserver/friends.php): `webserver/friends.php`

### Other components

- **App user**
- **SCP Wikidot**
- **CROM service**
- **YouTube**
- **Apple Podcasts**
- **SponsorBlock service**

## Connections

- App user → Reader: opens
- Reader → Browse home: shows
- Reader → Search archive: shows
- Reader → Library: shows
- Reader → Downloads: shows
- Reader → Friends screen: shows
- Reader → Settings: shows
- Browse home → App state: requests browse
- Search archive → App state: requests search
- Library → App state: requests saved items
- Downloads → App state: manages downloads
- Friends screen → App state: requests recommendations
- Settings → App state: changes preferences
- Article reader → App state: opens article
- App state → SCP repository: requests content
- SCP repository → Wiki scraper: fetches pages
- Wiki scraper → SCP Wikidot: reads articles
- SCP repository → CROM API: requests archive data
- CROM API → CROM service: fetches rankings
- SCP repository → Wiki voting: submits votes
- Wiki voting → SCP Wikidot: rates pages
- SCP repository → Article state: stores article state
- SCP repository → Search recents: stores search recents
- App state → Narration index: requests narration
- Narration index → YouTube source: discovers episodes
- Narration index → Podcast source: loads fallback episodes
- YouTube source → YouTube: fetches streams
- Podcast source → Apple Podcasts: loads feed
- Narration index → Player controller: resolves audio
- Player controller → Media service: serves media session
- App state → SponsorBlock: requests skip segments
- SponsorBlock → SponsorBlock API: fetches segments
- SponsorBlock API → SponsorBlock service: queries segments
- Player controller → SponsorBlock: loads skip segments
- App state → Friends repository: manages friends
- Friends repository → Friends API: calls
- Friends API → Friends backend: sends requests
- Recommendation poll → Friends repository: polls recommendations
- Recommendation poll → App user: notifies
- Settings → Update manager: checks releases
- Update manager → Update installer: passes APK
- Update manager → App user: reports status
