Here at carwow we allocate our Fridays to side projects, performance improvements, and internal tools.

Last Friday we wanted to create a simple dashboard to show our Git commits to the rest of the company.

It was a pretty simple problem — we needed an application to poll the commit list through the GitHub API and show it on a page.

Instead of going for a Rails project we decided to use Meteor. I had played with the framework in the past, so I knew it’s easy to prototype with it and I wanted to see a production system (albeit a small one) using it.

Why Meteor?

One of the main benefits using Meteor comes from the reactive nature of it. To put it simply, ‘reactive’ means that if something changes inside the framework everything gets updated as expected.

For example when the code on the server, the CSS, the client JavaScript code, or a record in the database is updated, the client is notified and will apply the changes on

its part, without the user having to refresh the page.

To do so, Meteor keeps a persistent connection between the clients and the server (via socketjs), and when there’s a change the server sends a message telling the client to update itself.

The client, on the other hand, has a local database (called minimongo). This allows the client to keep copy of the data it needs. So pages are rendered without any explicit interaction with the server.

This makes it extremely easy to create a dashboard: on the server side we just needed to poll from the GitHub API, save the data in the database and let the framework do what was built for.

The code

The logic of the app is split across three main areas:

Get the commit history from GitHub

Share the data with the client

Show the commit data in the client

You can have a look to our project on GitHub. Please feel free to suggest ideas and collaborate.

Step 1: get commit history from GitHub

We wrote a simple wrapper to get the data from GitHub, it’s in the github_api.js file.

To poll the data from the api we wrote an importer using Meteor.setInterval():

// server/startup.js

function getCommits() {

let repos = Github.getRepos()



repos.forEach( repo => {

results = Github.getCommits(repo)

deleteOldCommits(repo);

saveCommits(repo, results);

})

}



Meteor.startup(() => {

Meteor.setInterval(getCommits, 120000);

getCommits()

})

This deletes any data in the Commits collection and replaces it with the new list of commits

In Meteor the code inside the client folder is visible only to the client, while the code inside the server folder is visible only to the server. To share code between the two you can put it inside the lib folder.

We used that pattern to define our collection, in this way we didn’t have to declare it on both environments.

//lib/collections.js

Commits = new Mongo.Collection("commits")

Now on the server we need to publish the data we fetched from GitHub:

// /server/publications.js

Meteor.publish("commits", function() {

return Commits.find({}, {limit: 20, sort: {date: -1}});

})

And on the client we subscribe to the published data — this is the code we need to run:

// client/git_feed.js

Meteor.subscribe("commits");

In this way the client will start getting the data pushed from the server and it will save it in the local mongo db.

Step 3: present the data

Meteor comes with its own template engine called Blaze. By default it works like handlebars. Instead of using the default handlebars syntax we decided to use Jade. Jade makes the syntax similar to haml:

// client/git_feed.jade



head

title git_feed 2

link(href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet")

body

+header

+commitList



template(name='header')

.header Latest changes



template(name='commitList')

ul.collection

each commits

+commitCard



template(name='commitCard')

li.commit

.collection-item.avatar

img.circle(src=author.avatar_url, alt='')

span.title= author.name

p!= escapeMessage(message)

Each template can have its own helpers, the most interesting thing here is how we are showing the list of commits:

Template.commitList.helpers({

commits() {

return Commits.find({}, {sort: {date: -1}});

}

});

In this snippet you can see how the helper returns records from the local collection.

When the server updates the Commits collection the following happens:

The server publishes the updates

The client gets notified and updates the local database

The commits() function in the client gets executed and the page is re-rendered

We used Heroku to serve our app. To configure it for our needs we just used the buildpack available here and followed the instructions. Apparently now Heroku supports web sockets on multiple dynos and you can just add the support using heroku labs:enable http-session-affinity.

And here’s a screenshot of the app:

Meteor is a relatively young framework and that can be noticed by the limited number of tools available out of the box. Routing, for instance, is not supported by the core framework. Organising your files is another issue: Meteor doesn’t have conventions to help organise your files (compared to Rails, at least). It’s good to have the freedom, but a better defined structure can help you navigate code written by others.

On the other hand, Meteor has a great community, so what is not provided by the core team can be easily found in the huge list of packages inside Atmosphere.

The framework is easy to use, as long as you don’t mind writing some js code.