Discover, search, and watch movies and TV shows — across Web, Desktop (Windows/macOS/Linux), and Mobile (Android/iOS).
FilmSnaps is a cross-platform streaming-discovery ecosystem powered by the TMDB API. Browse trending content, search with fuzzy matching, build a watchlist, track watch history, and stream through provider players that are hardened against ads, trackers, and popups on every platform.
This repository is a pnpm + Turborepo monorepo: a Next.js web app, an Electron desktop app that wraps the web app with a native hardened player, an Expo/React Native mobile app, and a feedback portal.
| App | Package | Stack | Description |
|---|---|---|---|
| Web | @filmsnaps/web |
Next.js 16 (App Router) + Tailwind | Discovery UI, watch pages, API routes |
| Desktop | @filmsnaps/desktop |
Electron 43 + Next.js static export | Web UI + native hardened player (WebContentsView hybrid) |
| Mobile | @filmsnaps/mobile |
Expo SDK 55 / React Native 0.83 | Phone app with downloads + native player |
| Feedback | @filmsnaps/feedback |
Next.js 16 + Cloudflare Workers/D1 | Public feedback portal |
| Package | Description |
|---|---|
@filmsnaps/shared |
Shared guard scripts, provider registry, types, state, design tokens. |
@filmsnaps/adblock-config |
v5 providers.json + filters.txt schema + validation + Ed25519 OTA config loader. |
@filmsnaps/filter-compiler |
Adblocker engine (@ghostery/adblocker WASM) + mobile pattern export. |
- Security Architecture — the full security stack: R0–R8
rule cascade and L2–L8 desktop layers, mobile native protection, WebContentsView hybrid,
and the
providers.json+filters.txtv5 configuration. - Architecture — repository layout, data flow, builds, and CI.
- Contributing — how to set up, develop, add a provider, and ship changes.
- Node.js ≥ 18
- pnpm 10 (
corepack enableor install directly) - A TMDB API key (free)
# 1. Install dependencies (builds @filmsnaps/shared via postinstall)
pnpm install
# 2. Configure the TMDB API key
cp .env.example apps/web/.env.local # or set TMDB_API_KEY in your shell / .dev.vars
# TMDB_API_KEY=your_key
# 3. Run everything (all apps in dev mode)
pnpm dev
# Or run one app:
pnpm dev:web # http://localhost:3000
pnpm dev:mobile # Expo dev server
pnpm dev:desktop # Electron (starts the Next.js dev server + app)See each app's README for platform-specific setup (native modules, signing, build profiles).
| Command | Purpose |
|---|---|
pnpm build |
Build all apps/packages (Turborepo). |
pnpm lint |
Lint everything. |
pnpm test |
Run the Vitest suites (shared + desktop security). |
pnpm typecheck:desktop |
Typecheck the desktop app. |
pnpm format |
Prettier across the repo. |
pnpm build:filters |
Regenerate adblocker/filter artifacts from providers.json + filters.txt. |
pnpm sign:providers |
Sign providers.json with Ed25519 for OTA. |
pnpm cf:deploy |
Deploy the web app to Cloudflare Pages. |
pnpm dist:desktop |
Build the desktop installer. |
- Smart search — fuzzy title matching (Fuse.js) with hybrid ranking: fuzzy relevance + popularity + vote score.
- Watchlist & history — save titles, cross-session persistence, continue-watching. Stored locally on-device (no account required — the app is fully anonymous).
- Multi-provider player — provider registry in
@filmsnaps/shared; each platform mounts embeds with native security layers (see docs/security.md). - Native hardened desktop player — WebContentsView hybrid (Electron 43), L8
Page.addScriptToEvaluateOnNewDocumentHTML-bytes injection (replaces disabled CDP-Fetch that dropped renderer headers → Cloudflare 403),@ghostery/adblocker(adblock-rs WASM), session trust with MIME-based 15-min TTL,allowServerRedirectsfor redirect-mesh providers. - Native hardened mobile player —
PlayerWebViewnative Expo module withshouldInterceptRequestfiltering (Aho-Corasick unified trie), Ed25519-verified OTA config with ring-buffer rollback, 3×-failure watchdog, NavGuard server-redirect fix, session trust with 15-min TTL, and cosmetic rules from config. - Anime support — toggle Anime mode (Hard Mode Split) to surface anime via AniList search and route playback to MegaPlay (MAL/AniList-keyed). Every anime title auto-matches to its MyAnimeList / AniList ID, with automatic 410 fallback between ID spaces. Server selection is per-title, so a movie in anime mode (or anime in movie/TV mode) always opens with the correct servers.
- Signed OTA config —
providers.json+filters.txtv5, Ed25519-signed, ring-buffer rollback (3 configs), 3×-failure watchdog with localheal-events.logon both desktop and mobile. - Mobile downloads — SQLite-backed episode/movie downloads with a native downloader.
- Feedback portal — account-free bug reports, feature requests, roadmap, changelog, FAQ.
- Web: Cloudflare Pages + Netlify (
.github/workflows/). - Desktop:
electron-builder→ GitHub Releases (.github/workflows/release.yml). - Mobile: EAS build profiles (
apps/mobile/eas.json,.github/workflows/mobile.yml).
This project is licensed under the GNU General Public License v3.0 (GPL-3.0). You may redistribute and/or modify it under the terms of the GPL-3.0; see LICENSE for the full text.