Several months ago I started work on a new project that required a web-based user-interface. I had been out of the HTML game for several years, spending time instead on Windows Forms and Flex-based applications. For this new web project, however, I wanted to retain some of the user-experience and development features that I came to enjoy working with traditional "thick-client" technologies.
And so, I set out to assemble my own framework using several of these individual libraries. In the meantime, and months after I began my own efforts, a wholy-inclusive SPA platform has become available called Durandal. Though I had my own framework mostly developed by this point I wanted to see what Durandal offered and how it compared to the features I had put in my own framework. To my surprise, the two frameworks were amazingly similar. This is most likely because the problem domain was identical, and many of the libraries Durandal uses are the same ones I chose:
jQuery for DOM manipulation. This is a no-brainer for me, though there are reasons to choose other DOM frameworks.
SammyJS for in-page "hash"-style routing. I have also implemented routing using Path.js.
Knockout for data-binding. This is turning out to be a pretty core piece of the developer experience since it abstracts away a lot of old-world direct DOM manipulation for form input values and label display.
While all these libraries (and many more ancillary libraries I haven't mentioned) are important in assembling a SPA framework, they don't solve the entire problem. While a routing library helps with determining the view the user wants to see, it doesn't actually help with view management per-se. So I developed a view framework where each view has an event lifecycle: initialize(), beforeShow(), show(), hide(), afterHide(). Not surprisingly, Durandal offers a similar view lifecycle. What appears to be missing from the Durandal framework (though, honestly, I haven't spent more than a few hours examining it) is an integrated user-authentication mechanism, as well as global error handling and the ubiquitous "404" handling for undefined view routes.