A modern, self-hosted IPTV playlist manager. Edit, categorize and share your M3U playlists with native Xtream Codes integration, EPG support, drag-and-drop sorting and a clean dark/light UI.
📢 This project replaces xtreamcodesapitom3u. All future development, new features and updates will continue here. Completely free, no plan limits, no ads — full Xtream Codes & M3U editor with EPG, drag-and-drop sorting, multi-language UI, themes, and much more than the original tool.
- Xtream Codes API integration — Connect with server URL, username and password. Automatically pulls Live TV, Movies (VOD) and Series with categories.
- M3U import / export — Import from a local file or remote URL, edit, then export back to a clean
.m3ufile. - EPG TV Guide — Add XMLTV sources, automatic channel-to-EPG matching, multi-day programme grid.
- Bulk channel editing — Rename channels, change logos, edit stream URLs, swap categories — all from a side panel.
- Drag-and-drop sorting — Reorder both categories and channels with smooth drag handles.
- Three content types — Separate editors for Live Channels, Movies (VOD) and Series with their own categories and counts.
- Search & filter — Trigram fuzzy search across thousands of channels (PostgreSQL
pg_trgm). - Multi-language UI — Turkish + English (i18n keys, easy to extend).
- Dark / Light / System theme — Per-user preference saved in browser.
- Authentication — JWT access tokens + refresh tokens, password reset flow with SMTP, account deletion.
- Self-hosted & 100% free — No accounts on third-party servers, no plan limits, no ads. MIT licensed.
- Successor to xtreamcodesapitom3u — All future development happens here, with a far richer feature set: full editor UI, EPG, drag-and-drop sorting, multi-user auth, themes, i18n, demo seed, Docker support and much more.
Clean entry page with theme-aware hero, language switcher and direct GitHub link.
Dashboard showing all playlists with channel counts, stream-type badges (LIVE / VOD / SERIES), creation dates and quick actions for editing or deleting.
One-step connect flow. Auto-fills server URL, username and password by parsing a regular get.php?... M3U URL, or fill the fields manually. Pick which content types to pull.
Three-pane editor: stream-type sidebar, category list, channels table, and an edit panel for the selected channel (logo upload, EPG ID, stream URL, category).
The same editor specialized for movies — separate categories, channel-count badges per category, and a metadata "Fetch Info" action that hydrates titles from external sources.
Multi-day TV-guide grid. Add XMLTV sources, auto-match channels by tvg-id, then visually inspect the programme schedule per channel.
Reorder categories on the left, then drag channels on the right. Order is persisted instantly.
Profile summary, theme switcher (System / Dark / Light) and password change.
Backend
- Node.js 18+ · Express 4
- PostgreSQL 13+ · Knex 3 (migrations + query builder)
- JWT (access + refresh) · bcryptjs · helmet · express-rate-limit
- Pino structured logging · Nodemailer (SMTP)
Frontend
- Vue 3 (Composition API) · Vue Router 4 · Pinia 3
- Vite 6 · Axios
- Vanilla CSS with design tokens (no Tailwind)
Architecture
- Layered: routes → controllers → services → models
- M3U / EPG parsers as standalone modules (
src/parsers/) - Xtream Codes client with retry + exponential backoff (
src/services/XtreamClient.js)
- Node.js 18+
- PostgreSQL 13+ (with
pg_trgmextension — auto-enabled by the first migration)
git clone https://github.com/fyildirim-debug/M3uEditor.git
cd M3uEditor
# Backend deps
npm install
# Frontend deps
cd frontend && npm install && cd ..Copy the example file and fill in your values:
cp .env.example .envMinimum required keys:
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=m3u_playlist_editor
DB_USER=postgres
DB_PASSWORD=postgres
JWT_SECRET=change-me-to-a-long-random-string
APP_URL=http://localhost:5173
CORS_ORIGIN=http://localhost:5173SMTP keys (SMTP_HOST, SMTP_USER, SMTP_PASS, …) are optional — only needed for password-reset emails.
createdb m3u_playlist_editor # or use psql / pgAdmin
npm run migrateA one-shot seed creates a demo user with one populated playlist (9 categories, 36 channels — Live + VOD + Series) so you can explore the UI immediately:
npm run seed:demoDemo login:
Email: demo@m3ueditor.local
Password: demo1234
# Terminal 1 — backend (http://localhost:3000)
npm run dev
# Terminal 2 — frontend (http://localhost:5173)
cd frontend && npm run devOpen http://localhost:5173 and sign in.
A docker-compose.yml is included for a single-command boot:
docker compose up -dThis starts the API, the static frontend (served by Nginx) and a PostgreSQL container with persistent volume.
.
├── src/ Backend
│ ├── config/ DB, JWT, env config
│ ├── controllers/ Route handlers
│ ├── routes/ Express routers
│ ├── services/ Business logic (Auth, Channel, EPG, Xtream, …)
│ ├── parsers/ M3UParser, M3UFormatter, EPGParser
│ ├── middleware/ auth, admin, errorHandler
│ ├── models/migrations/ Knex SQL migrations
│ └── utils/ AppError, helpers
│
├── frontend/ Vue 3 SPA
│ └── src/
│ ├── views/ Landing, Login, Dashboard, Editor, Account, Admin, …
│ ├── stores/ Pinia (auth)
│ ├── langs/ i18n (tr.json, en.json) + useI18n composable
│ ├── composables/ useTheme
│ └── api.js Axios instance with refresh-token interceptor
│
├── scripts/ One-shot scripts (seed-demo.js, …)
├── tests/ Jest unit + property tests
├── screenshot/ UI screenshots used in this README
├── knexfile.js Knex config
└── docker-compose.yml Local stack
- Passwords are hashed with bcryptjs (cost factor 10).
- JWT secret must be rotated on first deploy — do not ship the example value.
- Auth endpoints are rate-limited (20 req / 15 min).
- All routes use helmet for security headers and CORS is locked to
CORS_ORIGIN. - Stream URLs and channel data live in your own PostgreSQL — nothing is sent to third parties.
PRs and issues are welcome. Before opening a PR:
npm test # Jest unit tests
npm run migrate # ensure migrations are cleanConventional commits are used (feat:, fix:, refactor:, docs:, …).
MIT © Furkan Yıldırım — see LICENSE.
Built with Vue 3, Express, Knex and PostgreSQL. Channel logos used in the demo seed are sourced from Wikimedia Commons.







