Getting Started Full Stack - Building API with Baucis - Part 3

In previous post, we’ve seen how to navigate in our site using backbone.js. In this post, we will go back to server side, and build our blog api using baucis. At the end of this tutorial, you will be able to query your mongodb database and pull blog information.

Building Schemas with Mongoose

Firstly, let’s define our blog schema. We will use mongoose to interact with mongodb. Go to app/scripts directory and create a new file named schemas.js.

app/scripts/schemas.js

var mongoose = require('mongoose');
var baucis = require('baucis');

// Define journal schema
var journalSchema = mongoose.Schema({
    paper: {name: String, url: String},
    author: {name: String, photo: String },
    title: String,
    body: String,
    date: { type: Date, default: Date.now},
    meta: {
        votes: Number,
        favs: Number,
        tags: { type: String, lowercase: true, trim: true }
    }
});

// db connection string
var MONGO_URI = process.env.MONGOHQ_URI || 'mongodb://localhost/test';


// connect to mongodb with mongoose
mongoose.connect(MONGO_URI);

// define a journal model with journalSchema
mongoose.model('journal', journalSchema);

// use baucis to create a rest api
var controller = baucis.rest('journal');

We created a blog schema, connected to our database, defined a model based on our schema, and finally used baucis to create the rest api. Now if you run your server, your api will be available at:

http://localhost/api endpoint.

Here is a table, describing available functions:

HTTP Verb /journals /journals/:id
GET Get all or a subset of documents Get the addressed document
POST Creates new documents and sends them back. You may post a single document or an array of documents. n/a
PUT n/a Update the addressed document
DELETE Delete all or a subset of documents Delete the addressed object

To test it go to http://localhost/api/journals in your browser, it should return an empty array. Because we don’t have any blogs in our database yet.

Using Mongo Shell

Though we can post blogs to our database using the api, we will simply create blogs using the mongo shell. Mongo shell is CLI for using mongodb. run mongo in your console to open the shell. Issue the following commands to create your first blog entry.

   # This is for commenting
   # just ignore it.

   # List databases
   show dbs
   
   # Choose database, test
   use test

   # List collections in the database
   show collections

   # journals collection is created when we created a model with mongoose.
   # collection is the plural form of our model.

   #list the contents in journals collection
   # it should be empty
   db.journals.find()

   # place a new blog entry in journals collection
   # here we define only title and body attributes, you can define other attributes as well

   db.journals.create({title: 'My Simple Blog 1', body: 'Simple body for testing' })

   # list the contents again to see the newly created blog
   db.journals.find()
   
   

Mongo shell is interpreting javascript code here, so use javascript. Undefined attributes will have their defaults value We can disable null values for attributes, but for simplicity we don’t.

Now go to http://localhost/api/journals again and see the newly created blog entry.

In the next post, we will consume this api with backbone.js and list the blogs in our main page.

Getting Started Full Stack - Building a simple blog - Part 2

In previous post we’ve seen how to setup a node.js server and serve our index.html. In this post, we will implement navigation in our site using backbone.js. At the end of this tutorial, you will be able to navigate between tabs in your site.

Router

Backbone.Router provides methods for routing client-side pages. We will start by creating a custom router class. Place this in js/app.js

  var AppRouter = new (Backbone.Router.extend({
    initialize: function() {

    },
    
    routes: {
        
    }
}))();

When creating a router you may pass its routes hash directly, or manually create a route for the router. We will do it manually inside initialize function. But first let’s define our routes in an object.

js/app.js

   var NavigationRoutes = {
    "Home": {
        route: "",
        view: Home
    },
    "About": {
        route: "About",
        view: About
    },
    "default": {
        route: "*default",
        view: NotFound,
        hide: true
    }
}

NavigationRoutes object will keep our routes for the application. The keys are title for the route. “route” property is the routing string. “view” property defines the backbone view objects that will be rendered for the route, they are the Route Views We will define them later. Finally “default” key has a “hide” property telling that it will be hidden on navigation tab. We can add different properties as we like here, for example “permissions” property might tell a navigation tab to be only shown for an admin.

Next we will add these routes to our router. Place this function in your Backbone router.

js/app.js

   initialize: function() {

        this.route(NavigationRoutes['default'].route, 'default');

        for (var key in NavigationRoutes) {
            if (key != "default")
                this.route(NavigationRoutes[key].route, key);
        }
    },

Here we traverse NavigationRoutes, and add each route in our router. There is a little logic there for the default route. We add the default route first, so it becomes the last route to be looked. The default route is defines as “*default”, this is called a splat and matches everything in the url. So anything else that is not defined previously will be matched by default route, and NotFound view will be rendered.

Navigation View

Bootstrap NavBar

Before we dive into Backbone.View, let’s see our html code for the navigation bar. Place this inside your index.html

index.html

    <nav class="navbar navbar-default">
      <div class="navbar-header">
        <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-collapse">
          <span class="sr-only"> Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href='#'> Simple Blog </a>
      </div>

      <div class="collapse navbar-collapse" id="navbar-collapse">
      	
        <ul class="nav navbar-nav" id="nav-item-container">
	<!-- Navigation tabs will be inside #nav-item-container here -->
        </ul>
      </div>

    </nav>

     <div class="container" id="container">

    </div>

Our Backbone.View for the navigation tabs will control the #nav-item-container. #container element will contain the navigated content.

Backbone views don’t determine anything about HTML, it can be used with any templating library. Underscore.js in this case. Place this in js/views/nav.js

js/views/nav.js

var Navbar = Backbone.View.extend({
    initialize: function(options) {

    	// we pass the NavigationRoutes as an option, later we traverse the routes in render function.
        this.routes = options.routes;


	// router will fire route event whenever url changes, we rerender our view
	// on each url change
        Backbone.history.on('route', function(source, path) {
            this.render(path);
        }, this);
    },

    // events hash that handles events in our view
    events: {
    	    // click handler for a navigation tab
        'click a': function(source) {
            var hrefRslt = source.target.getAttribute('href');
            Backbone.history.navigate(hrefRslt, {trigger: true});

            // Cancel the regular event handing so that we won't actually
            // change URLs We are letting Backbone handle routing
            return false;
        }
    },

    render: function(route) {
    	// Clear the view element
        this.$el.empty();

	// this is the underscore template for a navigation tab.
        var template = _.template("<li class='<%=active%>'><a href='<%= url%>'><%=visible%></a></li>");

	// Traverse the NavigationRoutes
        for (var key in this.routes)
        {
		// don't render if route is hidden
            if (!this.routes[key].hide)
                this.$el.append(template({url: this.routes[key].route, visible: key, active: route === key ? 'active': ''}));
        }
    }
});

Backbone.View’s looks complicated at first, render function is used to render the actual view, in our case, its about manipulating the dom. The dom is referenced by this.el, equal to #nav-item-container. this.$el references the jquery dom object, equal to $(‘#nav-item-container’). We don’t set this.el in this code we will pass it as parameter when we initialize our view later.

template variable defines an underscore template. It is our navigation tab. A json model is passed to the template to render actual html. Finally html is appended to this.$el. This is done for each element in NavigationRoutes. We can add any logic we wan’t here to render, for now, we only use hide property for the NavigationRoutes to control if a link should be rendered or not.

Next, we define a view for navigated content. It will control the #container element.

js/views/nav.js

var Content = Backbone.View.extend({
    initialize: function(options) {
    	// pass the NavigationRoutes as an option
        this.routes = options.routes;

	// Listen for route changes, and render when a route changes.
        Backbone.history.on('route', function(source,path) {
            this.render(path);
        }, this);
    },

    render: function(route) {
        this.$el.html((new this.routes[route].view()).render().el);
    }
});

This is a bit simpler, tricky part is the render function. Here, we initialize the view property defined in our NavigationRoutes, view contains the Backbone.View elements for each route. Call the render method for the View element. render method will return the Backbone.View, (we will define that later) , so we can access the el property. Finally we set this.$el.html to the dom element of the route view.

Phew, that’s quite hard to explain, hope it becomes clear later.

Individual Route Views

Next, we define the route views, these will be rendered into the #container. Place this in your js/views/main.js.

js/views/main.js

var Home = Backbone.View.extend({


    template: _.template($('#home-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
    	// Set the html to the template
        this.$el.html(this.template());

	// We return this, so parent view can access the this.el property
        return this;
    }
});


var About = Backbone.View.extend({

    template: _.template($('#about-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
        this.$el.html(this.template());
        return this;
    }
});


var NotFound = Backbone.View.extend({

    template: _.template($('#404-template').html()),
    
    initialize: function () {
        
    },

    render: function () {
        this.$el.html(this.template());
        return this;    }
});

Each view defines an underscore template property. Templates are initialized with some html from jquery dom elements. We will define them later in our index.html. render method simply sets the view’s el property to the underscore template, and returns the view which was used in our navigated content view.

Route View Templates

We define these templates in our index.html.

index.html

    <script type='text/template' id='home-template'>
       Home
    </script>

    <script type='text/template' id='about-template'>
      About
    </script>

    <script type='text/template' id='404-template'>
      Oops..
    </script>

Since these templates should not be readily visible in the page, we wrap them in script tags and give each an id. We referenced these templates with jquery before.

While we’re at it, let’s add the new script files we’ve created to the index.html as well.

index.html

      <script src="/js/views/nav.js"></script>
      <script src="/js/views/main.js"></script>
      <script src="/js/app.js"></script>

Main Function

js/app.js

   $(document).ready(function () {

    new Navbar({el: $('#nav-item-container'), routes: NavigationRoutes});
    new Content({el:$('#container'), routes: NavigationRoutes});


    Backbone.history.start({pushState: true});
});

Finally the main function, initializes Navbar and Content views. And calls Backbone.history.start We pass the el property for the views here as mentioned previously. and NavigationRoutes is passed as an option.

By default backbone routes the url’s with a containing # symbol. Backbone.history.start is passed pushState:true parameter, to get rid of the #.

Congratz, now you have a working implementation of a navigated content using backbone.js

Final Touch

As a final touch, let’s put some html inside our #home-template so it looks more like a blog.

index.html

   
    <script type='text/template' id='home-template'>

      <div class="row">
        <div class="col-lg-12">
          <h1 class="page-header"> Blog Home <small> Blog Homepage</small></h1>
          <ol class="breadcrumb">
            <li><a href="/">Home</a></li>
            <li class="active">Blog Home </li>
          </ol>
        </div>
        
      </div>

      <div class="row">
        <div class="col-lg-8" id="blog-list-view">

          
          <ul class="pager">
            <li class="previous"><a href="#">&larr; Older</a></li>
            <li class="next"><a href="#">Newer &rarr;</a></li>
          </ul>
          
          <div id="blog-list-container"></div>
          
          <ul class="pager">
            <li class="previous"><a href="#">&larr; Older</a></li>
            <li class="next"><a href="#">Newer &rarr;</a></li>
          </ul>
        </div>

        <div class="col-lg-4">
          <div class="well">
            <h4> Blog Search </h4>
            <div class="input-group">
              <input type="text" class="form-control">
              <span class="input-group-btn">
                <button class="btn btn-default" type="button">&nbsp;<i class="fa fa-search"></i> </button>
              </span>
            </div>
          </div>

          <div class="well">
            <h4>Popular Blog Categories</h4>
            <div class="row">
              <div class="col-lg-6">
                <ul class="list-unstyled">
                  <li><a href="somestuff">some stuff</a></li>
                  <li><a href="somestuff">some stuff</a></li>
                  <li><a href="somestuff">some stuff</a></li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      
    </script>

Thank you for reading this post, please share your thoughts below. I will extend this post over time.

Getting Started Full Stack - Building a simple blog - Part 1

In this post, we will install the required components to build a simple blog. In the end of this post, you will be serving a hello world page, with a responsive bootstrap theme, and all necessary script files.

Server Side:

Node.js
Host the website, on javascript platform, based on Google’s V8 JavaScript Engine
Express
Web application framework for node.js
Mongodb
Open-Source NoSQL database written in C++. Also look at Mongoosejs, simple mongodb driver for nodejs.
Bower
Package manager for the web. Simplifies installing client side resources.

Client Side:

Bootstrap
Responsive front-end css framework.
JQuery
Javascript, for interactive webpages.
Backbone.js
Gives structure to web applications. Models, Collections and Views.

Let’s get Started

Introduction

Building a simple blog, solving problems along the path, it’s gonna be fun.

Web Server

Nodejs hosts the website. Serving pages, scripts and stylesheets. Expressjs is a web application framework, simplifies dealing with serving pages. It uses middleware to extend functionality like plugins.

Database

Mongodb our nosql database. it has no relational tables, but nested documents. Mongoosejs is our driver for mongodb on nodejs. Model schemas and operate.

Content Management

Bower downloads scripts and stylesheets from web into our path, we will simply reference it.

CSS Theme

Bootstrap gives the site a nice look. Responsive, meaning it will behave when resized, looks nice on any device.

Javascript

JQuery, main dependency for manipulating dom. Backbone.js is mvc framework for building client side interaction.

Backbone.js is lightweight, and heavily depends on Jquery, a popular alternative is angularjs. Angular.js doesn’t need Jquery, and is a higher level framework.

Backbone.js doesn’t implement templating. Templating is supported by mainly underscore.js or other libraries. (handlebarsjs, mustache)

Backbone.js will teach us more about structure, templating, jquery, and javascript. We should move to higher level frameworks later on. (possibly built on backbonejs) Finally, backbonejs isn’t bound to SPA’s, we may use it for other projects later on (more coming after this).

Installation

I use ubuntu/linux you should find a way to install on your platform, read the guides and google.

Npm, Node.js

# install node.js
sudo add-apt-repository -y ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

# test should look like: v0.10.12
node -v

Or, follow the Instructions

This will also install npm package manager. Npm is used to install packages required by node.js.

Mongodb

# install mongodb
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen

# test should bring mongo shell, Ctrl-c to break
mongo

More Instructions

Bower

#install bower
npm install -g bower
# test should look like: 1.2.8
bower -v 

More Instructions

Congratz, this is enough to host our simple blog. We will learn these tools along the way. Now let’s build our codebase.

Directory Structure

Build the following directory structure. public folder will host our public pages, scripts and stylesheets. ‘scripts’ folder will host javascript code for running the nodejs server, interacting with mongodb.

../mysimpleblog
`-- app
    |-- public
    |   `-- js
    |       |-- collections
    |       |-- models
    |       |-- routers
    |       `-- views
    `-- scripts

Configuration

Package.json

package.json is a packaging format for node.js. Important part here is dependencies, where we declare dependencies for our project. Place it in root folder of your project, where your app folder resides.

express : web application framework, It uses middleware to handle http requests. Middleware could be third party code, which we will use shortly.

baucis : Baucis is Express middleware that creates configurable REST APIs using Mongoose schemata

connect : Lower level middleware for node.js, not important for us any time soon. baucis needs it so we include.

.bowerrc

.bowerrc file will change bower’s default components folder. Place it in root folder of your project.

Installing packages

Server side dependencies are defined in package.json, and installed with npm. Client side dependencies are defined in bower.json and installed with bower.

However we won’t be using bower.json rather install the required files manually.

# install server side packages (defined in package.json)
npm install
#install client side packages manually with bower
bower install bootstrap
bower install fontawesome

bower install jquery
bower install backbonejs
bower install underscore

Server side packages can be directly used in javascript code, we will see how that’s done later. Client side packages are simply files downloaded in directory we defined in .bowerrc so you can check it out there. We will reference them in our index.html.

Setting up the server

Final step is to actually setup the server, so we can host our files. Go to app/scripts directory and create the two files below.

Further information: middleware , require .

Finally we need an index.html to serve, and we are ready to launch. Go to app/public directory and create the file below.

Launch Time

To run the server go to app folder and run:

   # test: output should be 
   # - listening on port 3000
   node ./scripts/web

Now launch your browser and locate to http://localhost:3000.

One final note here is that, if you make changes inside app/public folder, a browser refresh is enough to see the changes, if you make changes inside app/scripts folder, you need to restart the server, in order to changes to take effect. There are tools to live reload every change but that’s for a later time.

Please share your thoughts below. Thank you.

Student learning to code.

Current focus nodejs, express, backbonejs.

No expert on any of the subjects, rather just googling solutions, reading books and patching existing code to own codebase.

Review, and critiques are appreciated, we are going to improve the content together.

In upcoming 2014 going to build a simple blog together.

It should take roughly 6 weeks, 1 post per week.

This is powered by Jekyll.

Jekyll offers powerful support for code snippets:

def print_hi(name)
  puts "Hi, #{name}"
end
print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT.

Jekyll also supports github gists:

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo.