This week, PouchDB v3.4.0 was released with Couchbase Sync Gateway compatibility.

In this post, we’ll take the existing TodoMVC example and add filtered sync using Facebook authentication. In addition to syncing between Web clients, we’ll change the data model slightly to sync with the existing ToDoLite apps running on iOS and Android:

To follow along, you can open and run the TodoMVC example at commit d9bb961. For convenience, I’ve added the Facebook login code in app.js. When the user logs in, the function startSessionAndSync(accessToken, userId) is called. Now let’s add the code to make it happen!


Make sure to serve the app on port 9000 as we will configure CORS for localhost:9000 later. The simple python command should do:

Data modelling

TodoMVC and ToDoLite have a slightly different data model. In ToDoLite apps, a user can create multiple lists and share them with multiple users.

First let’s look at a Task document with the expected title property and a list_id referencing the List it belongs to (in this case 123):

Likewise, a List document also has a title and an owner referencing the user it belongs to:

TodoMVC however is a single list app. To keep things simple we can insert the List document in code as soon as the user logs in.

Let’s create a new function called migrateGuestToUser to create the List document with the user id and save it to PouchDB:

Note: It’s very important to set the owner field, the sync function will reject the document otherwise.

And we can call it in startSessionAndSync:

Task documents belong to a list and so they have a list_id property we need to set. Change the addTodo function in app.js to look like below. Notice we set the list_id field to the hardcoded _id of the list we inserted above:

Now we have the appropriate documents conforming to ToDoLite’s data model we can take a look at authentication and replication.

Enabling CORS on Sync Gateway

In this tutorial, we’ll run a local instance of Sync Gateway on localhost:4984 but we’re serving our web app on localhost:9000. At this point we’d get a same origin policy error. But Chris recently added CORS support to Sync Gateway for this purpose. So we don’t have to write one line of server side code :)

CORS allows web apps to access resources on other domains than the origin domain. By enabling CORS on Sync Gateway we’re telling the browser “Yes, the Sync Gateway domain name is allowed to communicate with this web app”. Open sync-gateway-config.json with the extra CORS configuration to enable it on localhost:9000:

Use Sync Gateway 1.1 or later. Start it with the config file:

Back in app.js, update the remoteCouch url accordingly:

Now if we tried to sync the list to Sync Gateway we’d get a 401 Unauthorized error. Let’s fix that by creating a user session with Facebook login.

Authenticating with Sync Gateway

To authenticate with Sync Gateway we can send a POST request to /todos/_facebook with the access token, if we get back a 200 OK, the browser will set the session cookie returned from Sync Gateway for future push/pull replications.

Note: It’s important to set request.withCredentials = true in a CORS request to save the cookie returned from Sync Gateway for future authenticated requests (push/pull replications).

Call it in startSessionAndSync passing the accessToken we got back from Facebook:

Wrap up

Now open up your browser, you can test todo items are syncing with another browser window opened or the native apps running TodoLite.

Users can still create tasks without being logged in. But the minute a user logs in, the tasks belong to the user’s list. Providing a guest account feature is one of the many benefits of building for offline-first capabilities.

Notice the TodoMVC list document is displayed as a task in Chrome. That’s because this example was using the allDocs query to display tasks.

In the next post, we’ll use Map/Reduce queries to add the multi-list capability and a profile document as well to share them with other users.

Read more:


Posted by James Nocentini, Technical Writer, Mobile, Couchbase

James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for in his spare time.


  1. Nuthan Santharam April 29, 2015 at 8:56 am

    Hello James, Thanks for the tutorial. Any idea how to enable CORS on sync gateway for Windows machine?

    the build of commit e8cf146. Can I execute this on a Windows machine?

    When I try to run the sync_gateway with the json config, It throws:

    XMLHttpRequest cannot load http://localhost:4984/todos/_facebook. No \’Access-Control-Allow-Origin\’ header is present on the requested resource. Origin \’http://localhost:9000\’ is therefore not allowed access.


  2. Florion COIFFÉ June 16, 2015 at 5:33 pm

    I am using Sync Gateway that I build from the current master on Github. Is this supposed to include CORS and PouchDB support ?
    For me it doesn\’t, the browsers tells me \”No \’Access-Control-Allow-Origin\’ header is present on the requested resource\”.

    In my config.json file I added the CORS lines:

    \”CORS\”: {
    \”MaxAge\”: 1728000

    Do you have any idea why ? :)

  3. CORS is not working for me !!!! still No \’Access-Control-Allow-Origin\’
    any solution?

    1. James Nocentini July 12, 2015 at 12:16 pm

      Are you using Sync Gateway 1.1? You can follow this tutorial as well to setup CORS/PouchDB and Web Push Notifications…. Let me know if it\’s still not working for you.

  4. In the video you have a browser opened with a webpage. Is it part of the Sync Gateway? Do you have to install it separately?
    I tried to access it but only got 404s.

    1. Nevermind. The admin interface only accepts connection from

  5. Hi James

    CORS is Not working for me.
    XMLHttpRequest cannot load <host url=\”\”>. Response to preflight request doesn\’t pass access control check: The \’Access-Control-Allow-Origin\’ header contains the invalid value \’\’. Origin <origin url=\”\”> is therefore not allowed access.

    On sync the Request has the Local url for the \’ORIGIN\’ and gateway as the \’HOST\’. But the Response Header > \’Access-Control-Allow-Origin\’> is Null and the request is throwing a 204 No Content .

    The Sync Gateway was also Configured for Specific ORIGIN / All URLs still having the same Issue.

  6. CORS errors here too. I\’ve posted the following StackOverflow question if anyone has time to take a look:

Leave a reply