Statistics Page with Aurelia and Bootstrap 4

I really like how the New York Times displays interesting statistics about their business on their corporate website, The statistics are overlaid on photographs. They change when the page is refreshed. In this post we’ll use Aurelia and Bootstrap 4 to create something similar.


Start by installing the Aurelia CLI using npm and create a new project. Choose the default options. By default Babel is used for transpiling modern javascript to ES5.

npm install aurelia-cli -g
au new

Add Bootstrap 4 by linking to the CDN files in the header of index.html.

<!DOCTYPE html>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
    <script src="" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
    <script src="" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
    <script src="" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

  <body aurelia-app="main">
    <script src="scripts/vendor-bundle.js" data-main="aurelia-bootstrapper"></script>

Now update app.html, under the src directory, with the code below. This file is the view that will display the statistics. The view contains a template which contains a repeater.

  <require from="css/main.css"></require>
  <div class="container">
    <div class="row">
      <div class="col">
        <div id="stats-container" css="background-image:url('${theme.backgroundImage}')">
          <ul class="list-unstyled">
            <li repeat.for="stat of stats" class="h2">
              <span css="color:${theme.color}">${stat.number}</span> ${stat.description}

Templates work with view-models. By convention views and view-models in Aurelia have the same name. So our view-model for app.html is app.js. Update app.js to look like this:

export class App {
  constructor() {
    this.themes = [
      { color: '#FFBE0B', backgroundImage: './images/1.jpeg' },
      { color: '#E7F6CC', backgroundImage: './images/2.jpeg' },
      { color: '#AD2100', backgroundImage: './images/3.jpeg' },
      { color: '#CA8A3F', backgroundImage: './images/4.jpeg' },
      { color: '#EFD133', backgroundImage: './images/5.jpeg' },
      { color: '#8A3909', backgroundImage: './images/6.jpeg' }
    this.theme = this.getRandomTheme();
    this.allStats = [
      { number: '7,600,000', description: 'subs are served at Subway every day' },
      { number: '7,500', description: 'varieties of apples are grown throughout the world' },
      { number: '2,500', description: 'varieties of apples are grown in the United States' },
      { number: '671,396,071', description: 'cups of coffee were sold by Starbucks in 2017' },
      { number: '58,301', description: 'fusce cursus nisl in massa pulvinar' },
      { number: '8,645', description: 'nam aliquet, dui sed sagittis lobortis' },
      { number: '3,580', description: 'vivamus enim ligula, finibus vel purus non'},
      { number: '26,924', description: 'integer et erat neque' },
      { number: '14,597', description: 'vivamus mi sem, cursus in nisi vel' },
      { number: '876', description: 'ut mollis dui in ornare aliquam'},
      { number: '168', description: 'fusce auctor tristique elit, nec lacinia augue'},
    this.stats = this.shuffle(this.allStats).slice(0, 7)

  getRandomTheme() {
    return this.themes[Math.floor(Math.random() * this.themes.length)];

  shuffle(array) { //
    var currentIndex = array.length, temporaryValue, randomIndex;
    while (0 !== currentIndex) {
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    return array;

When the view-model is created it’s constructor() is called and the theme and stats arrays are instantiated. The repeater in our template loops over these arrays and uses databinding to set the text color and display the background image, numbers, and descriptions.

Now we need to create a directory for the images. Create this directory at the top level of the project. The images are from lorempixel.


Create a directory called css in the src directory. Add main.css containing this code:

/* Extra Extra Small Devices, Phones */ 
@media only screen and (min-width : 0px) {
    #stats-container {
        background-size: cover;
        margin-top: 2em;
    #stats-container ul {
        font-size: 2rem;
        color: white;
        padding: 1em;
    #stats-container li {
        padding: 0 0 1em 0;
    #stats-container span {
        font-weight: bold;

/* Extra Small Devices, Phones */ 
@media only screen and (min-width : 544px) {}

/* Small Devices, Tablets */
@media only screen and (min-width : 768px) {}

/* Medium Devices, Desktops */
@media only screen and (min-width : 992px) {
    #stats-container ul {
        padding: 1.5em 2em;

/* Large Devices, Wide Screens */
@media only screen and (min-width : 1200px) {}

Test the project using the run command:

au run

Finally, build the project using the build command. The files needed for deployment are index.html, the images directory, and the scripts directory.

au build --env prod

View a demo here. Download the source files.

- Bootstrap 4 Grid system
- Aurelia

This entry was posted in Uncategorized. Bookmark the permalink.