StreamVault
April 19, 2026 · View on GitHub
A browser-based IPTV client — no app install, no subscription, bring your own service.
Try it now: https://portalheaven.stream/
Supports Xtream Codes, M3U playlists, Stalker/Ministra portals, and direct HLS/MP4 URLs.
Features
| Category | Details |
|---|---|
| Live TV | Channel grid with logos, EPG now-playing, quick channel switcher |
| Movies & Series | Poster grid with year, rating, seasons/episodes, resume progress |
| TV Guide | XMLTV EPG grid — load any provider's XML feed |
| Global Search | Searches live, movies, and series simultaneously |
| Favorites | Per-profile favorites across all content types |
| Continue Watching | Watch history with resume support (last 60 items) |
| Themes | Dark, Navy, AMOLED, Forest |
| Player | HLS.js + mpegts.js, keyboard shortcuts, PiP, OSD overlay |
| Offline-ready | IndexedDB caching — channels/categories persist across sessions |
Player keyboard shortcuts:
Space play/pause · F fullscreen · M mute · ←→ ±10s or channels · ↑↓ volume or channels · P PiP · Esc close
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Browser (React SPA) │
│ streamvault/src/App.jsx │
│ - IndexedDB for offline content cache │
│ - HLS.js / mpegts.js for playback │
└────────┬───────────────────────────┬────────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌──────────────────────────────────┐
│ stalker-proxy │ │ CF Worker (optional) │
│ Express on Node.js │ │ streamvault-worker/ │
│ - Stalker handshake │ │ - Stalker/Xtream/M3U proxy │
│ - CORS proxy │ │ - Stream proxy (HTTP→HTTPS) │
│ - Stream proxy │ │ - D1 database (persistent) │
│ Deploy: Koyeb/ │ │ - KV cache (session paths) │
│ Railway/Render │ │ - Usage analytics │
└─────────────────────┘ └──────────────────────────────────┘
You can run either the stalker-proxy (simple) or the CF Worker (full-featured), or both.
Project structure
StreamVault/
├── streamvault/ # React + Vite frontend
│ ├── src/App.jsx # Entire app (single-file architecture)
│ ├── functions/worker.js # CF Pages stream proxy (legacy)
│ └── .env.example
├── stalker-proxy/ # Node.js CORS proxy
│ ├── src/index.js # Express server
│ ├── koyeb.yaml # Koyeb deploy config
│ ├── railway.json # Railway deploy config
│ └── .env.example
└── streamvault-worker/ # Cloudflare Worker (optional)
├── src/
│ ├── index.js # Router + CORS
│ ├── handlers/ # stalker, stream, catalog, analytics
│ └── utils/ # auth, cors, stalker session mgmt
├── migrations/ # D1 database schema
└── wrangler.toml
Quick start (local dev)
1. Clone
git clone https://github.com/YOUR-USERNAME/StreamVault.git
cd StreamVault
2. Start the proxy (needed for Stalker portals and CORS)
cd stalker-proxy
cp .env.example .env
npm install
npm start
# Runs at http://localhost:3001
3. Start the frontend
cd streamvault
cp .env.example .env
npm install
npm run dev
# Runs at http://localhost:5173
4. Connect
Open http://localhost:5173 and choose a connection type:
| Type | What you need |
|---|---|
| Xtream Codes | Server URL, username, password |
| M3U Playlist | Direct .m3u or .m3u8 URL |
| Stalker Portal | Portal URL, MAC address (proxy must be running) |
| Direct HLS | Any .m3u8 or media URL |
Environment variables
Frontend (streamvault/.env)
| Variable | Default | Description |
|---|---|---|
VITE_PROXY_URL | http://localhost:3001 | Stalker proxy / Koyeb backend URL |
VITE_CATALOG_URL | same as PROXY | CF Worker URL for catalog API (optional) |
VITE_STREAM_PROXY_URL | same as PROXY | Stream proxy URL (optional, for split routing) |
Proxy (stalker-proxy/.env)
| Variable | Default | Description |
|---|---|---|
PORT | 3001 | Server port |
ALLOWED_ORIGIN | * | CORS origin — set to your frontend URL in production |
Deploying (free tier)
Frontend — Cloudflare Pages
- Fork this repo
- Go to pages.cloudflare.com → Create project → Connect to Git
- Root directory:
streamvault· Build:npm run build· Output:dist - Add env var:
VITE_PROXY_URL= your proxy URL - Deploy
Proxy — Koyeb (recommended)
- Go to koyeb.com → Create App → GitHub
- Select your fork, work directory:
stalker-proxy - Build:
npm install· Run:npm start - Add env var:
ALLOWED_ORIGIN= your Pages URL - Deploy
koyeb.yamlpre-fills these settings. Also works on Railway or Render.
CF Worker (optional, replaces proxy)
cd streamvault-worker
# Create resources
wrangler kv namespace create SV_CACHE
wrangler d1 create streamvault-db
# Add the returned IDs to wrangler.toml
# Run migrations
wrangler d1 migrations apply streamvault-db
# Deploy
wrangler deploy
Set VITE_CATALOG_URL in your frontend to the Worker URL.
Proxy API
Stalker endpoints
| Endpoint | Method | Description |
|---|---|---|
/stalker/handshake | POST | Token handshake with portal |
/stalker/channels | GET | All live channels with genres |
/stalker/vod/categories | GET | VOD category list |
/stalker/vod | GET | VOD items by category |
/stalker/series/categories | GET | Series category list |
/stalker/series | GET | Series items by category |
/stalker/series/seasons | GET | Seasons and episodes for a series |
/stalker/stream | GET | Resolve stream cmd to playable URL |
/stalker/epg | GET | EPG program data |
/stalker/profile | GET | STB profile info |
/stalker/api | GET | Generic portal API passthrough |
Utility endpoints
| Endpoint | Method | Description |
|---|---|---|
/stream | GET | Proxy HTTP streams over HTTPS with HLS manifest rewriting |
/proxy | GET | Generic CORS proxy for any URL |
/health | GET | Health check |
All endpoints return JSON with CORS headers (Access-Control-Allow-Origin: *).
How it works
Stream routing
| Protocol | Path |
|---|---|
| Stalker (HTTPS page) | Browser → Proxy /stalker/play → Portal create_link → Proxy /stream → IPTV server |
| Xtream (HTTPS page) | Browser → Proxy /proxy → Xtream API; Browser → Proxy /stream → TS/HLS stream |
| M3U (HTTPS page) | Browser → Proxy /proxy → M3U fetch; Browser → Proxy /stream → stream |
| Any (HTTP page) | Browser → IPTV server directly (no proxy needed) |
Stalker session management
Stalker portals require a specific handshake flow:
- Path discovery — try multiple API paths (
server/load.php,portal.php, etc.) - Handshake — get a session token tied to the MAC address
- Token refresh — auto-refresh on 401 responses
create_link— resolve channel commands to stream URLs (tokens may be IP-bound)
The proxy (and CF Worker) handle this transparently, including caching discovered paths.
Tech stack
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 8, single-file App.jsx |
| Player | HLS.js (adaptive), mpegts.js (raw TS), native <video> |
| Proxy | Node.js 18+, Express, node-fetch |
| Worker | Cloudflare Workers, D1 (SQLite), KV |
| Storage | IndexedDB (browser), D1 (cloud sync) |
| Styling | CSS-in-JS via template literal <style> tag |
Disclaimer
StreamVault is a client application — it does not provide any IPTV content. You must supply your own IPTV service credentials. Ensure you comply with your provider's terms of service and local laws.
License
PolyForm Noncommercial 1.0.0 — free for personal and noncommercial use. Commercial use requires a separate license.