A high-performance mobile streaming app for discovering, watching, and tracking movies and series. Built with React Native + Expo SDK 54, with a multi-provider stream resolver that finds playable sources across HDFilmCehennemi, Dizipal, and Stremio addons.
- Cinematic native UI — glassmorphism, hero parallax, smooth Reanimated transitions, dark-mode-first.
- Discovery that learns — taste profiles, daily picks that roll over at local midnight, "Top New This Week", smart-similar carousels, franchise timelines.
- Real IMDb ratings on every poster — resolved per item via
imdbapi.devwith OMDB + TMDB fallbacks, cached aggressively. - Multi-provider stream resolver — HDFilmCehennemi native decoder, Dizipal, NuvioStreams/Stremify (Stremio addons). No WebView fallback unless every native source fails. See Stream Resolver.
- Native expo-video player — landscape lock, HLS quality picker, subtitle tracks parsed from master playlists, headers (Referer) forwarded for hot-link-protected CDNs.
- Cross-device sync — Supabase-backed watchlist, favorites, watched-state, profile.
- Silent OTA updates — EAS Update channels (
preview/production), reload triggered on background→foreground while the player is idle, 3s cold-start update window for new installs. - Live ops — Supabase-backed announcements + remote provider config (rotate
hdfilmcehennemi.nl/dizipal2079.comwithout a release).
| Layer | Choice |
|---|---|
| Framework | React Native 0.81 + Expo SDK 54 |
| Language | TypeScript 5 |
| Navigation | React Navigation (native stack) |
| Styling | styled-components + custom theme |
| Animation | Reanimated 3 |
| Player | expo-video (native) + expo-av (fallback) |
| State | React Context API + AsyncStorage |
| Backend | Supabase (auth, storage, postgres) |
| Data | TMDB API (via Cloudflare Worker proxy) |
| Build & OTA | EAS Build + EAS Update |
- Node.js 18+
- npm or yarn
- Expo Go (for development) or an EAS-built dev client
- TMDB API access (proxy URL or local API key)
- Supabase project (URL + anon key)
git clone https://github.com/MammadovEshgin/Streambox.git
cd Streambox
npm install
cp .env.example .env # fill in TMDB + Supabase values
npm startThen press a (Android), i (iOS), or scan the QR with Expo Go.
See
.env.examplefor every supported variable. The TMDB proxy variant is preferred — the directEXPO_PUBLIC_TMDB_API_KEY/_ACCESS_TOKENkeys are local-dev fallbacks only and must not ship to production / EAS.
| Command | What it does |
|---|---|
npm start |
Start Expo dev server on LAN (port 8081) |
npm run start:localhost |
Same, but bind to localhost (USB-tethered devices) |
npm run android / npm run ios |
Launch directly on the connected device |
npm test |
Run the node:test suite (91 tests across 12 files) |
npm run typecheck |
tsc --noEmit — strict TypeScript pass |
npm run check:hdfilm |
Probe HDFilmCehennemi for decoder rotation (used by decoder-recovery.md) |
src/
├── api/ TMDB client, IMDb ratings, OMDB fallback, franchise lookups
├── components/ Reusable UI (cards, carousels, modals, player overlays)
├── constants/ Static config, copy
├── context/ Auth, theme, language, watchlist providers
├── hooks/ Shared hooks (useTodayKey, useSyncedMediaIdList, …)
├── localization/ i18n strings (EN, TR)
├── navigation/ React Navigation stack + types
├── screens/ Home, Movies, Series, Detail, Player, Profile, Search, …
├── services/ Domain services (resolver, OTA, Supabase, runtimeCache, …)
├── settings/ User-tunable settings
├── theme/ Design tokens
├── types/ Shared TS types
└── utils/ Pure utilities
tests/ node:test suites (resolver, subtitles, auth, image URLs, …)
docs/ Architecture & ops references (production-readiness, live-ops, …)
scripts/ check-hdfilm-resolver, asset optimizers, health checks
The resolver lives in src/services/WebPlayerService.ts and tries providers in priority order — a real native stream from any provider always wins over a WebView fallback from another. Order:
- HDFilmCehennemi (native) — search → decode
RapidrameHLS via the auto-detectingreverse → b64 → rot13scheme, parse master playlist for resolutions + subtitle tracks. - Dizipal (native) — search → resolve
data-cfg→getVideoApi→.m3u8. - Dizipal embed — when the direct stream isn't extractable but the embed URL is.
- Turkish-title retry — fetch the TMDB
/translationslocalized title (e.g. Dune → Dune: Çöl Gezegeni) and re-search both providers. Handles cross-language matching plus a Turkish-dotless-i fold soYadigârlarımatches the ASCII slugyadigarlari. - Stremio addons — NuvioStreams (
nuviostreams.hayd.uk) + Stremify (stremify.hayd.uk) via the standard/stream/{movie|series}/{imdbId}.jsonprotocol. - HDFilm WebView (last resort) — only when every native source failed.
Hardening guarantees that have a dedicated regression test:
- Year gate — if both the target and a candidate have a known year and they disagree, the candidate is rejected outright. Prevents Dune (1984) from substituting for Dune (2021).
- Substring/year-coincidence guard — a substring title match (e.g. Fury in Cuban Fury) never gets the wrong-year boost; the score stays below the provider cutoff so the resolver falls through.
- No JS-execution scrapers — every stream URL is recovered via JSON/HTTP, not headless browsers. Stable on every Android skin (incl. HyperOS, MIUI) and zero runtime ad overlays.
See decoder-recovery.md for the manual rotation playbook when HDFilm changes their obfuscation scheme.
npm test # 91 tests, ~1.1s
npm run typecheck # strict tsc passCoverage focuses on the parts where a regression silently breaks playback:
webPlayerService.test.ts— resolver scoring (Dune year gate, Fury substring guard, Turkish ı folding), Rapidrame decoder schemes, HLS playlist inspection.directLinkService.test.ts— Stremio addon JSON shape, subtitle extraction.subtitles.test.ts— VTT + SRT parsing, URL normalization.playerArchitecture.test.ts— locks the contract thatPlayerScreennever importswebviewand always renders native controls off.tmdbAuth.test.ts— dual-mode (api-key + bearer) auth with auto-retry.
The app ships behind two EAS Update channels:
| Channel | Used by | When it ships |
|---|---|---|
preview |
Internal devices / EAS Build dev | Every fix as it lands on main |
production |
Public APK on streamboxapp.stream | After preview soaks |
Updates apply silently: a background→foreground transition with LiveOpsHost checking updateReady && !playerActive calls applyFetchedAppUpdate() and reloads the bundle. Cold-start has a 3-second fallbackToCacheTimeout so first-launch installs jump to the latest bundle before render.
| Doc | What's in it |
|---|---|
docs/production-readiness.md |
Pre-launch checklist (security, performance, observability) |
docs/backend-hybrid-architecture.md |
TMDB proxy + Supabase split, key rotation |
docs/supabase-user-data-architecture.md |
Auth flow, RLS policies, sync model |
docs/live-ops.md |
Announcements + remote provider config |
decoder-recovery.md |
Manual recovery playbook when HDFilm rotates its decoder |
AGENTS.md |
Project agent system (orchester / designer / backend_dev / qa_engineer) |
Proprietary. © Eshgin Mammadov. All rights reserved.