node.jstwitter-bootstrapmongodbassemble

Building an Assemble.io front-end in an ExpressJS build


Bear with me, currently learning the following technologies.

I have built a basic application consisting of a NodeJS + ExpressJS + MongoDB + Monk + Jade build. I intend on replacing Jade with Handlebars, a different templating engine. To assist with this, I was thinking of implementing Assemble.io, as it's a static site generator that uses Handlebars and it sets up a nice foundation to begin building with the Bootstrap front-end framework. I also like that Assemble nicely separates files into layouts, templates, and partials.

The goal for this application/website is to pull data from a MongoDB and display it on the front-end. The front-end will consist of 100s of different content pages, so they will need to be easy to maintain. I also need clear distinctions from the front-end and back-end code, of course.

What might be the most logical way to go about setting up something like this? Is it possible to implement Assemble with ExpressJS? And if so, how would I set up my views in app.js to display Assemble files? Or would it be better to set view engine to handlebars and pull in CDN links to Bootstrap? (But if I did that, how would I setup layouts, templates, and partials?)


Solution

  • There are a few different approaches you can take.

    1. Pre-render page structures with assemble at build time. Then use front-end javascript to load data and render dynamic content.
    2. Use the assemble api in the server-side controllers to load the templates and data and render the content at run-time.
    3. Similar to (2), override the built in View class in express and do the loading and rendering with assemble in there.

    I would go with #2 right now so you can use the assemble api directly to load templates, data, helpers, middleware, etc... in your app.js. Then create a render function that you can use in your routes to take a page and render it...

    var express = require('express');
    var Assemble = require('assemble');
    
    var app = express();
    var assemble = new Assemble();
    
    // setup middleware
    assemble.onLoad(/\.hbs/, function(file, next) {
      // so something if needed
      next();
    });
    
    // load helpers
    assemble.helpers(['path/to/helpers/*.js']);
    // load async helpers
    assemble.asyncHelpers(['path/to/async-helpers/*.js']);
    
    // load templates
    assemble.layouts(['path/to/layouts/*.hbs']);
    assemble.partials(['path/to/partials/*.hbs']);
    assemble.pages(['path/to/pages/*.hbs']);
    
    // load global site data
    assemble.data(['path/to/site.json']);
    
    // render function to make looking up and rendering pages easier
    function render(name, locals, cb) {
      var view = assemble.getView(name);
      if (!view) return cb(new Error('Unable to find "' + name + '"'));
      view.render(locals, function(err, result) {
        if (err) return cb(err);
        cb(null, result.content);
      });
    }
    
    // setup some express routes
    app.get('/', function(req, res, next) {
      render('index', {title: 'Home Page'}, function(err, content) {
        if (err) return next(err);
        res.status(200); // I don't remember this api off the top of my head
        res.send(content);
      });
    });
    

    Hope this helps.