/aura

A scalable, event-driven JavaScript architecture for developing widget-based applications.

Primary LanguageJavaScriptMIT LicenseMIT

Aura 0.9pre

Build Status

Aura is an event-driven architecture for developing scalable applications using reusable widgets. It works great with Backbone.js, but is framework-agnostic, adapts many best-practice patterns for developing maintainable apps and has first-class support for modern tools like Bower, Grunt and Yeoman.

Aura has been used to develop applications like MIT's Reap and is currently under active development.

Why Aura?

We've seen a large shift in the JavaScript community for the past 3 years, with people starting to write web apps in a much more structured way. Yet, assembling the bits and pieces and actually starting to make apps is still a challenge. Another challenge is that most of the time you end up doing the same stuff all over again : you need a way to authenticate users, give them ways to communicate, exchange ideas, work or play together. You have to integrate with external services or APIs like Facebook or Twitter.

Web apps are all about the end user experience (UI, DOM elements). The web development ecosystem is all about much more low level stuff. We need a way to package higher level abstractions and make them truly reusable, and that's what Aura is all about.

Need some more reasons to use Aura?:

  • It's basically glue for your application widgets, making it trivial to tie together a number of independently created widgets into a fully functional application.
  • A complete event-bus supporting application-level and widget-level communication mean you have control over what is getting triggered in your app
  • Specify an API end-point for widgets easily and just use data-attributes to include any widget or widgets. Minimal JavaScript for more capabilities.
  • Abstract away utility libraries you are using (templating, DOM manipulation) so that you can swap them out for alternatives at any time without a great deal of effort
  • Hit the ground running quickly widgets into reusable modules using AMD.
  • Bower is a first-class citizen in Aura, making it easier to manage your application dependencies
  • The web platform is moving towards using scoped styles and shadow DOM for keeping parts of your page safe from third-party content that might affect it. Aura does the same for communications by introducing per-widget sandboxes for your events
  • Tooling for scaffolding out new widgets without having to write as much boilerplate
  • Can be used with your MVC framework of choice - we're just there as a helper.
  • First-class support for the Hull.io platform. If you don't want to create a widget yourself, you can easily use them as a widget-source and create apps in less time.
  • Extensible via the extensions system, which make a good basis for a rich ecosystem around the project.

Concepts

The Aura object

Your application will be an instance of the Aura object.

Its responsibilities are to load extensions when the app starts and clean them up when the app stops.

Extension

Extensions are loaded in your application when it starts. They allow you to add features to the application, and are available to the widgets through their sandbox.

Core

The core implements aliases for DOM manipulation, templating and other lower-level utilities that pipe back to a library of choice. Aliases allow switching libraries with minimum impact on your application.

Sandbox

A sandbox is just a way to implement the facade pattern on top of features provided by core. It lets you expose the parts of a JavaScript library that are safe to use instead of exposing the entire API. This is particularly useful when working in teams.

When your app starts, it will create an instance of sandbox in each of your widgets.

Widget

A widget represents a unit of a page. Each widget is independent. This means that they know nothing about each other. To make them communicate, a Publish/Subscribe (Mediator) pattern is used.

Getting started

The simplest usable Aura app using a widget and extension can be found in our boilerplate repo. We do however recommend reading the rest of the getting started guide below to get acquainted with the general workflow.

Requirements

  1. bower: run npm install -g bower if needed
  2. grunt-cli: run npm install -g grunt-cli if needed

Building Aura.js

  1. Run npm install to install build dependencies.
  2. Run bower install to install lib dependencies.
  3. Run grunt build and aura.js will be placed in dist/.

Running Tests

Browser

Run grunt. Then visit http://localhost:8899/spec/.

CLI

Run npm test.

Creating an Application

The first step in creating an Aura application is to make an instance of Aura.

var app = new Aura();

Now that we have our app, we can start it.

app.start({
  widgets: 'body'
});

This starts the app by saying that it should search for widgets anywhere in the body of your HTML document.

Creating a Widget

By default widgets are retrieved from a directory called widgets/ that must be at the same level as your HTML document.

Let's say we want to create an "hello" widget. To do that we need to create a widgets/hello/ directory

This directory must contain:

  • A main.js file. It will bootstrap and describe the widget. It is mandatory, no matter how small it can be.
  • All the other files that your widget needs (models, templates, …).

For our "hello" widget the main.js will be:

define({
  initialize: function () {
    this.$el.html('<h1>Hello Aura</h1>');
  }
});

Declaring a Widget

Add the following code to your HTML document.

<div data-aura-widget="hello"></div>

