The code
PEK TV lives in one repository on one branch, main: a C++ backend, a Flutter UI shared by every platform, and an Android host.
Repository layout
backend/ C++ server + embedded Python (dev.sh builds it). API only, no web pages
flutter_ui/ the screens: the Flutter / Dart app shared by every platform
android/ Gradle project: Kotlin host, JNI, Python runner, resources
assets/ branding (icon, banner, splash) and screenshots
plugins/ bundled plugins: tmdb-discover, weather, skin-maker
plugin_packages/ plugin zips prepared for distribution
skins/ bundled skins: default (PEK Ember), green, neon
cloud/ Cloudflare Workers: PEK Cloud (sync, accounts, subtitles) and the PEK Store
tools/ sync_providers.js, make_skin.py, providers.json
.github/workflows/build_android.yml the signed Android APK buildHow the parts fit
Flutter UI (flutter_ui/) <---- HTTP, port 8080 ----> C++ backend (backend/)
plugin screens (Python screen.py) scans folders and network shares
are drawn natively by the app streams files, subtitles, trailers
libmpv driven over pek/* channels runs plugin backends via embedded Python,
behind hesper_guard.py
PEK Cloud + PEK Store (Cloudflare Workers + D1), optionalThe server answers only the device it runs on unless you set PEK_BIND and PEK_TOKEN. On Android, the Kotlin host starts the backend through JNI and plugin Python runs with Chaquopy.
Modules
Where to start reading.
| Part | Folder | What it does |
|---|---|---|
| Flutter UI | flutter_ui/lib/src/ | shell, home, layouts and focus (phone swipe pages, TV sidebar, D-pad); library, detail and dashboard pages; player, subtitles and skip; music; profiles and cloud; skins; the plugin host, install flow and store. |
| Backend | backend/ | server.cpp HTTP server and routes; media_scanner.cpp and nfo.h library scan; vfs_*.cpp one virtual file system over local, SMB, NFS, FTP, WebDAV and UPnP; music.cpp and music_tags.cpp; torrent.cpp; plugin_install.h, skin_install.h, github_install.h. |
| Plugin guard | hesper_guard.py | Decides whether a plugin's Python may run: manifest check, import and attribute scan, audit hook and time limits. |
| Android host | android/ | Kotlin host (MainActivity, FlutterHostActivity), libmpv player (MpvController), Chaquopy for plugin Python, JNI into the backend. |
| Cloud | cloud/ | Two Cloudflare Workers: PEK Cloud (accounts, sync, subtitle cache) and the PEK Store (plugin shelves). |
Releases and in-app updates
PEK TV checks GitHub for a newer release every time it starts and offers to download and install it. Android always asks for confirmation.
# 1. raise pekBaseCode by 1 in android/app/build.gradle (18 -> 19)
# 2. push a tag; the workflow builds and publishes the release
git tag v2.2.0 && git push origin v2.2.0
# Result: PEK-TV-<version>-release-arm64-v8a.apk
# PEK-TV-<version>-release-armeabi-v7a.apk// each CPU build gets its own versionCode, so a 64-bit install stays 64-bit
versionCode pekBaseCode * 10 + (pekAbi == 'arm64-v8a' ? 2 : (pekAbi == 'armeabi-v7a' ? 1 : 0))
minSdk 26 // Android 8.0 or newer- The updater reads the release list, so pre-releases count; the newest tag with a matching apk wins.
- The apk is checked against GitHub's SHA-256 when available, and Android refuses any apk signed with a different key.
- Debug,
-dev.Nand local builds never show the update screen.
More reference docs
Each of these lives in the repository root.
PLUGINS.md
The plugin manifest, backend guard, permissions and publishing.
FLUTTER_PLUGINS.md
Python screens, the pek_ui API and effects.
SKINS.md
Skin format, installer and tools.
MUSIC.md
How the Music tab reads and plays your files.
SUBTITLES.md
Automatic subtitle lookup.
LOCAL_METADATA.md
NFO files and local artwork.
UPDATES.md
The in-app updater.
FLUTTER.md
The Flutter UI.