Home

Awesome

IBM Cloud Deployments

Create an Offline First Shopping List with Polymer and PouchDB

In this code pattern, we will create an Offline First shopping list. Shopping List is an Offline First demo Progressive Web App built using Polymer and PouchDB. This app is part of a series of Offline First demo apps, each built using a different stack. Credit goes to Bradley Holt for this Polymer/PouchDB implementation.

When the reader has followed this code pattern, they will understand how to:

Flow

  1. The user manages shopping lists using the Offline First web app.
  2. Polymer is used to make it a Progressive Web App with Web Components and Service Workers.
  3. The shopping lists are stored locally in PouchDB while offline.
  4. When online, PouchDB syncs with Cloudant.

With Watson

Want to take your Watson app to the next level? Looking to leverage Watson Brand assets? Join the With Watson program which provides exclusive brand, marketing, and tech resources to amplify and accelerate your Watson embedded commercial solution.

Included components

Featured technologies

Key concepts

This shopping list app is a small single page web application built using Polymer and PouchDB library. The web app will allow multiple shopping lists to be created (e.g., Groceries, Camping Supplies) each with a number of shopping list items associated with them (e.g. Mangos, Oranges).

So what sets this app apart? Its Offline First architecture. The Offline First approach plans for the most constrained network environment first, enabling a great user experience even while the device is offline or has only an intermittent connection, and providing progressive enhancement as network conditions improve. This design also makes the app incredibly performant (fast!) on the best of networks.

PouchDB, CouchDB, and Service Worker are the primary tools that turn our simple shopping list app into a high performance, offline-capable Progressive Web App.

Data stays safe on your device, even while it's offline. Persistance of shopping lists and item data entered by the user is achieved using the in-browser database PouchDB. This will allow your data to survive between sessions and when disconnected from the network. (Whether you remember that you need juice while you're on your trusty home Wi-Fi or in the middle of the wilderness, you can still add it your list.)

Data syncs between devices when a connection is available. When a connection is available, the data is synced from the local device to a CouchDB database in the cloud, and can thus be shared across multiple devices or users. (Need to share your grocery list with your roommate or access it on both your phone and your laptop? No problem!)

The app loads quickly, even while offline. To keep the app itself functional while offline, a Service Worker is used to cache page resources (the most important HTML, CSS, and JavaScript files) when the web application is first visited. Each device must have a connection for this first visit, after which the app will be fully functional even while offline or in shoddy network conditions. (No more error messages or frustratingly slow page loads.)

