Wednesday, July 15th 2015 2 years ago

How I built the Music Player for Reddit and made it to the Front Page of the Internet

I started working on theMusic Player for Reddit a couple of years ago, two years ago now to be exact. It was supposed to be a desktop native app. I wanted to learn how to make one using web technologies so I fell down the hole of using Node.js and node-webkit (NW.js now). It was meant to be a music player for YouTube right on your desktop.

The very start

It started when I was listening to music on RedditPlaylister. My main complaint with that at the time was the interface. I couldn't easily switch subreddits, there was a lack of features that would allow you to see the video playing, you couldn't vote or comment on links, and it wasn't sexy.

I copied over the subreddits that the playlister had selected and used that as a basis and added other subs to it as I discovered them. After a few days of work I had a working app. I had SoundCloud working easily by playing audio through the native <audio> element. I even had a basic design where I could select subreddits and play the song in the background.

the first iteration

My struggles with the desktop app

But as I progressed I noticed there were problems with playing videos because of Flash permissions in node-webkit, and I wasn't able to stream it as audio only because of a lack of proprietary codecs in Chromium. Node-webkit is based on Chromium so it's not in there because they want to remain open and free. And you can't ship them together. Chrome, however, can.

I had a few architecture problems, where it became harder and harder to ship out new features because everything was so intertwined together. Often when I changed one thing it would break something else. I had to have an event go through multiple layers of code to be able to receive a PlayProgress event to the progress bar, for example.

So after struggling with it, first trying to integrate Flash and struggling with Flash permissions, and then trying to route the music through the native audio functions, I later gave up on the idea of making it a desktop app. I tried to make it a Chrome app but I couldn't get some features, such as opening a popup with a video of the song playing properly, to work.

To the web

At the time I had a good set up where I used Grunt to concatenate and minify the code and ship the particular files to a Chrome app, to a node-webkit app and try to build each of those. I added another step where I would build something to the web, something a browser could open and play right there. I had my kick-ass domain name il.ly registered and simply placed the code for that as a subdomain.

This solved most of my issues for playing audio. I added keyboard shortcuts, multireddit support, autoplay, permalinks, finding songs in Reddit comments, 129 more subreddits, and video mode.

But the interface wasn't good enough and I still had code smells where writing code became slower and slower.

Iterating on and on

At the time I started to get into CoffeeScript. So I started over from scratch and rebuilt the whole project to focus on the web, with a modular design. I also wanted to allow simple changes to be made to the program whenever I wanted, without having to look at how I made everything.

After looking up on how to architect an app I decided to use Backbone.js and settled on using an event-based system. This reduced complexity and my speed of iteration. I could write new features and add modules without bothering the rest of the code.

I added the features I've wanted to add, such as being able to log in through OAuth2 and Reddit. Then I added features where you could comment and upvote on songs, even self-posts, to allow users to participate in the Reddit community while listening to music.

I changed the look and feel of the application when I saw the newer version of Spotify and became inspired by that. Due to the change, I was also able to add a video that would play in the right sidebar and that would conform to the TOS of YouTube, where you always have to show the video.

version 0.3

It took me a while to get it to work again because I threw away all the old code, and because it took me a while to grasp the new libraries used. But I'm glad to have done it. As I iterated on with new releases every few days, and with feedback coming in through the subreddit, I was able to make something great.

I coded features I've had before such as multireddit support, search and custom subreddits. and added new ones with potential like remote control. Then I added HTTPS and called it a day in August 2014, and worked on other projects and freelance work.

Weeks before launch

I got back into it in May 2015. At that point I fixed outstanding bugs, updated my dependencies and tweaked the UI even more. I refreshed the logo, and switched to some newer libraries that had been released in the last year. I also changed the name to Music Player for Reddit to comply with Reddit's TOS, and added anonymous remote control that is based on tokens and QR codes.

I cleaned up the code and added a guide on how to contribute and created Github issues so potential contributors would know what to work on.

Then I moved the code to a Github organisation and changed the domain name to musicplayer.io and made the whole thing more robust.

Technologies used

Software:

Hardware: Running Debian with io.js, PM2 as a monitor, on a VPS

Node.js is JavaScript on the backend. You can write fast and scalable network applications. It's event-driven and lightweight.

I use Redis to save session data so people logged in are kept logged in if they come back later. It's a simple, fast and scalable key-value database.

Socket.io is for remote control. If someone is logged in they can make a QR-code and control the player using a phone for example. I had some fun with that where I had two speakers on two laptops in different rooms and I could sync up the music using the remote control feature.

Backbone was used as an architecture. I liked that I could separate Views and Collections and there are some useful built-in features. It doesn't mess with any other data like Angular would or control how you write your code too much.

I simply like writing in Coffeescript. It works well with Backbone too where I could easily create classes or use arrow functions. The code becomes a bit cleaner.

Less is a CSS pre-processor. If you don't know what it is, you have to try it. You can use variables and nest selectors.

Grunt is the tool that builds everything. I compile here, and listen on changes to my code where they are immediately compiled and the browser is reloaded. It's also has a production build where I minify and concatenate files so it uses less bandwidth.

Jade is a cleaner way to write HTML and a templating language. It has mixins and what not. I love using it and hate writing HTML without it.

Express is the server, I set up the backend as a MVC with it like Kraken does. Everything is separated in their own module.

Passport with my own extension handles the Reddit login.

Lodash helps with writing functional javascript. Making it really easy to work with arrays and collections.

Launching

I was still not getting a lot of interest in the Music Player and I didn't showcase it that much to other people so I decided to give it a try on /r/InternetIsBeautiful. I posted the link to the Music Player and figured I would at least get some visits. But it blew up almost instantly.

It reached the front page of /r/all and was the top link of Reddit for a few hours. I had about 5000 visitors in real time every few minutes. As the comments grew I was working the whole time trying to keep it from crashing on the back-end. I was using PM2 as a monitor and made it work in cluster mode with four balancers.

The app was very lightweight. All I had to deliver was the HTML and JavaScript files. The only real thing happening in the back-end was the socket.io integration for remote control. So I was able to cope fairly well.

I was still freaking out that something would go wrong every minute and I was fixing bugs users reported live in the comments. I added a cache busting mechanism and with the PM2 cluster mode I could reload the app without any downtime whatsoever.

People asked for an option to donate so I spun up a website on www.musicplayer.io in the next few hours and added a link. I made a twitter account and facebook page and followed tweets and blogs using mention and followed anyone who would mention the Music Player for Reddit or the domain name.

It was really amazing to get all this good feedback from people and all the love I've received. It's amazing for my motivation to do things like this. Not for money or for a company but because I want to make a product that I can be proud of and I would use myself.

"Quality stuff. I've already found a few things I like on the front page which I wouldn't normally hear."

"Probably one of the best sites I've found this year."

The traffic and aftermath

The music player became the top post of the month and still was when I wrote this article. I received about 150,000 sessions in 24 hours and currently serving about 700 per day. The launch explosion quickly died out but I'm happy to retain a sizeable portion of users. Before the launch I had about 30 users per day.

The next day the app got picked up on The Next Web and other blogs. I was featured on Product Hunt and I was added as a maker on Product Hunt, which is a great community for products.

Thanks to the traffic and SEO I added the few days after I was able to make it to first page of Google when you search "music player" partly due to the domain name and the fitting name. So hopefully more sustainable traffic would come through that channel over time.

Right now I'm focusing on adding good integrations that other music player don't have. Things like a command line interface, an API or a Telegram bot. Things that interest me and things I want to do.