Offline First Apps for Indians – Part 1

In 2015 I drove across India. It involved some of the most developed areas to very remote places. In some places it was difficult to get couple of hours of electricity. Connectivity was very patchy and in some places non-existent. In 2017 things have improved but not uniformly across India. Most of India is still offline or on very bad mobile internet connection.

Though the Digital India program is pushing everything to go online. The most popular Apps or Services in India are adding offline features. This shows consumers want offline features or expect the apps to work well when offline. India is not just a MobileFirst market but also an OfflineFirst.

Recently I was involved in designing tech architecture for an App meant for Indians. It was going to be a MobileFirst for sure but I also pushed for OfflineFirst features. The choice of technologies wasn’t that difficult. I went for cross-platform React Native for building apps. And then it was CouchDB backend with PouchDB in the front for the data storage. This Couch-Pouch setup also gives us Offline/Sync support. We will also use server-side data warehousing for analysis and reporting.

In this series I am going to write about the overall architecture, design. I will also add minimal setup and code examples for developers to bootstrap. In this first post we will set up the front end to work with PouchDB-CouchDB.

CouchDB and Cloudant by IBM

CouchDB is a NoSQL document database which is made for web applications. It supports restful APIs out of box. Data is stored in JSON format and can be queried using MapReduce or Mango. But the best part of CouchDB is synchronization. Various CouchDB instances can synchronize as soon as they can connect to each other.

This is what makes it best database for OfflineFirst apps. You can use, edit, modify data while offline. As soon it gets network connection it can sync.

It’s not super difficult to run your own CouchDB. But maintaining a server is not something everyone likes to do. This is where Cloudant, hosted CouchDB by IBM is useful. It also comes with Geospatial index. Else one has to build and install GeoCouch to get the geospatial support. Cloudant can also integrate with IBM’s DashDB which is a hosted data warehouse. You could do your extensive reporting and analysis on DashDB.

The biggest advantage I see with the hosted CouchDB/Cloudant is the reliability of IBM. IBM’s cloud computing is probably top three along with AWS and Google computing. But the other two don’t offer hosted CouchDB. The second advantage is the ability to move to a different vendor or host it yourself at any point. It’s easy to export data from Cloudant and host it with your instance CouchDB. No vendor lock-in.

React Native and PouchDB

PouchDB is an open-source JavaScript database that can run inside the database. PouchDB syncs to CouchDB effortlessly. Hence it was our first choice on client side. PouchDB has two adapters for local storage. It’s easy to boot up with built-in Async storage. I prefer SQLite backend as it’s much faster.

To start we need to install the React Native PouchDB package for PouchDB support with Async storage backend.

npm install pouchdb-react-native --save

By default we will get core PouchDB with some plug-ins like async-storage backend , mapreduce, replication etc. We can also add extra plug-ins if required. For example if you like to use “find” then install the corresponding package

npm install pouchdb-find --save

And in your code include the plugin

import PouchDB from 'pouchdb-react-native'
import find from 'pouchdb-find'
PouchDB.plugin(find)
//create DB
Db = new PouchDB('mydb', {adapter: 'asyncstorage'});

For our SQLite backend support for PouchDB, Along with pouchdb-react-native we need to install SQLite specific NPM packages

npm install pouchdb-react-native --save
npm install pouchdb-adapter-react-native-sqlite --save
react-native install react-native-sqlite-2

And in our code

import PouchDB from 'pouchdb-react-native'
import SQLite from 'react-native-sqlite-2'
import SQLiteAdapterFactory from 'pouchdb-adapter-react-native-sqlite'
 
const SQLiteAdapter = SQLiteAdapterFactory(SQLite)
PouchDB.plugin(SQLiteAdapter)
const db = new PouchDB('mydb.db', {adapter: 'react-native-sqlite'});

That’s on all the front end to start using a DB. To sync the local DB to remote one can use

localDatabase.sync(this.remoteDatabase,{live: false, retry: true})

Where remote DB is a CouchDB url. If you have it hosted on Cloudant then it will look like

https://<username>.cloudant.com/<database>

If you are running your own CouchDB on a server then 1

https://<server>:5984/<database>

You can use various authentication and authorization schemes that CouchDB supports for your application. I personally prefer Cookie/Session based authentication. I also use PouchDB authentication package for this. This package makes registration and login a piece of cake. A simple remote db sync after login will look like this

var remotedatabase = new PouchDB('https://localhost:5984/mydb', {skip_setup: true});
var localdatabase = new PouchDB('local_db');

localdatabase.put({
  _id: 'myfirstdocument',
  title: 'My first Document'
}).then(function (response) {
  // handle response
}).catch(function (err) {
  console.log(err);
});


remotedatabase.login('username', 'password', function (err, response) {
  if (err) {
    if (err.name === 'unauthorized') {
          console.log("unauthorized");    
    } else {
      console.log("error while login");
    }
  }
      //Login sucessful. Let’s sync to the remote
      localdatabase.sync(remotedatabase, {live: true, retry: true}).on('error', console.log.bind(console));
});

These few lines of code show how the data can be inserted locally and then can be synced to the remote database. This is the starting point for many OfflineFirst apps.

Of course in this post I have not covered schema design, Authentication and Authorization etc Those are very important topics to learn before one designs an App. They are also huge topics and hence I will make use of a separate blog post.

Note: This post was written with inputs from IBM.

Footnotes

  1. The default configuration of CouchDB is insecure http. You can enable https very easily. Its important.

2 Responses

  1. Konark says:

    Nice !
    Just a small comment, even if you are running your own server, it should be HTTPS not HTTP.