This repository has been archived by the owner. It is now read-only.
A simple web application supporting disconnection and deferred updates
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
app If client can't subscribe to faye, use a timer to periodically synchr… May 27, 2011
doc Initial commit May 15, 2011
script When a client does an update, the server broadcasts all clients using… May 18, 2011
Gemfile When a client does an update, the server broadcasts all clients using… May 18, 2011
Rakefile Initial commit May 15, 2011


No Maintenance Intended

Desligado: A simple web app supporting disconnection and deferred updates

Desligado is a proof-of-concept application made by junior developers.

It's a simple CRUD web app that runs both online and offline. Since it is meant to work when the client is disconnected from the web, and/or when the server is unavailable, it is heavily javascript based. Despite having a view for each one of the common actions (show, index, new and edit), it's a single-page application, since all necessary code (HTML, Javascript, and CSS) is retrieved with a single page load. Further communication is made using Ajax and HTML5 Web Sockets with JSON.

The resources are cached thanks to a HTML5 Cache Manifest file and the client keeps a synced local version of the data on a HTML5 WebSQL database (or, if not supported by his browser, on his Local Storage).

A special Thank You to James Yu and Zef Hemel.


Desligado is a simple item management application. Those are the functional requirements:

  • Users must be able to create, edit, destroy and list items
  • The item list must be updated, every time the server's database changes (without requiring any clicks)
  • Users must be able to use the app offline (static contents should be presented, and dynamic contents must function) even after closing and reopening the browser


  • Built with Ruby 1.9.2 and Rails 3.0.5
  • Faye gem (tested with 0.5.5)
  • Jammit! gem (tested with 0.6.0)
  • jQuery (included; version 1.4.4)
  • backbone.js (included; version 0.3.3)
  • persistence.js (included; version 0.2.4)


Supported Browsers and Caveats

Should work with, at least:

  • Chrome 11+
  • Mozilla Firefox 4+

It doesn't seem to work on Safari 5 (not fully tested), and Firefox will use local storage instead of WebSQL. Beware that, if the HTML layout file contains the reference to the application manifest, server pushing will not work. Comment out the reference <... manifest="application.manifest"> or just remove the public/application.manifest file to try it. This is a known issue.

The Application

The goal for this project was to create a multi-client simple web application with some basic functionalities (the creation, manipulation and deletion of shared items) that worked both online and offline.

Core technologies

To achieve the behaviour of keeping functionality in offline mode, we used several techniques introduced in HTML5 - Cache Manifest, WebSQL, Local Storage and Web Sockets.

Starting with the cache manifest, since we used Ruby on Rails for our back-end, to dynamically generate this manifest file we used the rack-offline gem, as suggested by Ryan Bates on his interesting railscast. Every time the user opens the website, all files required by the application are downloaded and saved for offline browsing. This solves the problem of accessing the static content in offline mode.

Another important aspect is that only one HTML page is fetched from the server. This page contains the necessary components to generate four views — index, show, edit and new. We used backbone.js and underscore templates to build them. Backbone.js let us implement a well-structured client-side application, but is not so rigid opinionated as Rails. To organize our client-side code, we followed the approach designed by James Yu on his article about backbone.js.

Javascript MVC framework

Backbone is composed by several modules. It contains one module called Backbone.sync which lets us persist data through RESTful JSON requests to the server. Since we want it to work offline too, we need it to persist the data locally, using the HTML5 WebSQL technology (if supported by the browser) or the Local Storage. This would be synced to the server, if possible, when both client and server are online. This is tougher than it may look, since we are talking about a multi-client app, with desynchronized clocks, etc..

Data synchronization

In what concerns persistence, we used persistence.js, and specifically the persistence.sync.js plugin, to keep the databases synced together. We created an adapter, a new Backbone.sync module, which maps the CRUD actions with the persistence.sync.js library's API.

Another problem is that persistence.sync was primarly made to communicate with node.js servers. Since we are using Rails, we coded the necessary mechanisms to make it work with RoR.

Server pushing

At last, we wanted the server to broadcast to all connected clients when one of them modifies the server's database. We integrated Faye for the server to client communication, which uses WebSockets, XMLHttpRequest (if WebSockets not supported) or JSON-P (if no other alternative is supported). We are still having some crazy issues regarding having both Faye and the application.manifest) which are listed on the bottom of this document.

Directory structure



To initialize the application, run:

mv config/database.yml.sample config/database.yml
mv public/application.manifest.sample public/application.manifest
bundle install
rake db:migrate


Run Faye:

rackup script/ -s thin -E production

Run the Rails sever:

rails server


A list of the current issues will be added soon.

Change log

For now, you may check our github page to keep track of all the undergoing changes.


Feel free to use the code for your own projects. Improvements are very welcome (keep in mind that we are junior developers, with no background on Javascript, asynchronous programming and all the like). Pull requests to our git repository would be greatly appreciated!