Partial update while supporting seo

Using NodeJs I'm trying to do something quite similar to Meteor: I want to send only the parts of a page that actually changed. My dilemma is that I know how to create such a framework to respond to link clicks and send partial updates but such a framework won't cater to direct browsing to a page other than the index (which is what is required for search engines and people without javascript to use your site).

I can also figure out how to make a framework to support entire page reloads, handlebars and a simple node server instance would take care of that. Hoeever, I can't figure out how to create a way that would allow me to write one method to tell the framework the partial updates for a page and let the framework figure out what else needs to be loaded.

A way I can think of would be to create the index page every time (for entire page loads) and apply partial updates to that but that can quickly become expensive if a subpage differs a lot from a very crowded index.

An example method would look something like this:

function images(id) {
    if (id == null) {
        // load all images from database
        template.images = db.result();
        template.content = template.loadblock('gallery');
    }
    else {
        // retrieve single image
        template.content = template.loadblock('single_image');
        template.image = db.result();
    }
}

On a partisl updste calling this method for domain.com/images would work just fine because it's clear what had changed. For an entire page load this function would miss things like a header, footer ,navigation, etc.

In an answer I would look for an example where this has been done or some tips that Can point me in the right direction. I'm sorry for any typoes I wrote this post on an ipad. If you have any questions about my question just ask and I'll update as needed.

Update: A possible example of a solution might be the following code. It's to give an idea, it probably won't actually run

// As a convention, don't pass around raw values if they aren't static but pass around functions such as
data.images = function () {
    // run db query
    // return an object with the images
}
// This constraint might be limited to the index() method

var routes = {
// This now allows us to do things like this:
index: function() { 
    var data;
    // Initialise everything needed for the index
    data.title = 'Index';
    data.nav = { Index: '/', Images: '/images' };
    data.content = 'Hello World';
},

categories: function() {
    var data;
    data.content = render('gallery', function () { /* load and return images as object */ }); // Not sure about this dynamic subtemplating but oh well
}

// This now allows us to do the following:
function request(page, type) {
    if (type == 'update') {
        if (routes[page] != undefined && typeof routes[page] == 'function') {
            respond(routes[page]());
        }
    }
    else {
        if (routes[page] != undefined && typeof routes[page] == 'function') {
            var data = mergeArrays(routes['index'](), routes[page]());
            // index.html which is just a Handlebars template
            respond(data);
        }
    }
}

Here is a pattern I often use (in Express apps):

function respond(req, res, name, resource) {
    if(req.accepts('json')) {
        // Send JSON to clients who want it
        res.send(resource);
    } else {
        // Render with layout only for non-XHR requests
        resource.layout = !req.xhr;
        res.render('resources/' + name, resource);
    }
}

Example usage:

app.get('/images', function(req, res, next) {
  getImages(function(err, images) {
    if(err) return next(err);

    respond(req, res, 'images', images);
  });
});

app.get('/images/:id', function(req, res, next) {
  getImage(req.params.id, function(err, image) {
    if(err) return next(err);

    respond(req, res, 'image', image);
  });
});

image.jade:

img(src=uri, alt=title)

images.jade:

#gallery
  for image in images
    include image

Clients who ask for JSON get that, otherwise they get the full page only if it's a non-XHR request. XHR requests get just the HTML snippet for the requested resource. This works well for quite simple apps, where resources mostly correspond to pages.