Thousands of the world's freely-available live channels, internet radio and public-domain movies β in one fast, installable app with an HLS player, a multi-screen mosaic, a TV guide, and a full SaaS layer. Every channel is free.
βΆ Live demo Β· Features Β· Quick start Β· Architecture Β· Legal model Β· Contributing
π Try it live: neowatch.soclose.co
NEOWATCH is an aggregator and player for publicly-available media. It hosts no content: it indexes and plays streams that broadcasters already publish openly β live TV from the iptv-org directory, internet radio from radio-browser, and public-domain films from the Internet Archive. It ships as a fast React PWA backed by a thin Node/Express API, deployable as a single process on a small VPS.
It's built to be used on anything β phone, desktop, and especially the TV (D-pad/remote navigation, installable APK) β and to stay fast and lawful: direct-first playback keeps host bandwidth low, and monetization sells features, never access to third-party content.
Content
- π ~12,000 live channels worldwide (every iptv-org category), normalized with logos, country, language, quality β all free to watch.
- π» Internet radio β 800+ stations from the radio-browser directory, with a sticky audio player.
- π¬ Public-domain films β a browsable VOD catalog from the Internet Archive (classics, cult, documentaries), played natively.
- π TV guide (EPG) β import an XMLTV source for now/next per channel + "search by programme".
Player
- β‘ Tuned hls.js β fast start, adaptive bitrate, low latency; YouTube embed support.
- π Resilient playback β automatic escalation: direct β proxy β alternate feed, with a stall watchdog. A dead primary feed auto-promotes to a working alternate.
- ποΈ Quality, audio-language & subtitle selection; Picture-in-Picture; fullscreen.
- π’ Honest LIVE badges β a background health sweep does a real segment download so "online" means it actually plays, not just that a manifest responds.
Experience
- πͺ Multi-screen mosaic β watch 1β9 channels at once (great for following several matches), audio on one, config roams across devices.
- π Relevance-ranked search β multi-word, accent-insensitive, best-name-match first, with recent-search suggestions.
- π± Installable PWA + Android TV APK β responsive, offline shell, full keyboard/D-pad navigation.
- π² QR sign-in β scan a code on the TV to log in from your phone (no remote typing).
- π i18n β complete French / English / Russian.
- π¨ Themes, accent colors, grid density, favorites & history.
SaaS layer
- π JWT auth,
admin/userroles, admin dashboard (users, catalog refresh, health, takedown blocklist). - π³ Freemium done right β every channel is free; Premium sells features (no ads, extended multi-screen, cross-device sync, your own M3U playlists, personalized EPG). Mock billing built-in, Stripe-ready (checkout + signed webhook).
- π‘οΈ Security-first β SSRF guard on every user-URL path, rate-limiting, atomic writes, signed proxy URLs, GDPR account deletion, legal pages.
Click any shot to open the live app β neowatch.soclose.co
![]() π¬ Films β public-domain VOD |
![]() π» Radio β 800+ live stations |
![]() π TV guide β now/next EPG |
![]() πΊ Channel page β details + programme |
Brand & social assets live in web/public/social/.
Monorepo (npm workspaces):
server/ Node 20 (ESM) Β· Express 4 β API, HLS proxy, catalog cache, auth, EPG, billing
web/ React 18 Β· Vite 6 Β· Tailwind 3 Β· Zustand 5 Β· hls.js β SPA / PWA
- Dev: Vite on
:5273, API on:8787(Vite proxies/api). - Prod:
npm run buildβweb/dist; Express serves the static bundle and/apion a single port. - Data: the iptv-org API is fetched and cached to disk with a TTL, normalized once in memory, then queried/paginated per request. No database β JSON-file persistence for users.
- Playback: the app plays direct-first and only falls back to the built-in HLS proxy for CORS/geo/mixed-content streams β keeping host bandwidth low on shared deploys.
Detailed module map: CLAUDE.md.
npm install # installs both workspaces
npm run dev # web β http://localhost:5273 Β· api β http://localhost:8787On first boot the server caches the iptv-org catalog (a few seconds) and creates an admin account β the email and a random password are printed once in the logs (pin them via .env).
npm run build # typecheck + build the SPA into web/dist
npm start # Express serves web/dist + /api on $PORT (8787)docker compose up --build -dCopy .env.example β .env. Key variables (see the example file for the full list):
| Variable | Default | Purpose |
|---|---|---|
PORT |
8787 |
Server port |
CATALOG_TTL_HOURS |
12 |
Catalog cache lifetime |
HIDE_NSFW |
true |
Hide adult channels |
REQUIRE_AUTH |
false |
true = account required to watch (SaaS mode) |
JWT_SECRET |
(dev auto) | Set a long random value in production |
HEALTH_SWEEP |
false |
Background availability sweep |
BILLING_PROVIDER |
mock |
mock (instant) or stripe |
STRIPE_SECRET / STRIPE_PRICE_ID / STRIPE_WEBHOOK_SECRET |
β | Real payments (leave empty to use mock) |
ALLOWED_ORIGINS |
β | CORS allowlist for a deployed instance |
No secrets are committed.
.env, user data, caches and signing material are git-ignored..env.examplecontains only empty placeholders.
curl localhost:8787/api/health # { ok: true }
curl "localhost:8787/api/catalog/meta" # non-zero "total"
curl "localhost:8787/api/catalog/channels?category=sports&limit=3"
npm run typecheck && npm run build # must passThere's also an integration suite (tasks/integration-test.mjs) and an end-to-end smoke test (tasks/e2e-smoke.mjs).
NEOWATCH is designed to be run lawfully:
- It hosts nothing. It indexes streams that are already publicly published and plays them from their source. Radios (radio-browser) and films (Internet Archive public domain) are curated, freely-redistributable directories.
- Monetization sells features, not content. Every channel is free to watch. Premium unlocks software features (no ads, extended multi-screen, sync, your own playlists, EPG) β never access to third-party content.
- Instant takedown. An operator can hide any stream immediately via the admin blocklist (
/api/admin/blocklist) β the standard mechanism for honoring a rights-holder request. - Do not add scrapers for paywalled or pirated content, and don't place ads next to third-party live streams.
Availability, quality and licensing of individual third-party streams are the responsibility of their broadcasters. Rights-holders can request removal via the contact in the app's legal page.
Contributions are welcome β see CONTRIBUTING.md. Found a security issue? See SECURITY.md.
MIT Β© SoClose Society. Built by the SoClose dev community.




