Landing Page with Yeoman, Bower, Grunt, and a Node API Server

After building some static sites with Jekyll and then DocPad, I decided that it might make sense to leverage Grunt for the multitude of build steps such as asset minification and CoffeeScript compilation, rather than tool-specific plugins. This was confirmed by briefly working on my own DocPad plugin for downloading Web components, an effort that led me back to Bower, which despite some flaws has been growing in popularity as a package manager for the Web.

Well, if you want to quickly scaffold a Grunt and Bower project, it turns that the new Yeoman (1.0) makes it very easy to do. To get started, I used yo webapp to redo a simple landing page for an AngularJS book that I'm considering writing. This was easy, although the Grunt build produced by the Yeoman webapp generator contains far too much testing (Mocha, PhantomJS) for such a simple page.

Taking time out to reflect on the slowness of the build, I tried out two non-Grunt Node site generators: Jared Hanson's Kerouac and Jeff Escalante's Roots. Both are lean and blazing fast, but do not leverage a larger ecosystem of plugins or components. However, I will almost certainly come back to both of them.

Continuing with Yeoman, I decided to build a somewhat more ambitious single-page site, with a small Backbone.js widget for signups backed by a light Node JSON API server. (I coded and deployed the server separately, although in the future I hope to mostly generate the server code from the front-end project.) Here is the finished result: The TacoConf Salt Lake City landing page.

tacoconfslc landing page

Things went smoothly at first. Adding Backbone using Bower was very easy, although the Underscore dependency was not handled automatically. (This made me think about using Browserify instead for JavaScript components.) But things got difficult when I needed different server host names for production and development. Yeoman's grunt-usemin plugin felt extremely limiting. I cobbled together a solution to the problem with grunt-config and grunt-replace, but it made me seriously miss the power of a template-based asset pipeline such as the one provided by DocPad.

One of the better ideas I picked up from Yeoman is using git subtree for deployment to GitHub Pages. On Mac/OS X, you currently need to re-install git with homebrew to get subtree, but it's worth it.

Next in my lineup for static site generation with Grunt: Assemble.


Static Site Generation with Node.js and CoffeeScript

This article was originally published on coffeescriptlove.com.

As I discussed in "Interactive Static Sites With Jekyll, Backbone.js, and Firebase", static sites built using powerful Ruby-based tools such as Jekyll and Middleman are surging in popularity based on their benefits: low hosting costs, speed, stability, and security. Jekyll has powered the Obama campaign's $250 million fundraising platform as well as a new version of healthcare.gov. Several months ago GitHub Co-Founder and CEO Tom Preston-Werner renewed his commitment to Jekyll, writing, "Sorry for not keeping this thing moving faster. 2013 is gonna kick ass. Wake up, go to war."

So, this certainly sounds like good news for rubyists. But is there a tool for creating static sites using Node.js and CoffeeScript?

Say hello to DocPad.

docpad home page

DocPad embraces CoffeeScript in a big way.

For starters, let's take a look at a typical DocPad configuration file. Whoa! Not only is it in CoffeeScript, it even contains functions! Used judiciously, the ability to include short, readable CoffeeScript functions in your configuration is quite handy. For an interesting example, check out the instructions for using DocPad, GitHub and Prose as a Wiki. (Aside: After publishing this post, I will use Prose and GitHub as described to add a link to my post to the official DocPad showcase.)

The DocPad core and almost all of its community plugins are written in CoffeeScript, but that's not all. Although DocPad supports a long list of renderers that includes Handlebars and Jade in addition to PHP and Ruby, the project's skeletons have a strong preference for Eco (Embedded CoffeeScript) templates. For an example of a typical Eco template, check out getting-started.html.eco.

If you enjoy CoffeeScript and Eco (it also uses Backbone.js), I encourage you to jump in and give DocPad a try. I have posted my notes about porting blog.scriptybooks.com from Jekyll to DocPad, in case they might be of use.

Finally, no discussion of CoffeeScript and static site generators is complete without mentioning Jeremy Ashkenas' small but delightful Journo. In just a single file of code-within-documentation Literate CoffeeScript, Journo provides a everything you need for a minimalist tool, including deploys via rsync.


From Jekyll/Octopress to DocPad

docpad home page

After just three posts on Octopress, I decided to migrate ScriptyBlog to DocPad. Why? I'm trying to find the best platform for authoring interactive online technical books, for the next version of ScriptyBooks.

Jekyll, the slightly more general project upon which Octopress is based, is a mature static site generation tool that has had a recent 1.0 release and is again enjoying active development. However, both Jekyll and Middleman are Ruby-based, while DocPad runs on Node.js and is written in CoffeeScript, Backbone.js, and Eco templates. Just like my own interactive Backbone.js + CoffeeScript book!

It took me a few hours to do the migration. Here are my notes:

  1. Update Node.js and npm. This is easy these days with the official installer.
  2. Follow the install instructions. Node tiny modules are for real. You may find it delightful, or alarming, to watch the npm install of DocPad.
  3. I reacted with shock and shut down my network connection when I realized the docpad run script was reporting back to the mother ship. After looking into the source code and thinking about it a bit, I decided this was okay.
  4. Follow the Quick Start instructions for a bare install. So far, so good.
  5. In a new directory, create a new project using an existing skeleton. After looking at the list of plugins used in several skeletons, I went with Twitter Bootstrap.
  6. Copy over a post source file from the Octopress project. If post doesn't show up in the list, it may be because you omitted the 'post' tag that the DocPad example posts include. The 'post' tag is used in a query and is required.
  7. Encounter the EMFILE 'too many open files' error. Waste time googling and tinkering before finally finding the correct solution in the DocPad troubleshoot page. Renew my vow to always RTFM.
  8. Since file watching on OS X doesn't seem to be working very well, follow troubleshoot page solution for switching to 'watchFile'. The result is noticeably better though still not perfect. The livereload plugin works well for me.
  9. Install the Highlight.js plugin for code highlighting. Plugin management with npm is awesome!
  10. Convert Jekyll/Octopress image helper to markdown.
  11. Customize Bootstrap. Replace style.css.styl with style.css.less and uninstall stylus plugin. Stylus may be cool, but on a Bootstrap project I think it makes sense to stick with Less.
  12. Find Ben Delarre's helpful post on creating an index page and use it to make something like the Octopress index page. So far so good with CoffeeScript and Eco!
  13. Run docpad generate --env static and compare output against Octopress. It's different of course, but looks good.
  14. Waste time trying to figure out how to push out directory from master as the top-level directory on GitHub. It turns out the ghpages plugin already takes care of this.
  15. Fiddle with git to restore the blog source to the master branch. (Octopress uses a source branch.)
  16. Deploy using the ghpages plugin with docpad deploy-ghpages. See the glorious site live for a minute or so. Then see a GitHub 404 page.
  17. Figure out that I forgot to copy the CNAME file from the Octopress blog to the DocPad src directory. Deploy again.
  18. Success!

If you have any DocPad expertise to share, give me a shout on Twitter (@quartzmo). I'd love to connect with some people using it.