In my previous post, I shared my recent experience building a RESTful API with Node.js, MongoDB, and Express.
In this post, I’m sharing the client application that uses that RESTful API. The Node Cellar application allows you to manage (retrieve, create, update, delete) the wines in a wine cellar database.
The client application is built with Backbone.js and Twitter Bootstrap.
Run the Application
You can run the application here. For obvious reasons, the create, update, delete features have been disabled in this hosted version.
NOTE: Node.js is running on port 3000 on my EC2 Instance. My friend James Ward convinced me to host the application on their service over at Heroku. It’s now running on port 80 at http://nodecellar.coenraets.org. Thanks James!
Server-Side
The details of the Node.js, MongoDB, and Express implementation are documented in my previous post.
Client-Side
In this application, Node.js is used to provide the RESTful services that the client application needs to manipulate the data. Node.js is not used to generate HTML/Views at the server-side. Instead, the Views are created dynamically at the client-side using Backbone.js and Underscore.js templates. They are injected into- and removed from the DOM as needed as you navigate through the application. Node Cellar is a “single page application”.
This is a Node.js and MongoDB powered version of an application I initially posted here with PHP and Java backends. The original post provides some additional Backbone.js context. This Node.js version also provides an improved user experience with the latest version of Twitter Bootstrap (2.1.1), and a responsive layout. It also uses Adobe Edge Web Fonts.
Source Code
The source code is available in this repository on GitHub.