Aura will call the initialize method that we have defined in widgets/hello/main.js.

Creating an extension

Imagine that we need an helper to reverse a string. In order to accomplish that we'll need to create an extension. By default extension are retrieved from a directory called extensions/ that must be at the same level as your HTML document.

define('extensions/reverse', {
  initialize: function (app) {
    app.core.util.reverse = function (string) {
      return string.split('').reverse().join('');
    };
  }
});

Emitting and listening for event notifications

The Aura Mediator allows widgets to communicate with each other by subscribing, unsubscribing and emitting sandboxed event notifications. The signatures for these three methods are:

  • sandbox.on(name, listener, context)
  • sandbox.off(name, listener)
  • sandbox.emit(data)

Below we can see an example of a Backbone view using the Mediator to emit a notification when tasks have been cleared and subscribing to changes from tasks.stats in order to render when they are updated.

define(['hbs!./stats'], function(template) {
  return {
    type: 'Backbone',
    events: {
      'click button': 'clearCompleted'
    },
    initialize: function() {
      this.render();
      this.sandbox.on('tasks.stats', _.bind(this.render, this));
    },
    render: function(stats) {
      this.html(template(stats || {}));
    },
    clearCompleted: function() {
      this.sandbox.emit('tasks.clear');
    }
  }
});

Using extensions

To make our reverse helper available in our app, run the following code:

app.use('extensions/reverse');

This will call the initialize function of our reverse extension.

Calling use when your app is already started will throw an error.

Debugging

To enable debug extension and logging pass {debug: {enable: true}} into Aura constructor:

var app = new Aura({debug: {
  enable: true
});

Logger usage:

// You can use logger from widgets or extensions
var logger = sandbox.logger;

logger.log('Hey');
logger.warn('Hey');
logger.error('Hey');

//Or directly from Aura app

var logger = app.logger;

Below we can see an example how to enable logging in specific ext/widgets. By default all loggers are enabled.

var app = new Aura({debug: {
  enable: true,
  components: 'aura:mediator login signup info'
});

Built-in components:

  • aura:mediator - event logging.

Also, when debug mode is enabled, you can declare following function for any debug purposes:

// Function will be called for all Aura apps in your project
window.attachDebugger = function (app) {
  // Do cool stuff with app object
  console.log(app);

  // Maybe you want to have access to Aura app via developer console?
  window.aura = app;
};

Resources

Yeoman generator

An Aura scaffolding generator (for Yeoman) is also available at Aura generator.

Usage

  # First make a new directory, and `cd` into it:
  mkdir my-awesome-project && cd $_

  # Then install `generator-aura`:
  npm install -g generator-aura

  # Run `yo aura`, optionally passing an app name:
  yo aura [app-name]

  # Finally, install npm and bower dependencies:
  npm install && bower install --dev

Generators

Available generators:

Widget

Generates a widget in app/widgets.

Example:

yo aura:widget sample

Produces app/widgets/sample/main.js

Extension

Generates a extension in app/extensions.

Example:

yo aura:extension storage

Produces app/extensions/storage.js

Styles

Generates cool styles.

Example:

yo aura:styles
Supported types:
  • Default (normalize.css)
  • Twitter Bootstrap
  • Twitter Bootstrap for Compass
  • Zurb Foundation

Examples

Want to look at some sample apps built with Aura? Check out:

###The GitHub client

###The GitHub Mobile client

###Hullagram - an Instagram clone built with Aura and Hull.io.

###An Aura TodoMVC app implemented two ways

###Writing a simple GitHub widget using Aura.

Aura Development docs

FAQs

Why do developers use us?

  • "The architecture and the fact that Aura Widgets are completely decoupled, will allow us to build an ecosystem of widgets that people can reuse internally or share with others."
  • "With WidgetSources and Require, we can load only the widgets that are needed by the app... at runtime."
  • "No JS is required to wire everything up, just include widgets with data-attributes in their markup"
  • "Mediation, same thing here it's a prerequisite to make everything decoupled... but in addition, it allows us to write much less code..."
  • "Template overrides FTW"

Contribute

See the contributing docs

Project status

Aura 0.8.x was well received by the developer community, but had regular requests for a few advanced capabilities. These included individual sandboxes, declarative widgets, support for Bower and a powerful Pub/Sub implementation amongst others.

To cater for this, Aura has been getting a heavy re-write over the past few months and we anticipate releasing a beta that can be tested in April, 2013. This will be followed by detailed documentation and new demo applications.

A version of Aura currently powers the Hull.io widget platform and we are honored to have members of that team directly contributing to the next version of the project.