Hung Truong: The Blog!

Side Project: Audubon

March 10, 2015 | 3 Minute Read

The Idea

A few weeks ago, I noticed a tweet from John Sheehan asking if there was an automated tweet -> screenshot tool:

Anyone know of a browser extension or something else that can turn a tweet into a single image for presentations, etc?I thought it was a pretty interesting concept that would be fairly easy to implement and had a small enough scope that I could use it to learn some more Javascript. After playing around with Ghost Inspector, I knew it would be possible to render a screen capture of a webpage. I just needed to implement the logic for figuring out what area of a page to render, rather than the whole page.

The Solution

I played around with CasperJS before finding a StackOverflow post that described that I could do all that I wanted in PhantomJS, which CasperJS is built on. I wrote a script that would take a url as an input and spit a png out to stdout. Then I wrote a node web app in Express that could take the url as a parameter and run the script through the child_process.spawn command. I had the express app write the stdout of the child process to a buffer and send it once the script was finished. Done!


I ran into a problem when I wanted to host my app on Heroku. Heroku apparently does not support writing to /dev/stdout, and I only found out about this when my images were being sent as empty files. I looked at some solutions that involved writing to an Amazon S3 bucket, but I didn’t want to incur that much of an operations overhead for something so lightweight.

As a workaround, I found that Heroku does allow writing to /tmp, though any files you throw in there are not guaranteed to remain there after the request is over. For me that’s perfect, since the file only needs to exist as long as the request lasts.

Finally, I threw together an index view with a form and a button that takes a Twitter URL and loads the image into the same view when you click on “OK.” I got a nice theme from here and hardly customized it.

Screenshot in a screenshot inception.
Screenshot in a screenshot inception.

I also figured out how to use the “Deploy to Heroku” feature by adding an app.json file to my git project.

There were a couple of other issues I ran into that I didn’t describe yet, mostly getting PhantomJS 2.0 to run on Heroku (because previous versions don’t render webfonts correctly) and setting up the multiple buildpacks on Heroku. You can see what I ended up using by inspecting the Github project here.

I called the project Audubon after the Audubon Society which is really into birds (get it? birds, tweets?). You can deploy it yourself with this button:



There’s a couple of things I need to wrap up in this project. If anyone wants to they could also fork the project and throw a pull request at me, but I’m planning on doing these eventually:

  • Make the command line tool better for generating images (right now it just writes to /tmp so I should make that configurable).
  • Make a bookmarklet so it’s easy to create images from the Twitter website.
  • Make the web index page look a little nicer
  • Maybe provide image format and quality options

Overall I think this was a really good side project in terms of scope and complete-ability. I learned a lot about Node.js, ExpressJS and PhantomJS. I’ve been meaning to level up my Javascript web game, and this project has been a useful exercise.