A Site For Dinner

I like to make small, single-serving sites - frivolous sites with only one
page, and one purpose. They’re intended to be dead-simple to use, fun to play with, and somewhat silly. I’ve made a couple in the past, both
alone and with others, often thinking of the idea over dinner and then implementing it in the hours (or days) that follow. Last night, I decided to
make another single-serving site - and to make it open-source, to show
others how simple it is to do.

Enter A Meal for Me. Roughly 200 lines of code for a fun site that now
helps me be more adventurous in the kitchen. (Grab the source on GitHub!)

That could make a tasty meal...

Development took a couple hours, and was simple enough:

  1. Have dinner.
  2. Google for “Recipe API.”
  3. Get an API key.
  4. Layout a simple page in HAML.
  5. Style with SASS.
  6. Wire it up to the API, and use some basic jQuery to munge the data.
  7. Apply a Google Web Font and subtle background pattern to make things look good.
  8. Apply API caching in Nginx.
  9. Sleep.

To save time (and lines of code), the site is nearly 100% in-browser. It makes
use of the wonderful Punchfork recipe API to grab data, then simply formats the resulting recipe cleanly and simply, providing an image of the meal and a link to instructions.

The site also makes use of HAML, SASS and CoffeeScript, rather
than HTML, CSS and JavaScript. This saved a significant amount of development time, and allowed me to use third-party style mixins like Bourbon. Images are sparse - the only .png files are the favicon, Punchfork reference, and the background, which was graciously taken from SubtlePatterns. Google Web Fonts also came in handy here, providing a well-suited font after roughly 60 seconds of searching.

To tie it all together are two non-browser components - a Rakefile and an nginx config. The Rakefile allows me to easily compile the HAML, SASS and CoffeeScript before deployment, and also fetches the required mixins (Bourbon). It could very easily be extended to watch the files during development, making the feedback loop much quicker.

The nginx config, on the other hand, serves two purposes: to cache queries to the Punchfork API, and to hide my private API key. As their API is rate-limited, I cache every query for 24 hours to make best use of the data I get. I also hard-code my API key in the nginx config, to prevent others from reading it from the client-side code and using it. All of this is quite simple to do with the proxy_pass and proxy_cache directives:

proxy_cache_path /tmp/recipe_cache levels=1:2 keys_zone=RECIPE:64m inactive=3600m max_size=360m;

# Yada yada yada...

server {

    # Yada yada yada, more in here...

    location ^~ /recipes {
        rewrite ^/recipes\??(.*) /recipes?key={your_private_api_key_here}&$1 break;
        proxy_pass http://api.punchfork.com/;
        proxy_cache RECIPE;
        proxy_cache_valid 200 204 302 3600m;

Although I haven’t load-tested or browser-tested the site, I’m done. Its mission was to provide an evening’s worth of learning and challenge. Now, it can hopefully help some others learn how to as well - and if nothing else, it’ll
help me learn how to cook more things.

Note: I’ve definitely made some errors in the code. If you find any, or even
just have any suggestions or comments, please do get in touch.


Now read this

Using Eight Cores (incorrectly) with Python

One of my web apps, The Wub Machine, is very computationally expensive. Audio decoding, processing, encoding, and streaming, all in Python. Naturally, my first instinct was to turn to the multiprocessing module to spread the CPU-bound... Continue →