Skip to content
This repository

Mozilla OpenBadges

Badge plumbing for all!

Hi, welcome to the Mozilla OpenBadges wiki. For an overview of the OpenBadges project, and to earn your first OBI compliant badge, see If you want to play around with Mozilla's hosted version of this code, you can create your own Badge Backpack at

This wiki is focused on documenting the Open Badges Infrastructure reference implementation (OBI). This code runs, and acts as the pipes that keep the larger badges ecosystem humming. The goal of the code (and the project) is to provide a user-centric backpack that allows badge earners to collect OBI compliant badges from multiple badge issuers. The user then has the option of displaying the badges wherever they'd like.

A full list of wiki pages is available here. Depending on your reasons for being here, these pages are probably useful,

I want to help, how?

If you're interested in contributing to the project (hurray! you should!) the place to start is the official README. Join our Google Group, and look for us on IRC at #badges, specifically the tech team:

If you need help using IRC, reading this wiki will help you get started.

You can also jump in right away by picking up a ticket and working on it. We've marked a handful of tickets as "Volunteer On-boarding," which is a reasonable place to jump in and get started. However, if you're really into it, feel free to just pick up a big issue and run with it. Make sure you comment in the issue so we know you're working on it.

If you're new to contributing to an open source project on Github, start here - How to fork a Github repository. Once you've made your changes to your fork, send them to us as a pull request, mentioning the issue you're addressing in the pull request description.

How does everything tie together?

OpenBadges uses an MVC architecture, with a separate place for static content like CSS and JavaScript for pages. Things work together as follows:

  • app.js contains all the master code, as well as the URL routing. If you want to know how a specific URL maps to a specific page-in-the-code, you'll find it in this file. All mappings are located in the router function call.

  • ./controllers houses all the code that can be triggered from page loads.

  • ./models houses all the code that describes the data structures in OpenBadges.
  • ./views houses all the templates that are used by the OpenBadges site.

Note that the "master" header is found in ./views/layout.hogan.js, which contains all the CSS and script includes before a page-specific template is added to the page rendering.

  • ./static/js houses all the javascript that is loaded in the master header. If the template ./views/backback.js" is loaded, then./static/js/backpack.js` will also be loaded, for instance (because layout.hogan.js has a script include for it).

  • ./static/css houses all the stylesheets, although the only stylesheet that should be touched is style.css

An example page rendering

Loading up the base page on localhost:8888, app.js loads up the ./views/layout.js template, and for the specific content then routes to the "backpack" controller, in ./controllers/backpack.js. Specifically, it calls backpack's manage function (it does this for both / and /backpack urls):

  • .get('/', 'backpack.manage')
  • .get('/backpack', 'backpack.manage')

The backpack.js controller requires the Badge and Group models (./models/badge.js and ./models/groups.js) in order to access the data that is stored in the database, which it uses in the manage function. Page output is generated by the makeResponse function, which does data masaging, and loads up the actual HTML template and associated resources by calling response.render('<template name>', {parameter object{).

When the template is loaded, its ./views/templatename.hogan.js is added to the http response, and the user gets this page back. This will load all the JS that layout.hogan.js indicates should be loaded, as well as any script that's inlined in the template file.

A note on frontend development involving badge dropping and other interaction behaviours

./static/js/backpack.js defines a number of interactions and behaviours in terms of which event should be listened to on which elements, based on CSS selector, mapping to which JS function. However, the way it does this may seem a bit unusual for people unfamiliar with Backbone.js: page fragments are marked as mapping to specific Backbone.js views, with event handling defined like this:

    Group.View = Backbone.View.extend({
      parent: $('#groups'),
      tagName: "div",
      className: "group",
      events: {
        'keyup input': 'checkDone',
        'focus input': 'storeCurrent',
        'blur input': 'saveName',
        'drop': 'badgeDrop',
        'mousedown .delete': 'preventDefault',
        'click .delete': 'destroy',
        'click .share': 'share',
        'change .js-privacy': 'savePrivacy'

In this definition, lines like 'focus input': 'storeCurrent' mean "listen to the focus event for all elements that match the CSS selector input. When it fires, call the function storeCurrent that is defined in this view.

This is rather different from the plain html on...="someJSFunction()" approach, or the jQuery $("...").on("event",function(){...}) approach. If you are looking for on-page behaviour, look through the event binding list in ./static/js/backpack.js.

Also note that this means that UX changes generally have to touch two files; the hogan template, to modify the HTML structure, and the ./static/js/backpack.js file to modify the on-page interactions and behaviours

Development, Staging, and Production AWS Information

To get changes onto development, please make your changes, commit or merge to development branch, and then tag as indicated here.

  • Tag version number must be 0.0.*
  • Annotated tag must begin with dev

For example: If the current dev tag is dev0.0.1, use the following: ** git tag -a dev0.0.2 -m "Some notes about 0.0.2"

For staging and production tags, we will avoid using the 0.0.* series version numbers.

Something went wrong with that request. Please try again.