Skip to content

justb81/watchbuddy

Repository files navigation

WatchBuddy Logo

WatchBuddy

Google TV + Android Companion App for cross-app series tracking with Trakt, local LLM recaps and deep links.

MIT License Platform Kotlin


Architecture Overview

watchbuddy/
├── app-phone/      Android companion app (LLM brain, BLE advertiser, HTTP server, Trakt auth)
├── app-tv/         Google TV app (display, BLE scanner, recap WebView, deep links)
├── core/           Shared: Trakt API, TMDB API, data models, network
├── backend/        Node.js Trakt token proxy (Docker, runs on your own server)
├── .github/        CI/CD workflows (build, test + release-please)
└── docs/           Architecture docs and decisions

For a detailed system architecture, communication protocols, LLM strategy and more, see docs/architecture.md.

Key Features

  • Cross-app tracking via Trakt — automatic scrobbling via MediaSession listener on the TV
  • AI Recaps ("Was bisher geschah") — generated by a local LLM on the companion phone, rendered as an animated HTML slideshow on the TV
  • Manual watched toggle — tap a show on the phone home screen to open the detail view, with the season you're currently mid-watching expanded on top and every episode tickable; home counters update instantly
  • Deep links — launches directly into Netflix, Prime Video, Disney+, WaipuTV, ARD, ZDF, etc.
  • Multi-user — multiple phones/users sync to one TV; active viewers are derived automatically from the phones connected to the TV, with no manual picker; shared watch mode avoids spoilers
  • Editable identity — override the display name and choose the avatar source (Trakt photo, generated from the name, or a custom photo from the phone) in Settings → Identity
  • RAM-adaptive LLM — AICore (Gemini Nano) if available, otherwise LiteRT-LM with auto-selected Gemma model based on free RAM
  • Resilient pairing — BLE-based discovery so phone ↔ TV discovery keeps working on guest Wi-Fi, mesh routers, and other networks where multicast / peer-to-peer traffic is blocked
  • Toggleable phone discovery — TV Settings → "Phone discovery" turns the BLE scanner off when you don't want it; TV Settings → "Autostart at TV boot" keeps discovery running in the background after a reboot so phones are already visible the next time you open the TV app
  • In-app diagnostics — Settings → Diagnostics on both apps shows live connection health (Wi-Fi / HTTP / BLE on the phone; discovery / heartbeat / discovered phones with RSSI on the TV) with a one-tap "Share diagnostics" button that exports the DiagnosticLog and any pending crash reports for bug reports

Module Structure

Module Description
app-phone Compose UI, BLE advertiser + HTTP server (port 8765), LLM inference
app-tv Compose for TV, BLE scanner, WebView recap, MediaSession scrobbler
core Trakt & TMDB API clients, shared models, network utilities
backend Node.js proxy: exchanges Trakt auth_code for tokens server-side

Code Statistics

Last updated: 2026-05-02 — generated by scripts/update-readme-stats.sh.

Module Files Lines of code Tests
app-phone 99 15 629 480
app-tv 82 13 392 352
core 65 8 520 525/526 (1 skipped)
backend 5 2 170 139
Total 251 39 711 1496/1497 (1 skipped)

Localization

WatchBuddy supports multiple languages out of the box. The UI is fully localized via Android resource files (values-<locale>/strings.xml):

Language Phone App TV App
English ✅ (default) ✅ (default)
Deutsch
Français
Español

AI-generated recaps automatically adapt to the device language via LocaleHelper, which passes the system locale to the LLM prompt so recaps are generated in the user's language.

To add a new language, create values-<locale>/strings.xml in both app-phone/src/main/res/ and app-tv/src/main/res/.

Setup

Android Apps

  1. Register a Trakt application at trakt.tv/oauth/applications
  2. Register a TMDB account at themoviedb.org
  3. Set environment variables: TRAKT_CLIENT_ID, TOKEN_BACKEND_URL (or leave empty for no proxy)
  4. Build with Android Studio or ./gradlew assembleDebug

Backend (Token Proxy)

cd backend
export TRAKT_CLIENT_ID=your_trakt_client_id_here
export TRAKT_CLIENT_SECRET=your_trakt_client_secret_here
docker-compose up -d

Optional environment variables:

Variable Default Description
PORT 3000 HTTP port the proxy listens on
DEBUG_MODE false Set to true to enable request debug logging
FETCH_TIMEOUT_MS 8000 Upstream Trakt API timeout in milliseconds. Increase only if Trakt responses are consistently slow in your network; keeping it low limits slow-loris-style resource exhaustion.

Play Store

Both apps share the package name com.justb81.watchbuddy:

  • Phone APK: versionCode ~1000, category LAUNCHER
  • TV APK: versionCode ~2000, category LEANBACK_LAUNCHER

Google Play auto-delivers the correct APK per device type.

Contributing

Contributions are welcome! Here's how:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit your changes with a descriptive message
  4. Push to your fork (git push origin feature/my-feature)
  5. Open a Pull Request against main

Please make sure your PR:

  • Follows the existing code style and project structure
  • Builds successfully (./gradlew assembleDebug)
  • Passes static analysis (./gradlew detektAll :app-phone:lintDebug :app-tv:lintDebug; npm --prefix backend run lint && npm --prefix backend run format:check)
  • Includes a clear description of the changes

CI runs detekt, Android Lint and (for backend changes) ESLint + Prettier on every PR. New findings beyond the committed baselines block the merge, and a per-module findings summary is posted to the PR. Inline annotations appear in the Files changed tab via GitHub code scanning.

Privacy / Datenschutz

WatchBuddy is designed with privacy in mind: no tracking SDKs, no analytics, no WatchBuddy-side user accounts. Trakt tokens stay in the Android Keystore on the phone, LLM recaps are generated entirely on-device, and the only server component (the optional token proxy at watchbuddy.server.rang.it) runs on an EU host and does not persist tokens. The URL is injected at build time via TOKEN_BACKEND_URL; self-hosters can override it in local.properties.

The full privacy policy is available in two language versions:

Note: The policy is a carefully researched draft and not legal advice. Before linking it from a public Play Store listing, a qualified IT / data-protection lawyer should review the German version — in particular the third-country transfer clauses for Trakt, TMDB and Hugging Face.

Attribution

  • This product uses the Trakt API but is not endorsed or certified by Trakt.
  • This product uses the TMDB API but is not endorsed or certified by TMDB.

License

This project is licensed under the MIT License.

About

WatchBuddy — Google TV + Android Companion App for cross-app series tracking with Trakt, local LLM recaps and deep links

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors