{"id":1544,"date":"2014-12-17T15:43:15","date_gmt":"2014-12-17T15:43:14","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1544"},"modified":"2025-06-13T23:50:08","modified_gmt":"2025-06-14T06:50:08","slug":"couchbase-connect-2014-keynote-demo-application-how-we-did-it","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/","title":{"rendered":"Couchbase Connect 2014 Keynote Demo Application &#8211; How We Did It"},"content":{"rendered":"<h3>Node.js + Couchbase 3.0 + SDK 2.0 + Bootstrap<\/h3>\n<h2>Requirements<\/h2>\n<p>When it came time to build a product demonstration for the Couchbase Connect Conference the following requirements were established:<\/p>\n<p>[1] It must be a live demo, with audience participation &#8212; no canned movies or powerpoint only presentations. \u00a0The bar was set high with significant risk.<br \/>\n[2] It must demonstrate the power of Couchbase 3.0 and show realtime consistency of data between clusters in different datacenters (XDCR).<br \/>\n[3] It must be agile, leveraging the power of the new Couchbase 2.0 SDK&#8217;s.<br \/>\n[4] The application needs to be code complete in 4 days to reinforce how development with Couchbase is ideal for the agile enterprise.<br \/>\n[5] Tell the world how it was done, and prove it by publishing the source code.<\/p>\n<p>It was decided that an auction application, spread over two web servers in two different datacenters talking to two different clusters would achieve the objective. \u00a0 A Salt Lake City Cluster, and a London Cluster will maintain consistency with bidirectional replication between them using XDCR. \u00a0 The new DCP protocol in Couchbase 3.0 means that consistency would only be limited by wirespeed. \u00a0 An application server in each datacenter running node.js handles traffic in each region. \u00a0The code can be downloaded from <a href=\"https:\/\/github.com\/couchbaselabs\/keynotedemo14\">couchbaselabs repo on github. <\/a>**<\/p>\n<h2><span style=\"font-family: inherit;font-size: 1em;line-height: 1.4375em\">Application Design<\/span><\/h2>\n<p>In addition to <a href=\"https:\/\/www.couchbase.com\/blog\/build-a-rest-api-with-node-js-express-and-couchbase\/\">using node.js<\/a> with Express and the Couchbase 2.0 SDK, bootstrap was used for front end development. \u00a0 The 2.0 SDK&#8217;s are a remarkable achievment, and include significant new advancements that simplify development. \u00a0 Information on the 2.0 SDK&#8217;s and why Couchbase continues to extend development leadership within the market can be found in our <a href=\"https:\/\/www.couchbase.com\/developers\/\">developer portal.<\/a><\/p>\n<h3>Session Management<\/h3>\n<p>While no authentication is needed for a just for fun auction, \u00a0a means of identifying users and concurrent sessions is still required. \u00a0A simple login form stores a cookie with a user id for each session. \u00a0 The login function checks if the user exists, and if there is any filtered words violations prior to creating a session cookie.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">module.<span style=\"color: #660066\">exports<\/span>.<span style=\"color: #660066\">login<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>newUser<span style=\"color: #339933\">,<\/span>req<span style=\"color: #339933\">,<\/span>res<span style=\"color: #339933\">,<\/span>done<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nfilterScan<span style=\"color: #009900\">(<\/span>newUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>filtcb<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>filtcb<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ndb.<span style=\"color: #660066\">read<\/span><span style=\"color: #009900\">(<\/span>newUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>err<span style=\"color: #339933\">,<\/span> user<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>err <span style=\"color: #339933\">&amp;&amp;<\/span> err.<span style=\"color: #660066\">code<\/span> <span style=\"color: #339933\">===<\/span> couchbase.<span style=\"color: #660066\">errors<\/span>.<span style=\"color: #660066\">keyNotFound<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nres.<span style=\"color: #660066\">cookie<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;user&#8217;<\/span><span style=\"color: #339933\">,<\/span> newUser<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndb.<span style=\"color: #660066\">upsert<\/span><span style=\"color: #009900\">(<\/span>newUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #cc0000\">0<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>err<span style=\"color: #339933\">,<\/span> res<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>err<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nconsole.<span style=\"color: #660066\">log<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR CREATING:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> err<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndone<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR CREATING:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> err<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">null<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\nconsole.<span style=\"color: #660066\">log<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> newUser <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">&#8220;:SUCCESS&#8221;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndone<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">null<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #3366cc\">&#8220;LOGIN:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> newUser <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">&#8220;:SUCCESS&#8221;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">else<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>user<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nconsole.<span style=\"color: #660066\">log<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> newUser <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">&#8221; EXISTS&#8221;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndone<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> newUser <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">&#8221; exists &#8212; please choose a different username&#8221;<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">null<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\nconsole.<span style=\"color: #660066\">log<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR:END:&#8221;<\/span> <span style=\"color: #339933\">+<\/span> err<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndone<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR&#8221;<\/span> <span style=\"color: #339933\">+<\/span> err<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">null<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">else<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nconsole.<span style=\"color: #660066\">log<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR:WORD VIOLATION&#8221;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndone<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;LOGIN:ERROR, PROHIBITED TERM IN USERNAME&#8221;<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">null<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Then a very small \u00a0&#8220;middleware&#8221; function checks if a user has setup a session prior to routing incoming requests.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">function<\/span> isLoggedIn<span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span> res<span style=\"color: #339933\">,<\/span> next<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">cookies<\/span>.<span style=\"color: #660066\">user<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span> next<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\nres.<span style=\"color: #660066\">redirect<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;\/&#8217;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>A further &#8220;middleware&#8221; function checks to see if a countdown is set or if this auction is closed.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">module.<span style=\"color: #660066\">exports<\/span>.<span style=\"color: #660066\">isActive<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span><span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span>res<span style=\"color: #339933\">,<\/span>next<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ndb.<span style=\"color: #660066\">read<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;state&#8217;<\/span><span style=\"color: #339933\">,<\/span><span style=\"color: #003366;font-weight: bold\">function<\/span><span style=\"color: #009900\">(<\/span>err<span style=\"color: #339933\">,<\/span>done<span style=\"color: #009900\">)<\/span><span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span><span style=\"color: #009900\">(<\/span>done.<span style=\"color: #660066\">value<\/span>.<span style=\"color: #660066\">active<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span> next<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #000066;font-weight: bold\">else<\/span><span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span><span style=\"color: #009900\">(<\/span>done.<span style=\"color: #660066\">value<\/span>.<span style=\"color: #660066\">countdown<\/span> <span style=\"color: #339933\">!=<\/span> <span style=\"color: #3366cc\">&#8220;none&#8221;<\/span><span style=\"color: #009900\">)<\/span><br \/>\n<span style=\"color: #009900\">{<\/span><br \/>\nres.<span style=\"color: #660066\">render<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;countdown.jade&#8217;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #000066;font-weight: bold\">else<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ndb.<span style=\"color: #660066\">read<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;bike&#8217;<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>err<span style=\"color: #339933\">,<\/span> cb<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nres.<span style=\"color: #660066\">render<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;winner&#8217;<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #009900\">{<\/span>user<span style=\"color: #339933\">:<\/span> req.<span style=\"color: #660066\">cookies<\/span>.<span style=\"color: #660066\">user<\/span><span style=\"color: #339933\">,<\/span> amount<span style=\"color: #339933\">:<\/span> cb.<span style=\"color: #660066\">value<\/span>.<span style=\"color: #660066\">bid<\/span><span style=\"color: #339933\">,<\/span> high<span style=\"color: #339933\">:<\/span> cb.<span style=\"color: #660066\">value<\/span>.<span style=\"color: #660066\">high<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">return<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<h3>User Interaction<\/h3>\n<p>The app.js file controls how the application functions. \u00a0 All of the routes are defined in the routes.js object in a specific file. \u00a0The application object is \u00a0passed into the routes object. \u00a0This is a stylistic preference that facilitates easier middleware functionality (as used in the above examples). \u00a0 The REST API is straight forward: The following methods are exposed:<\/p>\n<p>POST \u00a0 api\/auction\/login [set a session, cookie, for each unique user]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/login [safety method, in case of page refresh]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/load [load the auction page]<br \/>\nPOST \u00a0 api\/auction\/bid [set a bid, with validation]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/bid [safety method, in case of page refresh]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/get [get current high bidder]<br \/>\nPOST \u00a0 api\/auction\/open\/:password [reset auction, flush bucket, and set auction to open]<br \/>\nPOST \u00a0 api\/auction\/close\/:password [set auction to closed]<br \/>\nPOST \u00a0 api\/auction\/view\/build\u00a0\u00a0 \u00a0[set a view to be used for looking at bid history]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/view\/get [get view for bid history]<br \/>\nGET \u00a0\u00a0 \u00a0api\/auction\/countdown\/get [get time in seconds between auction &#8220;go live&#8221; and now]<br \/>\nPOST \u00a0 api\/auction\/countdown\/set\/:yyyy\/:mm\/:dd\/:hh [set auction go live date]<br \/>\nPOST \u00a0 api\/auction\/countdown\/del\/:password [set auction countdown to none, and auction to live]<\/p>\n<h3>Dynamic Updates<\/h3>\n<p>In the keynote demo multiple users bid concurrently against two different clusters, and any updates need to be immediately propagated to any other user currently viewing the auction page. \u00a0There are several ways of \u00a0performing this, each with advantages and disadvantages. \u00a0 This particular application loads the auction page through a jade template. \u00a0The jade template instantiates a jquery ajax polling loop. \u00a0This loop polls the \/api\/auction\/get REST endpoint twice each second to determine the highest bidder.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>setInterval<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\npollBid<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #cc0000\">500<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<p><span style=\"color: #003366;font-weight: bold\">function<\/span> pollBid<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n$.<span style=\"color: #660066\">get<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216;\/api\/auction\/get&#8217;<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">function<\/span> <span style=\"color: #009900\">(<\/span>cb<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">if<\/span> <span style=\"color: #009900\">(<\/span>cb<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n$<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;#bid&#8221;<\/span><span style=\"color: #009900\">)<\/span>.<span style=\"color: #660066\">html<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;$&#8221;<\/span> <span style=\"color: #339933\">+<\/span> cb.<span style=\"color: #660066\">bid<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n$<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8220;#high&#8221;<\/span><span style=\"color: #009900\">)<\/span>.<span style=\"color: #660066\">html<\/span><span style=\"color: #009900\">(<\/span>cb.<span style=\"color: #660066\">high<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">else<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<\/div>\n<\/div>\n<h2>Administration<\/h2>\n<p>The following methods are called using curl commands during the demo to set the auction states. \u00a0 The sequence for the demo is reset the auction, set a go live date, set the auction live when the keynote starts, and close the auction.<\/p>\n<p>curl -X POST https:\/\/localhost:3001\/api\/auction\/open\/un5ecure_pa55word<br \/>\ncurl -X POST https:\/\/localhost:3001\/api\/countdown\/set\/2014\/10\/06\/13<br \/>\ncurl -X POST https:\/\/localhost:3001\/api\/countdown\/del\/un5ecure_pa55word<br \/>\ncurl -X POST https:\/\/localhost:3001\/api\/auction\/close\/un5ecure_pa55word<\/p>\n<h2>Source and Considerations<\/h2>\n<p>Much of the functionality in this app is hard coded and specific to this keynote demo use case. \u00a0 The data model is specific to this use case and is only applicable as a proof of concept. \u00a0 The use case has no secure access or authentication. \u00a0When deploying to different clusters linked by XDCR additional administration is required to &#8220;reset&#8221; the auction. \u00a0 Buckets cannot be &#8220;flushed&#8221; that are currently participating in XDCR.<\/p>\n<p><strong>** Disclaimer: Couchbase Labs provides experimental code for research and development purposes only. \u00a0 Code and applications from Couchbase Labs are not supported under any Couchbase Support Agreement and are provided as is with no warranty of any kind. \u00a0<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Node.js + Couchbase 3.0 + SDK 2.0 + Bootstrap Requirements When it came time to build a product demonstration for the Couchbase Connect Conference the following requirements were established: [1] It must be a live demo, with audience participation &#8212; [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1822],"tags":[1254],"ppma_author":[9019],"class_list":["post-1544","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-node-js","tag-express"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Couchbase Connect 2014 Keynote Demo Application<\/title>\n<meta name=\"description\" content=\"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Couchbase Connect 2014 Keynote Demo Application - How We Did It\" \/>\n<meta property=\"og:description\" content=\"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-17T15:43:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T06:50:08+00:00\" \/>\n<meta name=\"author\" content=\"Todd Greenstein\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@todd_greenstein\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Todd Greenstein\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/\"},\"author\":{\"name\":\"Todd Greenstein\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/64b5d1e5969768c5d63c11c696951ed3\"},\"headline\":\"Couchbase Connect 2014 Keynote Demo Application &#8211; How We Did It\",\"datePublished\":\"2014-12-17T15:43:14+00:00\",\"dateModified\":\"2025-06-14T06:50:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/\"},\"wordCount\":1061,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"express\"],\"articleSection\":[\"Node.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/\",\"name\":\"Couchbase Connect 2014 Keynote Demo Application\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-17T15:43:14+00:00\",\"dateModified\":\"2025-06-14T06:50:08+00:00\",\"description\":\"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Couchbase Connect 2014 Keynote Demo Application &#8211; How We Did It\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/64b5d1e5969768c5d63c11c696951ed3\",\"name\":\"Todd Greenstein\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=gabfbe093983052aa28595343c19888ce\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=g\",\"caption\":\"Todd Greenstein\"},\"description\":\"Todd Greenstein is a Solution Architect at Couchbase. Todd is specialize in API design, architecture, data modeling, nodejs and golang development.\",\"sameAs\":[\"https:\\\/\\\/x.com\\\/todd_greenstein\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/author\\\/todd-greenstein\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Couchbase Connect 2014 Keynote Demo Application","description":"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/","og_locale":"en_US","og_type":"article","og_title":"Couchbase Connect 2014 Keynote Demo Application - How We Did It","og_description":"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.","og_url":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-17T15:43:14+00:00","article_modified_time":"2025-06-14T06:50:08+00:00","author":"Todd Greenstein","twitter_card":"summary_large_image","twitter_creator":"@todd_greenstein","twitter_misc":{"Written by":"Todd Greenstein","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/"},"author":{"name":"Todd Greenstein","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/64b5d1e5969768c5d63c11c696951ed3"},"headline":"Couchbase Connect 2014 Keynote Demo Application &#8211; How We Did It","datePublished":"2014-12-17T15:43:14+00:00","dateModified":"2025-06-14T06:50:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/"},"wordCount":1061,"commentCount":2,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["express"],"articleSection":["Node.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/","url":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/","name":"Couchbase Connect 2014 Keynote Demo Application","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-17T15:43:14+00:00","dateModified":"2025-06-14T06:50:08+00:00","description":"Learn more about building a product demonstration for the Couchbase Connect Conference. Also, check what requirements were established.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-connect-2014-keynote-demo-application-how-we-did-it\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Couchbase Connect 2014 Keynote Demo Application &#8211; How We Did It"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/64b5d1e5969768c5d63c11c696951ed3","name":"Todd Greenstein","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=gabfbe093983052aa28595343c19888ce","url":"https:\/\/secure.gravatar.com\/avatar\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=g","caption":"Todd Greenstein"},"description":"Todd Greenstein is a Solution Architect at Couchbase. Todd is specialize in API design, architecture, data modeling, nodejs and golang development.","sameAs":["https:\/\/x.com\/todd_greenstein"],"url":"https:\/\/www.couchbase.com\/blog\/author\/todd-greenstein\/"}]}},"acf":[],"authors":[{"term_id":9019,"user_id":20,"is_guest":0,"slug":"todd-greenstein","display_name":"Todd Greenstein","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f230045f7f6e636cf01abbd35f1cbf66a1206fbe149a0d4f0bbdd992c646257d?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/1544","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=1544"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/1544\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=1544"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=1544"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=1544"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=1544"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}