A multi-tenant Stremio addon platform. Users sign up, add their IPTV provider credentials (Xtream Codes), and get a unique personalized Stremio addon URL that serves their VOD catalog with automatic host failover and TMDB metadata matching.
See ADR.md for full architecture decision record.
/
├── backend/ Node.js + Express + PostgreSQL
│ └── src/
│ ├── addon/ Stremio addon protocol handlers
│ ├── api/ REST API routes (auth, user, providers)
│ ├── admin/ Admin API routes
│ ├── jobs/ Background cron jobs
│ ├── services/ Business logic
│ ├── db/ Schema, migrations, queries
│ └── middleware/
└── frontend/ React + Tailwind CSS
└── src/
├── pages/ User dashboard (6 pages)
├── admin/ Admin dashboard (6 pages)
├── components/
├── context/
└── utils/
- Node.js 18+
- PostgreSQL 14+ (or Docker)
- TMDB API key (free at themoviedb.org)
# Copy env file
cp backend/.env.example backend/.env
# Edit backend/.env with your TMDB API key and secrets
# Start everything
docker compose up -d --build
# Run migrations (first time only)
docker exec streambridge_backend npm run migrateApp will be at:
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
- Admin panel: http://localhost:3000/admin/login
The Docker frontend runs as a production build served by Nginx. If you change
VITE_API_URL, rebuild the frontend image with docker compose up -d --build.
# 1. Set up PostgreSQL database named 'streambridge'
# 2. Backend
cd backend
cp .env.example .env # Edit with your values
npm install
npm run migrate # Apply schema
npm run dev # Start backend on :3001
# 3. Frontend (new terminal)
cd frontend
npm install
VITE_API_URL=http://localhost:3001 npm start # Starts on :3000| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
TMDB_API_KEY |
TMDB API key (optional but improves match quality) |
ADMIN_USERNAME |
Admin panel username |
ADMIN_PASSWORD |
Admin panel password |
JWT_SECRET |
Random secret for JWT signing |
PORT |
Backend port (default: 3001) |
BASE_URL |
Public URL of the backend (for addon URLs) |
FRONTEND_URL |
Frontend origin (for CORS) |
RESEND_API_KEY |
Resend API key for transactional email |
RESEND_FROM_EMAIL |
From address for outgoing emails (must be on a verified Resend domain) |
The following secrets must be set in GitHub → Settings → Secrets and variables → Actions:
| Secret | Description |
|---|---|
RESEND_API_KEY |
Resend API key — get from resend.com → API Keys |
RESEND_FROM_EMAIL |
From address — currently noreply@thekush.dev (verified domain: thekush.dev). If you change the sending domain, update this secret and re-verify the new domain in Resend. |
Domain change checklist: Update the
RESEND_FROM_EMAILGitHub secret → verify the new domain in the Resend dashboard (add SPF/DKIM DNS records) → redeploy.
- Create a new Railway project
- Add a PostgreSQL plugin
- Deploy the backend service with the
/backendroot directory - Deploy the frontend service with the
/frontendroot directory - Set all environment variables in Railway dashboard
- Run
npm run migratein the backend service shell
Kubernetes deployment assets now live under deployment/README.md.
The included Helm chart covers:
- frontend Deployment + Service
- backend Deployment + Service
- optional scheduler Deployment for cron jobs
- optional in-cluster PostgreSQL
- optional Ingress routing for
/,/api,/admin,/addon, and/health
Basic install:
helm upgrade --install streambridge ./deployment/helm/streambridge \
--namespace streambridge \
--create-namespace \
-f your-values.yamlFor K3s, there is also a starter profile at deployment/helm/streambridge/values.k3s.yaml.
Each user gets a unique URL:
https://your-app.railway.app/addon/{token}/manifest.json
| Job | Schedule | Description |
|---|---|---|
| Health Check | Every 5 min | Pings all provider hosts, sets best active host |
| TMDB Sync | Daily 2 AM | Downloads TMDB export files |
| Catalog Refresh | Daily 4 AM | Re-fetches VOD from all providers |
| Matching | Daily 5 AM | Matches unmatched titles against TMDB |
All jobs can be triggered manually from the Admin → System panel.
- Raw title from IPTV provider:
"The Matrix (1999) Hindi Dubbed 1080p" - Cleaned by stripping language tags, quality tags, year:
"The Matrix" - PostgreSQL trigram similarity query against
tmdb_movies - Score > 0.6 → stored in
matched_contentwith TMDB ID - Unmatched content still shows in Stremio with provider poster/title as fallback
- Match cache is global — if another user has the same raw title, result is reused