This post was originally posted on Plyr's GitHub repo.
In early 2015, I was working at an e-commerce startup called Selz. We were launching a product for selling access to videos and needed a player that looked good. Being a bit of a design snob, customization wasn’t just nice to have — it was essential.
At the time, there were two solid options: Video.js and MediaElement. Both are excellent players, but neither quite fit what I was looking for. So I decided to build something simple: a clean wrapper around the <video> element using what were then cutting-edge techniques. We’re talking <button> elements for buttons (revolutionary, I know), <input type="range"> for sliders, and <progress> elements for progress bars.
I started by forking PayPal’s accessible video player — credit to them for creating such a solid foundation. But eventually, for better or worse, I rewrote the whole thing. I tossed it on GitHub as an open source project, thinking not much would come of it. Who’d want to use my player, right?
A month or two later, someone posted it on Hacker News. If you’ve been in tech long enough, you know what happens next: traffic explodes. The project jumped in stars and suddenly I was getting feature requests and issues. I built as many features as made sense, and the project kept growing. It even landed on Product Hunt. Today, Plyr is sitting at almost 30,000 stars on GitHub. It's been an incredible journey, and now I'm working with the team at Mux to bring everything that made Plyr successful into Video.js v10. Here's how we got here.



What made Plyr special
Looking back, I think two things drove Plyr’s success:
Ease of use — It was really simple to add to your project. No complicated setup, no endless configuration. Just include it and go. It was literally this easy:
<video id="player" playsinline controls data-poster="poster.jpg">
<source src="video.mp4" type="video/mp4" />
<track src="captions.vtt" kind="captions" srclang="en" label="English captions" />
</video>
<!-- You had the above already, just add this... -->
<link rel="stylesheet" href="plyr.css" />
<script src="plyr.js"></script>
<script>const player = new Plyr('#player');</script>Design — It had a polished UI that supported basic customization out of the box. It looked good without developers having to fight with CSS.


As a bonus, it started small in file size — just 4kB min-zipped at launch — which was important when every kilobyte mattered.
Over the years, Plyr has been used on various spots across sites like the BBC, Netflix, SpaceX, Peugeot, Toyota, and many more. Even today, I stumble across it fairly frequently in my day-to-day browsing of the internet, which is always nice to see. Seeing it in production at that scale was incredibly validating, even as it revealed areas where the architecture needed to mature.
The surprising lessons and hard truths
Success sometimes reveals your mistakes more clearly than failure. If Plyr hadn’t been posted on Hacker News or Product Hunt, it’d probably be sitting on GitHub with a handful of stars. So yes, timing and luck played a huge role.
What surprised me most was the appetite for the player. I was solving a problem I had, and it turned out plenty of other developers had the same frustration and couldn’t find a good solution elsewhere.
But with time and experience, I can see all the things I’d do differently now:
Decomposition and decoupling
There’s no way to opt out of features in Plyr. You get everything whether you use it or not. Not great. Today, I’d break the player down into more granular pieces, using lazy loading and other techniques to keep the initial bundle small.
That original 4kB bundle? Today it’s 34kB min-zipped — an 8.5x increase. While some of that growth came from valuable features, a lot of it is code that many users never touch but have to download anyway.
Extensibility
The monolithic structure made extending Plyr difficult. This meant all functionality had to live in the core, which meant I (or contributors) had to build it, and worse — it was always in the bundle whether you used that feature or not. Moving forward, I’d create a proper API for plugins and extensions to modify both the core and the UI.
Reactivity
The logic to render the UI is all hand-built and pretty complex. These days, I’d probably use a small UI library to handle data-to-UI binding. Also, you couldn’t make changes to the player config without destroying and recreating the whole thing, which is pretty bad. I’d definitely fix that.
Better documentation
I used the repo’s README, and now it’s… well, it’s huge. A proper documentation site would have been so much better.
Technical breakthroughs: The details matter
I spent a lot of time getting the menu animations working just right. The system works kind of like the View Transitions API — it takes a snapshot of the start and end states and animates between them. Of course, the View Transitions API didn’t exist back then, and even now, Scoped View Transitions aren’t quite available everywhere just yet.
Those little touches—the way menus slide, the smoothness of transitions—that’s where the design polish really lived. It’s the kind of thing users might not consciously notice, but they’d definitely feel if it weren’t there.
Plyr’s evolution into Video.js v10
Here’s the exciting part: what’s coming forward from Plyr into Video.js v10.
Design and ease of implementation — those are the crown jewels of Plyr, and they’re absolutely making the journey forward. As for the core foundation? The team at Mux has far more experience building solid player infrastructure than I ever had working solo.
But we’re not just porting Plyr’s design over. We’re making it better. Instead of a single skin, Video.js v10 will offer multiple polished, accessible skins to cater to different tastes and use cases. And honestly? That’s the part I enjoy most—sweating over the details and pixels, making sure everything feels just right.
I’ll be honest: I’m not hugely proud of what Plyr’s codebase has become. It’s coupled, inflexible, and messy in ways that make me cringe. But here’s the silver lining — Mux has a solid development team with decades of combined experience building cutting-edge media players and hosting services. Teaming up with them to build the next iteration of Video.js just makes total sense.
The convergence means we get the best of both worlds: the design polish and ease of use that made Plyr successful, combined with the robust, battle-tested architecture that Mux brings to the table. Hopefully, I can do their excellent code justice by giving it a beautiful, modern UI that developers and users alike will love.
A message to Plyr users
We’re aiming to make the transition from Plyr to Video.js v10 as smooth and rewarding as possible. This is the best player we’ve ever built. We’re confident you’ll love it.
Think of Video.js v10 as what Plyr v4 would have been if it had existed — but even better. Everything you loved about Plyr is coming with you, amplified by the collective wisdom and technical expertise of multiple player projects converging into one powerful platform.
Your feedback, feature requests, and contributions to Plyr over the years directly influenced Video.js v10. This isn’t goodbye to what you built with Plyr — it’s graduation day.
The road ahead: Building something extraordinary together
The convergence of Plyr, Vidstack, Media Chrome, Mux Player, and the other players in this series represents something special in the video player ecosystem. We’re taking the hard-won lessons from years of real-world use and combining them into a foundation that’s both more powerful and more flexible than any individual player could be.
For developers who value design, for teams who need extensibility, for anyone who’s ever fought with a video player to make it do what they want — Video.js v10 is being built for you.
The beta is coming in February 2026, and I genuinely can’t wait to hear what you think.
Ready to see where Plyr’s design philosophy is headed? Check out Video.js v10 and join us in building the future of video on the web.



