No antenna, no problem: Building my own digital TV ecosystem

Let's be honest. The internet is a magical place, full of tools to do almost anything. Need to watch free-to-air TV online?

Feb 8, 2026
Let's be honest. The internet is a magical place, full of tools to do almost anything. Need to watch free-to-air TV online? There are dozens, if not hundreds, of projects out there. They're all pretty good, really. Some are even, dare I say, excellent. So why, you might ask, did I feel the need to create yet another one?
Because, like any good developer, I am an unreasonable man. And unreasonable men don't just accept what's there; they demand it to be slightly different, just for them.
It all started with a simple, yet profoundly annoying, problem: the antenna cable. Or rather, the lack of a convenient one near my TV. I needed a solution, and the web, with its vast collection of free IPTV playlists, seemed like the obvious answer. But a new set of First-World problems immediately cropped up.
• "This playlist has the channels in the wrong order."
• "I don't like the color of the interface."
• "Why are these dead channels haunting my list like digital ghosts?"
• "Seriously, why is it so hard to just watch Italian TV without a PhD in network streaming?"
Instead of doing what a sane person would do, you know, just dealing with it, I decided to embark on a quest. A quest to build the perfect, personal TV hub. The one I wanted. The result? A new useless project.

A tale of two tones: Backend Blues and Frontend Follies

This project is not a revolution. It's an evolution of personal frustration. My mission was simple: to watch free-to-air content in Italy, stuff I already pay a TV tax for, without having to tear down walls to install an antenna cable just to watch the Sanremo music festival. That seemed even crazier than starting this whole project. For years, I dedicated myself to building and refining every possible add-on for Kodi, a popular open-source media player. My work involved countless hours of reverse engineering APIs, a legality I still question years later, but let's not dwell on that.
My love for Kodi eventually faded when it became a digital black hole, consuming all the precious storage on every TV stick and TV box with just 8GB of space cause yep every device that allows you to watch Netflix with evil Winedive-DRM support rarely has more than 8gb of storage.
I needed something simple, something that just worked, without the hassle.
The project's core is a simple, elegant API that generates .m3u playlists on the fly. The entire system is powered by the excellent and community-maintained Free-TV/IPTV repository, which provides a massive, constantly updated list of global free-to-air channels. My project doesn't host any video content; it simply processes this massive list to give you exactly what you want.
The backend, written as a serverless Netlify Function in JavaScript, is the workhorse. You want just the Italian channels? The function takes your request, api/it, fetches the massive .m3u8 file from the Free-TV repository, and then filters it. It's not just a simple search, though. It intelligently parses the #EXTINF metadata tags, specifically targeting group-title="Italy" including both live and VOD contents.
But the real magic happens next: it cleans the channel names, stripping out unnecessary Unicode characters and suffixes, and then re-tags each entry with a proper tvg-id and tvg-name. This last part is crucial because it ensures the playlist is fully compatible with external players and, most importantly, with an Electronic Program Guide (EPG) what's EPG? It's the magical data that tells you what show is on and when. I'm also combining EPG data from different sources to provide a rich, combined guide for Italian channels.
The front end, however, is where my inner drama queen truly shines. This is where I got to play with vanilla JS, CSS, and HTML, a testament to the fact that you don't need a 5GB framework to build a simple web page that none will ever use.
The user interface, with its "Immersive Mode" (read: a dark theme to save your retinas), is designed to be as minimal and distraction-free as possible. It's a bit like watching a movie with the lights off, but for your web browser. Why? Because who needs a glowing white screen shouting at them while they're trying to watch a documentary about, well, something? The front-end's JavaScript handles the client-side parsing and rendering of the channel list, dynamically populating the UI. For the video playback itself, it uses the hls.js library to handle the live streams, ensuring smooth and reliable playback directly in the browser.

When a serverless function just isn't enough: The Bazooka Approach

Now, some of you might be thinking: "A serverless function? That's so… easy. So… efficient." To which I reply, "Exactly. Where's the fun in that?" The ways of deployment are as infinite as the ways of the Lord, and sometimes you just need to pull out a bazooka to swat a fly. For the truly unreasonable developer, OpenTivu offers a full-fledged Python backend.
Let's include a Flask web server, all wrapped up neatly in a Docker container. This turns your machine into a personal IPTV hub, complete with its own RESTful API. Why go through all that trouble? Because it’s there. And because I can. With a simple docker-compose up, you can run a local server that provides a dynamic .m3u API endpoint for all your devices. This provides unparalleled control, allowing you to configure hosts and ports with a simple config.yml file, a small token of gratitude to those who crave total sovereignty over their TV-watching experience.

What's next?

This journey, from a simple desire to watch TV to a full-blown development project, is a classic case of what happens when a developer is left to their own devices. It's not about solving a problem for everyone; it's about solving a problem for me, and maybe, just maybe, a few other people who are just as picky.
So, there you have it. A project born out of pure, unadulterated personal preference. And isn't that what the best software is all about? Don't answer that. It's a rhetorical question.
  • • "This playlist has the channels in the wrong order."
  • • "I don't like the color of the interface."
  • • "Why are these dead channels haunting my list like digital ghosts?"
  • • "Seriously, why is it so hard to just watch Italian TV without a PhD in network streaming?"