The app can be installed on a mobile device. In combination with the Service Worker used for caching, a manifest file containing metadata allows the app to become a Progressive Web App, an enhanced website that can be installed on a mobile device and can then be used with or without an internet connection. (It's secretly still a website, but you can access it through one of those handy dandy little app icons on your homescreen!)

Explore the code in this GitHub repository to see how the Offline First design is applied.

Watch the Video

Steps

Deploy to IBM Cloud

Deploy to IBM Cloud

  1. Press the above Deploy to IBM Cloud button and then click on Deploy.

  2. In Toolchains, click on Delivery Pipeline to watch while the app is deployed. Once deployed, the app can be viewed by clicking View app.

  3. To see the app and services created and configured for this code pattern, use the IBM Cloud dashboard. The app is named shopping-list-polymer-pouchdb with a unique suffix. The following services are created and easily identified by the slpp- prefix:

    • slpp-CloudantNoSQLDB

Run locally

NOTE: These steps are only needed when running locally instead of using the Deploy to IBM Cloud button.

  1. Clone the repo
  2. Install the prerequisites
  3. Run the server
  4. Create a Cloudant or CouchDB service

1. Clone the repo

Clone the shopping-list-polymer-pouchdb locally. In a terminal, run:

$ git clone https://github.com/ibm-watson-data-lab/shopping-list-polymer-pouchdb

2. Install the prerequisites

First, install Polymer CLI using npm (we assume you have pre-installed Node.js):

npm install --global polymer-cli

Second, install Bower using npm:

npm install --global bower

Third, install the Bower npm resolver:

npm install --global bower-npm-resolver

3. Run the server

This command serves the app at http://127.0.0.1:8081 and provides basic URL routing for the app:

polymer serve

4. Create a Cloudant or CouchDB service

PouchDB can synchronize with CouchDB and compatible servers. To run and test locally, you can install CouchDB. Alternatively, you can use a hosted Cloudant NoSQL DB service for your remote DB.

Installing Apache CouchDB

Install CouchDB 2.1. Instructions are available for installing CouchDB 2.1 on Unix-like systems, on Windows, on Mac OS X, on FreeBSD, and via other methods.

Configure CouchDB for a single-node setup, as opposed to a cluster setup. Once you have finished setting up CouchDB, you should be able to access CouchDB at http://127.0.0.1:5984/. Ensure that CouchDB is running and take note of your admin username and password.

Creating a Cloudant NoSQL DB service

Sign up for an IBM Cloud account, if you do not already have one.

Once you are logged in to IBM Cloud, create a new Cloudant instance on the Cloudant NoSQL DB Bluemix Catalog page. This should take you to a page representing the newly-created service instance. Click the "Service credentials" link. You should have one set of service credentials listed. Click "View credentials" which should show you a JSON object containing your service credentials. Copy the value for the url key to your clipboard (the value will be in the form of https://username:password@uniqueid-bluemix.cloudant.com).

Database and replication setup

  1. Create the remote database
  2. Enable CORS
  3. Set the replication target

1. Create the remote database

Use your Cloudant or CouchDB dashboard to create a database. Select the Databases icon on the left and then use the Create Database button to create the "shopping-list" database. The Shopping List app can be used locally before the database exists, but cannot sync until the remote database is completed.

2. Enable CORS

Cross-Origin Resource Sharing (CORS) needs to be enabled. Use your Cloudant or CouchDB dashboard to enable it. The CORS options are under the account settings or config depending on your version. Enable CORS and restrict the domain as needed for security.

3. Set the replication target

Run the Shopping List app and use the Replicator form to enter your Database URL. If you use the Bluemix Cloudant URL taken from the service credentials as described above, the URL includes user and password GUIDs.

Add /shopping-list to the URL to connect to the database that you created.

Using the app

The app allows you to create a shopping list by clicking on the plus sign. Click on the list to see its items. Then, you can add items to the list by clicking the plus sign. There is a checkbox to allow you to mark the items complete as you buy load up your cart.

When you have not configured your Replication Target or when you are offline, the lists will not sync. One good way to test this is to run two browsers. You can use Chrome and Firefox and have different lists in each.

When you go online and have the database and CORS enabled and the Replication Target is set, the shopping lists will sync. You will then be able to use both lists from either browser.

Features as epics

Shopping List is a simple demo app, with a limited feature set. Here is a list of features written as user stories grouped by Epic.

Not all features are implemented in the current Polymer app. This demo app does not yet include item/list removal, geolocation features or multi-user features.

Building for production

The polymer build command builds your Polymer application for production, using build configuration options provided by the command line or in your project's polymer.json file.

You can configure your polymer.json file to create multiple builds. This is necessary if you will be serving different builds optimized for different browsers. You can define your own named builds, or use presets. See the documentation on building your project for production for more information.

This app is configured to create three builds using the three supported presets:

"builds": [
  {
    "preset": "es5-bundled"
  },
  {
    "preset": "es6-bundled"
  },
  {
    "preset": "es6-unbundled"
  }
]

Builds will be output to a subdirectory under the build/ directory as follows:

build/
  es5-bundled/
  es6-bundled/
  es6-unbundled/

Run polymer help build for the full list of available options and optimizations. Also, see the documentation on the polymer.json specification and building your Polymer application for production.

Previewing the build

This command serves your app. Replace build-folder-name with the folder name of the build you want to serve:

polymer serve build/build-folder-name/

Running the tests

This command will run Web Component Tester against the browsers currently installed on your machine:

polymer test

If running Windows you will need to set the following environment variables:

Read More here daffl/launchpad

Adding a new view

You can extend the app by adding more views that will be demand-loaded e.g. based on the route, or to progressively render non-critical sections of the application. Each new demand-loaded fragment should be added to the list of fragments in the included polymer.json file. This will ensure those components and their dependencies are added to the list of pre-cached components and will be included in the build.

Deploying to GitHub Pages

If you are deploying to a Project Page then you will first need to modify the base URL and root path values in index.html to match your project name. For example, for the project name shopping-list-polymer-pouchdb change:

<base href="/">

To:

<base href="/shopping-list-polymer-pouchdb/">

And change:

window.Polymer = {rootPath: '/'};

To:

window.Polymer = {rootPath: '/shopping-list-polymer-pouchdb/'};

You can then deploy the app to GitHub pages by running:

npm run deploy:gh-pages

App architecture

This app uses a drawer-based layout. The layout is provided by Polymer's app-layout elements.

This app, along with the polymer-cli toolchain, uses the "PRPL pattern" This pattern allows fast first delivery and interaction with the content at the initial route requested by the user, along with fast subsequent navigation by pre-caching the remaining components required by the app and progressively loading them on-demand as the user navigates through the app.

The PRPL pattern, in a nutshell:

Live demo

https://ibm-watson-data-lab.github.io/shopping-list-polymer-pouchdb/

Tutorial

Refer to the tutorial for step-by-step instructions on how to build your own Offline First shopping list Progressive Web App with Polymer and PouchDB.

Links

License

Apache 2.0

Privacy Notice

Refer to https://github.com/IBM/metrics-collector-service#privacy-notice.

Disabling Deployment Tracking

To disable tracking, simply remove require('metrics-tracker-client').track(); from the app.js file in the top level directory.