Hi Christophe,
I’d like to keep the node server listening on port 3000, where can I update your client code to send http://localhost:3000/wines ?
Thanks.
@Chun: The source code in GitHub still uses port 3000 by default. It’s in server.js.
Yes I see that the server code still uses the port 3000 in the “app.configure” function.
My question is about the client code : clicking on the button “Start Browsing Cellar” for example ends up with a GET http://localhost/wines which results in the error 404 as I see in the console debugger in Chrome.
How can I modify the client code to add the 3000 ?
Thank you.
@Chun: All the links should be relative. So if you initially access the app using http://localhost:3000, then clicking the “start browsing” button should take you to http://localhost:3000/#wines.
Hi Christophe,
I asked you these questions because I want to take a step further by making the client a mobile app using PhoneGap.
The REST API will be hosted on another machine (the mongoDB and the node server) to which the client on my smartphone will send request.
I need your advice for this. Thanks.
I have the same requirement. I need to have the REST API listening on lets say, Port 3000, and the client listening on say port 2000 and I need to have the client redirect the calls to the rest server. I am using Node.js, Express and MongoDB…
Connecting to http://nodecellar.coenraets.org/ with my Samsung Galaxy S and Galaxy Tab 10.1, I expected to see the effects of responsive design, the app looks good on both devices.
I notice that on the smartphone, the text of the home page is not exactly vertically centered, I try to fix this, do you have any suggestion ? Thx
Nice sample! And big thank for the sourse.
1. but, why I see a low speed of response your sample? localy nodejs show me very very high speed
2. i can;t find any solutions about session and security. As example DEL and PUT rests can use any body w/o rights in any sample that I see before.
Thanks for this great sample, I wish you would releaser a version of it with Sencha Touch 2 (and ExtJS now that your apps has already reached the stage of integrating the Responsive Design), do you think this makes sense ?
@Paul: good catch on the smartphone. Thanks. The problem was that my padding in the CSS was too big. I added a few media queries to my style sheet to change the padding depending on the screen size. It should work fine now. I also pushed the changes to the GitHub repo.
Thank you very much, great post and fantastic examples.
Hi @Christophe. Great tutorial and example of using Node.js to build a functional site. I managed to get everything working, but had to comment out the last res.send() line in addWine, updateWine, and deleteWine to get rid of the error: “Can’t set headers after they are sent..”
Also moved the res.send(wine) into the else block of addWine.
Even with these minor updates, this is one of the best examples that I have seen so far.
Dan: Thanks for catching that! I introduced that bug yesterday after making changes to the hosted version that has the CRUD operations disabled, and just sends back an unchanged object. Fixed it in the GitHub repo. Thanks again. Christophe
Hi Christophe,
Thanks for these tutorials. I am curious as to what sort of IDE or environment you like to use for coding your javascript apps. Put more directly, I am wondering if you would share your set up as part of one of your posts.
Hi Christophe,
Thanks for this sample application which covers many interesting features.
I try to wrap the client in PhoneGap to deploy in my iPad3 but I have the problem of invoking the Rest service hosted with Node.js on my Windows 7 laptop.
Can you give me some directions ?
Good sample application but as many people have mentioned I would like to have it run not only on the same machine as the rest server but as a phonegap application. Thanks.
when you make an example with Sencha Touch 2 and PhoneGap ?
Small bug, the link to the git repository on the demo site doesn’t work
@Yann & Tan: there shouldn’t be any problem running this as a PhoneGap app. Take everything that’s in the /public folder and package it as your PhoneGap app. Make sure the URLs in models.js point to the right service and that you include the remote server in the server white list.
Thanks, your client works using MDS Phonegap plugin for Android and model.js updated as you adviced. Two remarks though : 1. with or without , the client can query the node server running on my laptop 2. the back button from an external link make me return to your app home page which is no longer centered on the vertical (for example : on the home page, I tap on Christophe Coenraets, your blog shows, then I use the Samsung back button, I return to the home page and see it not centered).
Christophe – TY for sharing! This is exactly the stack I was looking for. Thanks for putting me a few weeks ahead of schedule.
All – I see a few people have used PhoneGap on this example. If someone would send me over a high level on getting this in place that would same me some more time! briancarter AT ChipSoftTech.com.
Hi Christophe,
I am new to Node.js and I need to implement Rest API using Slime Framework with backbone and socket.io actual my requirement is on every insert operation(i.e every transaction ) I need to update all users resultset who ever access the that data can you tell me how can i call my Slim Framework Rest API using node.js on every insert update delete operations
Nice post, for all the wine restaurants I recommend take a look at top cellar wine menu software as well.
Many thanks Chris! A question: why this route doesn’t work?
app.get(‘/’, function(req, res){
console.log(‘Route / ‘);
});
Great tutorial. I start to use backbone.js and node.js for the development. My question is how can i embed it into a portlet which has a div to embed into. Do i need to use request.js or some lib to bootsratp it? Any idea wiill appreciate it.
We are a group of volunteers and opening a new scheme in our community.
Your web site offered us with valuable information to work
on. You’ve done an impressive job and our entire community will be grateful to you.
Nice post, I’ve a newbie question: what if I’ve not a heroku account and want to deploy nodecellar in one of my servers (just to try it and modify it and inderstand it).
Thanks
Rob
Christophe,
Thank you so much for your sharing. I’ve been reading your posts from several years ago when I was a Flex developer. I don’t have any Javascript experience, I use your sample application as my learning ‘Bible’.
I hope you can write some books, I’ll definitely buy those books =:)
Andi
Hello just wanted to give you a quick heads up.
The words in your article seem to be running off the screen in Chrome.
I’m not sure if this is a formatting issue or something to do with browser compatibility but I thought I’d post to let you know.
The style and design look great though! Hope
you get the problem solved soon. Many thanks
What I do when this error appears:
ERROR: XHR: api/wines Object {method=”GET”, url=”api/wines”, …} Object {status=404, …}
Thank you so much for this tutorial.
I’ve been researching how to include Asynchronous Module Definition (AMD) in this example and finally I created a project in Githup. It uses Require.js to load all modules that the application needs. Now all views and templates are included in this manner.
Also I’ve replaced the fetch() method for Backbone.Pagination created by Addi Osmani. Now the application only returns a number of records defined in the collection.
I’m not an expert in any of the technologies that Christophe uses, so I would appreciate any suggestions or improvements that you give me.
The Githup project:
https://github.com/perezagua/nodecellar_require
Best regards
Angel Martin
CHRISTOPHE can you please add authentication and authorization in this example app, because many peoples including me, have lots of misconceptions to build an app using backbone.js and node.js that supports authentication and authorization as well.
+1 on this. Would be great to see how that is handled for someone that is authorized to post and delete from wine database instead of random user using curl to delete via the api
+1 as well. Perhaps integrating passport into this would be a good next step.
+1 on authentication example. Thanks
Nice one, thank you very much!
One BIG question:
How would you make this site indexable by web pages ?
Is there a way to reuse the client-side templating on the server side as well?
Maybe use this :
https://github.com/stdbrouw/backbone-express
?
http://passportjs.org/guide/
Authentication middleware for Node.
I was able to get up and running on my local with this, but I wasn’t able to get image uploading to work. Every time I added a wine, the image gets added to the database as null. Any steps that I need to take in order to get that portion working?
I am having the same issue with the images, were you able to resolve it
Thank you for the great work you are doing. I am a big fan of your tuts and this example on nodejs came the right time when I have just learned express and mongodb. My concern though is how we organize our views and the routes. I would like to build an application that I forsee it might end up beign complex with time. Do you think with this method we can comfortable manage and handle big applications?What are your suggestions?
Note: I have been to bbb but no solid example on managing files, though I know using bbb might be the best alternative.I have not been able to grasp the concept well.
I hope to hear from you soon
Thank you
hi uploading image by drag-drop style doesn’t work at opera may you fix it
Hi,
thanks for the tutorial,
I’am trying to get the data into the sidebar. I have a mysql database and the wine table exists and is filled with the data.
My sidebar keeps beeing empty but function getWines() doesent give a PDOExeption.
What could be the reason?
Thanks for any Idea!
Gelo
Seriously amazing. You even populated it with sample data for us. :) Thank you!!
If i visit nodecellar.coenraets.org/wines, I can see all the details in mongodb.
That’s not good.
very thanks
good blog very nice
Excellent site you have here.. It’s difficult to find quality writing like yours nowadays. I seriously appreciate individuals like you! Take care!!
Christophe,
I notice that you don’t have copyright info included in your github page. I’m working on a small project in my spare time and want to reuse some code from your nodeceller github repository. Would you be so kind as to let me know if this is something you’d be okay with? Maybe you could add a copyright file to you repo to set your expectations when somebody forks or reuses code ?
Have you tried angularjs ? I seem to like it better than backbone.jar. Wondering if you had any opinions on it.
Pramod
Hi
I have a webapp which we have done using Backbone and now we want this webapp to work on touch devices. So is it possibel to integrate BackBone webapp with sencha touch ??
if yes do you have any example of how we can integrate both ??
Thanks
Great stack!
Hi,
I’ve followed all the steps and the app seems to have installed easily on heroku…
http://mysterious-journey-8562.herokuapp.com
Listing wines does not work – can you shed any light on the issue?
http://boiling-chamber-3306.herokuapp.com/#wines
New link same problem – seems like anything database related is not going through…
In Hopes this might help someone like me:
The issue was that i wasn’t connecting to the database properly (or at all) with the default code base from the Git repo. I needed to customize slightly the database connection methods to make compatible with Heroku add on MongoLab.
Here is a quick link: http://jsbin.com/uqisig/2/edit
Enjoy and good luck !
Thanks for posting that fix for the DB connection you just saved me hours.
Hey Christophe, another great tutorial. I keep ending up on your blog :-) Just wondering if you’ve given any thought as to which js framework (clearly from the ones you’ve been using/evangelizing) might be a good candidate for building a Chrome extension. I believe Backbone.js should work, assuming the Models live on the Background.html and communicate to the Views/Templates on the Pop-ups and Content Scripts while keeping each other in sync through the Chrome API’s. But I’ve never tried it out. You seem to have a knack for in-depth tutorials. This would be a cool one to tackle … especially if you could work from one of your existing tutorials, like in the past. Cheers!
Love your work!!! This stuff is so cool. I just dropped a pull request to make the api a little more robust. May help some people who are new to this. Cheers!
Hi,
I followed the first tutorial and this one, when I click in the link :
Browse Wine nothing happened.
When I try to add a new wine ,In the node server console I have :
GET /pics/generic.jpg 304 3ms
GET /favicon.ico 404 2ms
Adding wine: {“_id”:null,”name”:”newWine”,”grapes”:”newGrapes”,”country”:”USA”,”
region”:”California”,”year”:”",”description”:”some notes.”,”picture”:null}
GET /favicon.ico 404 2ms
GET /favicon.ico 404 3ms
Thanks,your help is appreciated.
I have never seen the output of the console coming from wines.js ”
“Connected to ‘winedb’ database”
or
“The ‘wines’ collection doesn’t exist. Creating it with sample data…”
thanks
Spot on with this write-up, I really think this
website needs a great deal more attention. I’ll probably be returning to read more, thanks for the information!
I am new with all above technology but i keen to understand them so for this i need a clear picture that how can i build the above application step by step with backbone.js node.js and other mentioned above ..and the software required to run the application.
I will appreciate your help and It will great help for me.
Just I want in simple way step by step so a person who is know only java script ; can understand the application and run on his machine.
Thanks Paras
Seriously content I came across this webpage currently has
made me happy quite honestly
Great post! Thanks for sharing! I noticed when running the web app that the URL kept changing, as if you were fetching new pages. Did you consider making this a single-page web app? Or perhaps a better question is how did you decide when to go to a new page instead of retrieving more data using a REST API and modifying the data and/or visibility of DOM elements shown in the current page? I apologize if this is bad question, as I’m new to node.js. Thanks.
Hi,
I’m just learning Node and NoSQL DBs and I just can’t figure out one moment. I’m trying to repeat almost the same app that you did, but I want to show items grouped by categories. In your example it could be a country, i.e.
France
– wines from France
Algeria
– wines from Algeria
Spain
– wines from Spain
etc.
If I decide to store Wine objects as subobjects of Country, I could easily query this way. But to get single Wine details, I will need to query the whole Country.
If I decide to store Country as a field of Wine object, how can I group Wines by Country? What is the best way to do this?
Thanks in advance,
Max
Running into this error when executing ($ node serverwithanalytics.js)
info – socket.io started
Express server listening on port 3000
GET / 200 11ms – 2.74kb
GET / 200 11ms – 2.74kb
GET /css/bootstrap.css 304 3ms
GET /css/bootstrap.css 304 3ms
http.js:704
throw new Error(‘Can\’t set headers after they are sent.’);
^
Error: Can’t set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:704:11)
at ServerResponse.res.setHeader (/home/zach/nodecellar/node_modules/express/node_modules/connect/lib/patch.js:59:22)
at SendStream.type (/home/zach/nodecellar/node_modules/express/node_modules/send/lib/send.js:455:7)
at SendStream.send (/home/zach/nodecellar/node_modules/express/node_modules/send/lib/send.js:347:8)
at /home/zach/nodecellar/node_modules/express/node_modules/send/lib/send.js:322:10
at Object.oncomplete (fs.js:107:15)
I did not install node modules global, but local. Please advise.
Thank you.
I updated to 0.9.14 socket.io by changing package.json.. serverwithanalytics.js does not completely die, but will not display entire page.
Cleared Chrome History. Loading..
Images not saving when i add a new wine. I was able to get the drop and drag image to work but when I click to save the default image still displays. How do I save a new image to the database.
Please how do I run the sample app on my local machine, I have downloaded the sorce from github, I can fetch wines by this http://localhost:3000/wines/
how do I run the client application?
thanks
Thanks for another informative website. The place else could I get that type of info written
in such a perfect means? I’ve a venture that I am just now operating on, and I have been on the look out for such information.
arośniętej jakości. – Widziałeś? – spytał balcony [Hans]
rozochocony rycerz, słysząc Arnolda w środku tuleja.
- Kogo? – Lecz owo
Cztan spośród Rogowa! Obaj rycerze spoglądali z podziwem na mocarza, kto, w charakterze leg.
I’m trying to extend your example by adding JQuery-Sortable to let the user reorder bottles, did you try doing that?