Recently, at Sidelab, we developed and deployed signforms.com, an application for signing documents online, in 14 days. The application runs on a node.js back-end, using amazon web services. One interesting thing about the application is that it uses effectively no HTML.

There are a few static html files for the lander site, but once logged in, there is only one .html file. Other than script tags to load the application for the very first time, the file looks like this:

</head> <body> </body> </html>

After that, no HTML is ever sent.

Don’t believe me? Sign up (its free currently), log in, then view source. You will see nothing but JSON.

WAT!?

The front end of SignForms is build using an opensource framework called Gaffa. Once the application has been loaded, all navigation is achieved via requests for JSON resources.

Oh, so it’s client-side templating.

No, there are no templates, ever. When we work on SignForms, we never write HTML, or HAML, or any kind of ML. We write JavaScript ‘pages’ that are made up of ‘view items’ such as containers, textboxes, buttons etc. For cache-ability we serialize these pages to JSON for the application to consume.

In your browser, Gaffa takes the serialized page, inflates it into objects, then generates the DOM required to display the page, and adds all other functionality such as event handlers, page load, and autosave behaviours that are required.

Why?

I’m not a fan of HTML, it’s not something humans should write. One thing that people usually seem to forget is that HTML is a sibling to XML. The majority of people would prefer not to write XML, but have no issues writing HTML. This seems strange to me. The other thing people seem to forget is that HTML is a serialization format for DOM, it is verbose and inflexible.

One commonly seen flow of data for a web application is as follows:

Developer:

Write ‘Views’ in HTML

Add magic strings to tell the server where to put more strings

Server

Scan massive string, stringify data and concatenate the extra strings to the original string

Send massive string across the wire

Don’t cache it because it will change next time.

Client

Parse massive string

Correct any invalid HTML, take a best guess as to what it was supposed to be

Convert strings into DOM

Render the DOM

The way Gaffa handles navigation is different:

Developer:

Write code

File watcher auto-serializes to JSON

Server:

Serve JSON Page, cache for next time.

Serve DATA.

Client:

Parse JSON into ‘viewItems’.

Apply Data to ‘viewItems’.

render DOM (Or Canvas, or webGL, or google map markers, or any other logical view).

There are a few big advantages:

Only one HTML page is ever sent, once, and it’s tiny (2KB uncompressed)

Developers write code, not an XML derivative.

Application pages are cached indefinitely, and are tiny (17 KB uncompressed and unminified for a feature rich page)

The server only serves data, reducing load.

Page-weight is microscopic. (<0.5 MB per page for everything, including all images, css, and data)

Pages render stupid-fast (~1s for a complicated, data-bound page).

Gaffa achieves this by creating a declarative programming abstraction for the UI. If you want to display a textbox, and bind it’s value to the model, you would create a textbox viewItem:

var myTextbox = new textbox(); myTextbox.value.binding = '[myValue]';

Other views can bind to the same value in the model:

var myLabel = new label(); myLabel.text.binding = '[myValue]';

And the data can be manipulated before displaying it:

myLabel.text.binding = '(join " " "hello person, your value is" [myValue] "which is" [myValue].length "characters long")';

Then you add the viewItems to gaffa:

gaffa.views.add([myTextbox, myLabel]);

And you’re done.

Because viewItems are rendered as DOM, you can use CSS to style them as you normally would, and end up with a fast, feature rich web application in a very short period of time.

As to be expected from my previous post, this application forgoes the usual “Don’t think, include” librarys such as jQuery, bootstrap, etc, and instead uses small components that do exactly the job required.

A few libraries/technologies used:

JS:

CSS: