Prototype web applications with CouchDB and Bootstrap

Separate web design from database design, then glue them back together


Apache CouchDB is one of a new breed of database management systems (DBMSs) within the NoSQL movement. The primary information is stored as JavaScript Object Notation (JSON) documents. CouchDB also supports more general document formats as managed attachments. What it does not support is the classic tabular data, which is queried by SQL, that ruled the DBMS world for decades. Another key characteristic of CouchDB is that all of its operations are available as simple HTTP calls, particularly in the REST (Representational State Transfer) form. This architecture makes it easy to work with CouchDB regardless of your host platform or toolkit. It also makes CouchDB a useful tool for providing a persistent back end for websites and applications.

You can find several tutorials to get you started with CouchDB for application development using its built-in JavaScript libraries and related tools such as CouchApp (see Related topics). In this article I take a different approach, showing that you can prototype websites quickly by combining CouchDB with a simple, statically served website scaffold.

One popular, new way to rapidly set up a website's front end is Bootstrap. The Bootstrap system was developed by Twitter engineers to help tame the zoo of platforms and toolkits that they used for website development. Bootstrap provides a consistent framework for web application UIs. It makes it easy to design beautiful sites with cascading style sheets (CSS) elements for typography, forms, buttons, tables, grids, navigation, alerts, and much more. In this article, learn to kickstart the development process with Bootstrap for the front end and CouchDB for the back end — even for complex web applications.

Why not prototype entirely on the CouchDB stack?

Although many tutorials show how easy it is to develop a complete production website entirely on CouchDB, it is not advisable. Getting started that way leaves a huge temptation to cut corners and use the same approach when the site goes public. From a security and maintenance perspective, it is better to separate the database back end from the presentation front end. This article gives you various options for locking down the CouchDB instance when it goes live to secure any sensitive data. Security always requires vigilance and expertise. Because websites based on static files have been around longest, they are best understood, and their management tools are most mature.

Separating CouchDB from the website front end gives you another advantage because multiple frameworks are typical during web development:

  • The DBMS for handling data
  • The web server or content-management system
  • The web design framework

In this article I use CouchDB, Apache HTTP Server, and Bootstrap.

The personnel, skill set, and criteria for choosing technology for these layers are often varied. You want decisions for one to be loosely coupled with decisions for another. In addition to them, you have moving parts such as content-delivery networks, testing frameworks, middleware to support security, and more. The more flexibility that you allow for mixing and matching these components, the easier the system is to maintain and improve in the medium and long term.

The technologies that I selected for this article reflect my database management specialization. Apache and Bootstrap are just tools that help me get the application off the ground rapidly. I expect to collaborate with other specialists after the basics are in place. A middleware developer might prefer to continue with a web server framework such as Django or Ruby on Rails, or even a content-management system such as WordPress — so I use Apache in such a way that it can be replaced without greatly affecting the other layers. A web designer would most likely prefer a hand-crafted design rather than Bootstrap, so I use Bootstrap in such a way that it is easily replaceable. Thanks to modern tools and frameworks, it is not a great deal more complicated to prototype web applications in this way, rather than relying on a single, monolithic stack.

Getting started

I will present a simple web application demo: a site for poetry quotes. For help with the installation of CouchDB, see Related topics. Once you have CouchDB running on a server, download either the plain Twitter Bootstrap, which is just a bundle of CSS and JavaScript, or the full project bundle. I am working with the full bundle in this article.

I started with the fluid.html example from the Twitter Bootstrap bundle. I trimmed the file, fixed CSS and JavaScript scripts to remove the leading ../assets/, and updated some of the static content for the example site. The result, which I saved as index.html, is in the code bundle for this article (see Download). A significant portion of the HTML page header is in Listing 1:

Listing 1. Part of the index.html page header
<!-- Styles -->
<link href="css/bootstrap.css" rel="stylesheet">
<style type="text/css">
  body {
    padding-top: 60px;
    padding-bottom: 40px;
  .sidebar-nav {
    padding: 9px 0;
<link href="css/bootstrap-responsive.css" rel="stylesheet">

<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
  <script src="//"></script>

Listing 2 is part of the index.html table into which featured quotations are loaded from CouchDB:

Listing 2. Part of the index.html table into which featured quotes are loaded
<div class="row-fluid">
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>
  <div class="span4 featured-quote">
    <h2>Poet's name</h2>
    <p>Body of quote here.</p>
    <p><a class="btn" href="#">View details &raquo;</a></p>

This page also includes a mechanism for interacting with the database. In particular, the sidebar includes a form that the user can use to create new quote records. The user accesses the form by clicking a link, which triggers jQuery to make the form appear. Listing 3 shows the form markup. (The first two <input> lines are split to fit this article's page-width limitations.)

Listing 3. The form from index.html for creating a new quote record
<a href="#popup" id="popup">Click to create a new quote</a>
  <form id="newquote" action="index.html">
      <legend>The quote</legend>
      <label for="author">Author's Name</label>
      <input id="author" name="author" type="text" placeholder="First and last name" 
          required="required" autofocus="autofocus">
      <label for="text">Text of the quotation</label>
      <input id="text" name="text" type="textarea" placeholder="Text of the quote here" 
      <legend>The work</legend>
      <label for="title">Title of the work</label>
      <input id="title" name="title" type="text" required="required">
      <label for="link">Link to the work</label>
      <input id="link" name="link" type="text" required="required">
      <label for="year">Year of the work</label>
      <input id="year" name="year" type="text" required="required">
    <input id="donewquote" type="submit" value="Add quote" />

Listing 4 is the section near the end of the index.html page body that loads the necessary JavaScript. The last script line has the specific code for working with the poquotes database in CouchDB.

Listing 4. Loading JavaScript near the end of the index.html page body
<!-- Placed at the end of the document so the pages load faster -->
  <script src="js/jquery-1.7.1.js"></script>
  <script src="js/bootstrap.js"></script>

  <script src="js/poquotes.js"></script>


In less than 5 minutes, Bootstrap made it possible for me to enjoy the basic setup of a website that offers the most modern features, including graceful support in older browsers and on mobile devices. For your own website, update the colors, fonts, images, and other details to suit your design. You can visit the Bootstrap gallery for plenty of inspiration (see Related topics).

Preparing the data

In Listing 2, notice the div elements of the featured-quote class. I will load the data from CouchDB into those elements. The main page features six prominent quotes that are loaded dynamically by the page script and replace the current boilerplate.

Go to Futon, the CouchDB browser-based console — for example, at http://localhost:5984/_utils/ — and create a database named poquotes, as in Figure 1:

Figure 1. Setting up the poquotes database from the CouchDB Futon page
Screen capture from the CouchDB Futon page setting up the poquotes database
Screen capture from the CouchDB Futon page setting up the poquotes database

Listing 5 is a sample document that contains the information for a quote. (The fourth line is split in two to fit this article's page width.)

Listing 5. Sample JSON document for a quote
    "type": "quote",
    "author": "Thomas Hardy",
    "text": "And as the smart ship grew<br>In stature, grace, and hue<br>
In shadowy silent distance grew the Iceberg too.",
    "work": {
            "title": "The Convergence Of The Twain",
            "link": "",
            "year": 1915

I loaded this file as q1.json into the new database using cURL:

curl -u user:passwd -X POST http://localhost:5984/poquotes \
 -H 'Content-Type: application/json' -d @q1.json

The response from CouchDB (which starts with {"ok") indicates that the document was added and gives the generated ID and revision of the new document. CouchDB's RESTful nature makes prototyping data sets for the site almost as easy as manipulating the file system. You can also use Futon to add documents, if you prefer. The downloadable sample code for this article includes six such quote documents — enough to fill the grid of the target page.

Preparing the main query

I used Futon to design a view to load the documents needed for the web page. In Futon you can design temporary views, test them, and then save them for actual use. If possible, design your views early in your development cycle while you have only a few documents in the database because temporary views can quickly slow down. Listing 6 is the view JavaScript:

Listing 6. CouchDB view used to get all quote documents, indexed by year of source work
function(doc) {
  if (doc.type == "quote") {
    emit(, doc);

The view is simple, but it does the trick, indexing the results by year of the work because that is how I want to sort the records into the page. To add this view to your database, click the View selector and switch to Temporary view. Then, you can paste Listing 6 into the Map Function box. Click Run to see a table listing of six documents. If that works, save the view with the design document name of by_year. It is no longer a temporary view. You can then go back to trusty cURL to exercise the view:

curl "http://localhost:5984/poquotes/_design/poquotes/_view/\

The GET parameters (&descending=true&limit=6) adjust how the database delivers the query results. In this case only the six most recent documents are returned in descending order, ensuring that the document with the most recent year field comes first.

Cross-domain limitations

One thing that makes loosely coupled, rapid prototyping of multitiered web applications tricky is the set of cross-domain request restrictions in browsers. For security reasons, browser scripts are severely limited from making HTTP requests except to the same port on the same host as the source page. Several approaches for dealing with this problem are available. One of them is to use JSONP (JSON with padding; see Related topics). Listing 7 is an excerpt from poquotes.js — the part that loads records into the target divs:

Listing 7. JavaScript and jQuery code to load the target page with quotes
    root: "http://localhost:5984/",
    max_quotes: 6,

    //Invoked when the HTML page is first loaded
    loadPage: function()
        var six_latest = poq.root + "poquotes/_design/poquotes/_view/by_year?&limit="
            + poq.max_quotes + "&descending=true&callback=?";
        $.getJSON(six_latest, poq.handleMainQuotes);

    //Invoked with the result of the Ajax call to load quote documents
    handleMainQuotes: function(json)
        //Load up to six records, as available
        quote_count = Math.min(poq.max_quotes, json["total_rows"])
        for (var i=0; i<quote_count; i++) {
            var doc = json["rows"][i]["value"]
            var year = doc["work"]["year"].toString()
            var title = doc["work"]["title"].toString()
            var link = doc["work"]["link"].toString()

            //Create an HTML snippet from the fields of each quote document
            qblock = $("<div class='span4 featured-quote'></div>")
              .append("<h2>" + doc["author"] + "</h2>")
              .append("<p style='font-size: 80%; height: 8em;'>" + doc["text"] + "</p>")
              .append("<p>" + year + "</p>")
              .append("<p><a href='" + link + "'>" + title + "</a></p>")
              .append("<p><a class='btn' href='#'>View details &raquo;</a></p>")
            //jQuery's eq selector to find the target div corresponding to the loop index
            $('div.featured-quote:eq(' + i.toString() + ')').replaceWith(qblock);

In Listing 7, the callback=? is added at the end of the URL for loading documents. This tells jQuery to use JSONP for the Ajax GET query to pull documents from CouchDB, required because the database is running on a different port from the web front end. This workaround is also needed if you query a database on a different host.

To make Ajax requests using methods other than GET is trickier. Listing 8 is an excerpt from poquotes.js — the part that creates a new form and sends it to the database:

Listing 8. JavaScript and jQuery code to turn fields from a form into a record and POST it to CouchDB
    dbroot: "db/",
    //Invoked when the HTML page is first loaded
    loadPage: function()
        $('#donewquote').click(function() {
            var db_link = poq.dbroot + "poquotes";
            var record = {
                "type": "quote",
                "author": $("#author").val(),
                "text": $("#text").val(),
                "work": {
                    "title": $("#title").val(),
                    "link": $("#link").val(),
                    "year": parseInt($("#year").val())
                url : db_link,
                data : JSON.stringify(record),
                contentType : "application/json", 
                type : 'POST',
                processData : false,
                dataType : "json",
                success : function(resp) {
                    alert("New document created: " + JSON.stringify(resp));
            return false;
        //Set up the collapsible form for adding new quotes
        //Start out with the create quote form collapsed

In Listing 8, the POST is made to the same host and port, but to a /db/ URL. I use the standard trick of setting up a reverse proxy from that URL to the CouchDB host and port. More specifically, I use an Apache HTTP Server ProxyPass directive. The details of this technique depend on your setup, but it is useful in setting up a web prototype with strong separation between the browser and server layers.

The look and feel

Figure 2 shows the working sample page when it is first loaded, after the target divs are filled with records from the database:

Figure 2. Browser screen after index.html is loaded from the Apache web server
Screen capture of browser screen after index.html is loaded from Apache
Screen capture of browser screen after index.html is loaded from Apache

The user can select Click to create a new quote to display the form for adding a new quote, as in Figure 3:

Figure 3. Browser screen from index.html with form shown
Screen capture of browser screen from index.html with form shown
Screen capture of browser screen from index.html with form shown


Throughout the article I've explained why I prefer certain techniques for prototyping web applications. They make it easier for the web design and the middleware to proceed in independent, parallel tracks, which feels like a more natural separation of concerns. I would rather have a dedicated web server hosting the site, even in development, than a DBMS.

In this article, I glossed over details of user authentication and authorization on CouchDB. After the prototyping stage, I update the middleware to handle user management, sessions, and the like. I can forward these concerns to CouchDB's facilities or use separate frameworks, depending on the project. This is the key flexibility that I gain. The web application gains a few details pertaining to logging in and session management, but usually it is an independent layer.

My intention in this article is not to disparage other approaches for prototyping on a NoSQL platform. I offer it as an alternative approach that is worth considering. It can be fun as well as productive to combine the most interesting open source projects, focusing each on its core strengths. In the process, you also learn many important details that too often get glossed over by tools that couple layers together too tightly.

Downloadable resources

Related topics


Sign in or register to add and subscribe to comments.

Zone=Web development, Open source
ArticleTitle=Prototype web applications with CouchDB and Bootstrap