The app is built in Node.js and uses the REST API as its data store. We’re proud to have built the entire app on an open-source stack, and plan to share a lot of our code in the coming months.
We aimed to follow best practices throughout: DRY modular code; automated deployment, provisioning, and continuous integration; (a goal of) 100% automated front-end testing; two-week sprints and releases, with scrums combining dev+QA+UX+product; utilizing the latest browser capabilities while degrading gracefully for older browsers; and using Git-flow and Github-style workflows.
The project first began in June 2012 with one developer and a vision of building the next-generation web app as a front-end layer on top of the API. After a period of prototyping and setting the groundwork, the project (codenamed “Martini”) kicked into high gear around a year ago. The team now consists of twelve developers, including three dedicated to QA automation; a team of designers, two product managers, and all the other amazing support (ops, program management, facilities) that keep the servers humming and the stars aligned.
We launched a public beta in September, and became DocuSign Beta; now we’re official, but we still affectionately call the project and team Martini.
To support the entire new experience, our API grew from serving a relatively narrow set of third-party use cases to supporting every customer-facing application function. Not all of these API features are public yet, but they will be soon.
Beautiful user interface
Our in-house design team did incredible work designing the interactions and visuals of the new experience. Our first developer, Derek, has an incredible passion for pixel-perfection and seamless UI’s that led to a wonderful dev-design collaboration. We used CSS3 (and where necessary, jQuery animations) to bring the designs to life. If you’re using the app and are impressed by a smooth transition or subtle effect, Derek is the main reason.
We built a layer on top of Backbone.js which enables modular, re-usable components and a very snappy UI. Models are the basic building blocks and their types and hierarchy are shared between client and server. Routes are defined in a “route data” mapping, with the models and attributes that belong to each route. The server processes this mapping through Express middleware, and the client through the Backbone router. On initial load, the server knows all the data that the client wants and gets it from the API; when the browser asks for the same data a moment later, the data is either already in Redis to be delivered instantly, or on its way. Subsequent routes are handled entirely on the client when possible (degrading gracefully back to IE8).
The models have views associated with them in the route-data mapping; each view attaches itself to a parent element, down from the thin layout rendered on the server to any level deep of client-side nesting. Everything is decoupled and DOM elements that should persist from one route to another are left intact.
We plan to extract this framework from the app and open source it. We think it is well suited to apps like ours: API-backed, client-heavy (everything is authenticated so we have no need to render from the server to search engines), with a complex data hierarchy and multi-use components.
This has been one of the most challenging parts of the journey so far, and while we we haven’t quite achieved 100% automated test coverage, we are getting close, and in the process we have built a testing tool chain that we want to open-source. Our test runner parallelizes multiple Mocha tests simultaneously and aggregates the results into a single XUnit file for Jenkins. Our “driver wrapper” adds a layer of utilities to the WD module. We’ve added syntactic sugar on top of Mocha to define test levels (smoke, acceptance, etc) inline. The tests can run in PhantomJS via GhostDriver (which we’ve improved to handle file uploads) or via a real browser using Selenium, as well as with numerous virtual browsers via SauceLabs.
Redis Sentinel client
As we wrote a few months ago, we are using Redis Sentinel with master/slaves for failover and redundancy, and we wrote a node.js client to make Sentinel seamless, working the same as a regular Redis client. (We’re also looking forward to Redis Cluster and hoping it will take Redis reliability to the next level.)
The last few months have been heads-down in the code finishing the features and fixing bugs for our launch. Now that we’re live, we’re looking forward to taking a deep breath and a step back, and re-imagining even more. We made assumptions and decisions a year ago that we might make differently on a blank slate today. We wrote a lot of code that serves general use cases, and we want to share that with the open source community, to give back and get valuable feedback. Like any big software project, we have technical debt to clean up and test suites to finish. And of course, we still have tons of features to build, known and yet-unknown, for the future of Digital Transaction Management.
So sign up for an account and try it out! We hope you love the new experience and look forward to learning from all your feedback.