Paul Graham wrote an essay back in 2009 entitled “The List of N Things”:
I bet you the current issue of Cosmopolitan has an article whose title begins with a number. “7 Things He Won’t Tell You about Sex,” or something like that. Some popular magazines feature articles of this type on the cover of every issue. That can’t be happening by accident. Editors must know they attract readers.
Why do readers like the list of n things so much? Mainly because it’s easier to read than a regular article. Structurally, the list of n things is a degenerate case of essay. An essay can go anywhere the writer wants. In a list of n things the writer agrees to constrain himself to a collection of points of roughly equal importance, and he tells the reader explicitly what they are.
After reading this essay I distinctly remember getting an idea for a web app immediately. Although only now I realize it has been 5 years since that essay came out, it was only last week that I decided to use the spare 3 days left in the week after a vacation to actually build it. I challenged myself to build the whole from scratch app during those three workdays (altogether 20 effective hours).
I did. I had fun. And I’m pretty pleased with the result.
So, what is it? nthings.net is a simple web app that makes it easy to collaboratively create and edit these types of “n things about x”-style articles, sometimes referred to as listicles.
Anybody can create an account, create a new list with a title along the lines “n things you didn’t know about lemons,” and start adding things to it. Other registered users can extend the list with their own things, and vote on things already on the list that you didn’t author yourself. Items with more points end up higher in the list, resulting in lists (that can potentially get very long) with the most interesting stuff at the top. A kind of reddit for thing lists, if you will. If things you add to a list get voted up or down, you receive or lose points. There’s a ranked user list, topic pages (as subdomains), search etc.
The funny thing is that I have had this idea for many years, and only 5 minutes ago bothered to check if anybody else built something like this. “If I’ve never heard of it, it must not exist” — I thought. Turns out there are many of them. None of them seem particularly successful, though (or look in the least attractive). Oh well, we’ll see how my implementation of this concept will work out.
“Fascinating stuff, Zef — just tell me about the tech already.”
Usually, I take any side project as an opportunity to use some hyper new stack. So what did I use? Clojure with MongoDB? React.js with node.js? Nope.
Prepare to be disappointed.
This time I decided to take my own advice: to pick my battles. I had three days, did I really want to waste it on new tech with little documentation or with difficult to reliably deploy dependencies?
No. This time the challenge was to build something in a reasonably polished state quickly, without taking much additional risk.
So, I decided on the a stack I had worked with a few years ago (or some variant thereof):
- Google App Engine running Python: this is the oldest and still best-supported language App Engine offers. Any error message you get and weird thing you want to try is quickly Google’able. In addition, using a PaaS like this solves any trouble in deploying and reliably keeping up the site. The last thing that I want to do is operate servers and fail over databases reliably. App Engine offers all this out of the box: scalable datastore, memcache, reliable email sending, full-text search, image manipulation, data blob storage, one-command deployment, auto scaling. Perfect for this project.
- Python Flask: while not the most main-stream choice on App Engine (the SDK comes with the webapp2 framework), I had heard good things about flask, so wanted to try it. Documentation was thorough, lots of questions and answers on StackOverflow too. Seemed like a safe choice.
- Jinja2 templates: this came with Flask, so I used it.
Some tidbits from the implementation:
- There are no images used at all. You can upload an image as part of a “thing,” but the site lay-out uses none.
- Practically all content is generated statically on the server. AJAX is only used in a few places, e.g. to validate the registration form, load comments dynamically and to search while typing in the UI to create a new list. All AJAX calls send back pre-rendered HTML, so no templating happens in the browser at all.
- The about page is a n things list itself. So, that was easy to implement.
- A lot of caching using memcache is used. App Engine’s ndb database module does part of this automatically already, but I had to add some query caching manually, e.g. for recent list, related lists etc.
- With a simple header-tag I made the site look reasonable on mobile devices (at least on my iPhone and iPad).
I found the App Engine with Python combination a very gratifying rapid development environment. I had used it a few years ago, so I roughly remembered the restrictions and features of the App Engine data store. I also had used Python before, so that came natural. The development experience was productive: I wrote all my code in Zed, obviously (and improved the Python mode a bit, too), reloading the page picked up changes in code automatically and errors were reported clearly.
I set specific goals for each day and always ended up doing significantly more than I planned, which why the end result is more polished than anticipated (there are even some moderation features, and the site doesn’t look terrible even though I have no design talent whatsoever).
I found the experience of building a full app from scratch in such a short time frame very gratifying. If you have a few days to set aside at some point I suggest you give it a try. Of course, the challenge is to come up with a “scalable” project — on where it’s possible to get to something usable very quickly, and extend from there.
So, there you have it: nthings.net. Who knows, you’ll may see some nthings.net lists appear on the Twitters soon. I already created one on iOS 8 features and Apple’s new Swift language.
Now, let’s get back to “real” work.