[DjangoWaves] How To Build A Status Page For Uptime And Incidents

Who wrote this course?

Hi there! Thanks for purchasing this course. My name is Stan Triepels. I live in the Netherlands and I have been developing for years with Django and VueJS. I have built multiple SaaS businesses from scratch. Some more successful than others. One of the biggest platforms I have built is called ChiefOnboarding. It’s onboarding software, used by businesses. It uses everything that I will mention in this course and so much more.

I noticed that a lot of people (probably like you) were posting questions on forums and I thought it would be useful to create a crash course on how to use VueJS and Django together.

If you have any questions about me or this course, feel free to send an email to hello@djangowaves.com. That’s where I live. I generally reply quite quickly.

Set aside quite a few hours and walk through the course at your own pace. I am here if you need help. You can also add me on skype (stan.triepels) or Discord (stantriepels#5034) or just send me an email at hello@djangowaves.com.



The what/why/how about this course

When you are reading this, you have already bought the course, which means that you should have a vague idea of what this is all about. Yup… you got that right. Django and VueJS. We will be building a status page to track uptime and incidents. This is going to to be a tool that will be used by system administrators to keep customers and/or users up-to-date on the current status of your system. Have an unfortunate outage? This status page will send updates to users and will, therefore, help you decrease support hours.

What’s the goal of this course?

That’s quite simple. You will learn how to use Django and VueJS in a way that you can host both the front end and the back end on different servers, still acting as one site. This means that we won’t be using the default templates files, except for emails. We will use VueJS to render the front end part. Django will be used as a standalone API.

Why are we building an application like this?

Honestly, we could also build this application with the standard MVT structure that Django uses. Without having to use Vue a lot. So, you might be wondering why we are separating both anyway. The main reason is to learn this way of developing. Let’s say we would also like to build a mobile app for status tracking (this is very unlikely for this type of application – but just bear with me for a second), in that case, we need to communicate with the same server to get all the data. If we would go with the standard structure, we couldn’t get that info properly.

Now, we have a full REST API that can be used for mobile applications as well. The only thing that would need to be built is the front end of the mobile application. That would need to be done in Android Studio or Xcode depending on what platform you want to support. Actually… that’s not entirely true. You could also create so-called hybrid applications. Those are applications that are built with JavaScript (with the VueJS framework in this case). That part won’t be covered in his course, but if you would like to see that, then be sure to let me know! In the meantime, take a look at Weex or Quasar if you want to learn more.

How are we building this application?

Developing an app or website goes through various phases. In this course, we will skip the requirements gathering and designing parts. I have already completed those part and we will start right away with building this application. We will first start with the front end, this is generally advised to do when you are building user focussed applications. If you prefer to build the back end first, then that’s fine too. Though, I would recommend to follow this course step by step and not skip chapters.

After the coding part, we will test our whole application. I will show you how you can properly test your application and make it (almost) entirely bug-free. Remember that there is no such thing as bug-free software.

After the testing part, we will deploy our application on multiple server setups. Django applications aren’t necessarily fun or quick to deploy, but I have made that easy for you :).

MPA vs SPA and why it matters

The standard type of applications developed with Django are MPAs (multiple page applications). You use its built-in Model View Template. It’s the structure which Django uses to separate the database tables and functions, the logic and the html templates from each other. I am not sure how old you are, but if you have been developing for a bit, I bet you remember the good old days when sites existed from one messy PHP file, completely unorganized. I am glad those days are gone, even though I still find a gem every now and then.

The sites that are created through the MVT model could be dynamic. Though, for things to change, you will need to refresh the page. This is assuming that you are not using any JavaScript to do some funky stuff. This means, that if you want to submit a form, it will have to submit the info to the server and you get a full page back, which requires a full reload of the page.

A SPA (short for Single Page Application) on the other hand does not have to reload the page. It just reloads the parts it wants to reload and does this based on JSON code that it gets from the server. An example would be that when you submit a form, you will actually stay on the same page – it will not reload. It will only change a small part of the site where it says that it submitted it successfully (or unsuccessfully). This could be done based on something like this from the server: {'status': 'ok'} .

When would I go for SPAs?

There are quite a few reasons why you would want to build single page applications over the normal structure. Here are a few of them:

  • You want to speed up the development process. When you split the back end from the front end, you can split the work over two teams. One doing the front end and one doing the back end. This could also increase the quality of your product, since you can hire people that are specialized in one thing. Most devs are better at either front end or back end, so you can put the best people together.
    One note to this is that if you are developing an application that isn’t too complex but does have a lot of user input, then it could actually be more work to create one with an SPA.
  • If you want to build a mobile app as well. Now, this isn’t always true. But in most cases, you will have to build an API to consume for the SPA to interact with a server. This same API could be used for the mobile app as well if the information you need is somewhat the same. This allows you to write less code, but still get the same results.
  • If you are in a region with unstable internet and have visitors that visit lots of pages. This isn’t as common anymore, since a huge part of the world has stable internet. SPAs will ‘download’ the entire site on the first load. You can also cache a lot of data in your browser (don’t do this with personal info though). Which means that you won’t need to communicate with your server that much.

When would I need to use standard MPAs?

There could be quite a few reasons why you would want to build an application with the standard MVT structure over SPA. Here are a few reasons:

  • You want to build something with SEO in mind. Search engines are getting better at indexing pages rendered by JavaScript, but we are not there yet. If you care deeply about ranking your site in your preferred search engine, then you will want to play it safe and use Django to render the entire page. That way you know that search engine can always fetch the content.
  • You have a lot of different pages to display. Think of e-commerce stores. Most people who visit an online store, will want to see the product fast. A lot of them won’t buy it if it’s slow. They don’t need/want to load the JavaScript to be able to see all of the pages. That’s why an MPA would be better.
  • Marketing pages. Generally, marketing pages are one-off pages that can simply be loaded without much JavaScript. Most of the time, they doen’t have a lot of moving elements and only contains a simple ‘signup form’. There is no need to make this all more complex with a SPA when you can just load this through as a ‘normal’ MPA.


You don’t need much to be able to roll through this course smoothly. The things that would come in handy:

  • A computer with internet access
  • Django and Vue (with NPM and webpack) installed
  • Successfully completed the Django introduction tutorial
  • Installed the Vue debug tool extension.
  • Have a solid idea of how HTML/CSS/JavaScript works.
  • Use whatever text editor/IDE you want. My personal favorite is VS Code.

If you want to deploy the app, then you also need access over a VPS, which costs a few bucks per month. I generally recommend Digital Ocean or Vultr (disclosure: both are affiliate links, though my opinion is not influenced by that – I use both providers for production applications every day).

Make sure you also have created an empty folder somewhere on your computer. I will call this folder ‘course’, but you are free to call it whatever you want. It’s not important for the course itself.

Set up VueJS

Let’s get our Vue site up and running. Install the required libraries:

npm install -g vue-cli 
vue init webpack front

It will now start to ask you some questions. The only thing you have to watch out for, is that you pick the standard linter (instead of the Airbnb one) and make sure you opt-in for end2end testing. Pick Jest for this.

It will now start to ask you some questions. The only thing you have to watch out for, is that you pick the standard linter (instead of the Airbnb one) and make sure you opt-in for end2end testing. Pick Jest for this.

Example output:

Project name front
? Project description A Vue.js project
? Author stantriepels
? Vue build (Use arrow keys)
❯ Runtime + Compiler: recommended for most users
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (recommended) npm

This will take some time. Let’s continue:

cd front 
npm install 
npm run dev

Great! Our website is now live at http://localhost:8080 if you are not running other services on that port. It will auto increment with 1 until it finds a free port. When you go to that, you will get the default Vue example page like this:

When you open the newly created folder in your favorite text editor, you will see a bunch of files and folders. The one that is important for now is the src folder. That’s where we can create the front end. The layout of the folder should look like this:

Alright, great. We can now start creating the front end of our website.

Our design

So, for this course, I have designed a quick design which we will build from scratch. That’s right – we will not use a Vue CSS framework for this one. I want to show you how you can create components and how they can be useful. Don’t worry though, it’s not that much custom CSS that we need. I will not explain the CSS in detail. If you want to know what something does: Google it.

Here is our design:

Vue uses components. Components are smaller files, parts of a site, that can contain JavaScript, HTML and CSS. Eventually, all of those components are bundled together and then compiled into a few files.

Let’s split the design file into some pieces we will create with those components. These are the yellow lines:


We currently have an empty project, which only shows us the default Vue page with a few links. Remove the current component HelloWorld.vue (which is in src/components/ ). Create a new folder in src/components/ and call it general . In this folder, we will put some components that are used everywhere. Think of the header, footer, indicator and notification bar.

Our base component

In general create a new file that’s called NotificationBar.vue . Let’s add the default empty component structure in this:


export default {
  name: 'NotificationBar'

<style scoped>


As you have probably seen, I have given this component the name ‘NotificationBar’. This component has 3 different blocks. The first one is for the HTML. I have already added one empty div . This is required. For every component, you have to start with one root html tag and build your component in that.

Then we have a script part. This is the part where we will do all the logic. This is the part where our JavaScript code goes.

At last, we have a style part. This is where our CSS styling goes. The scoped attribute means that this styling will only be applied to this component. Other components will not be affected by this. This also means that you can use reuse class names without having to use the same CSS style (I wouldn’t recommend this though. This can get confusing quickly). If you remove scoped then the styling will apply to inner components as well. Inner components are the components that live inside of other components. It’s often referred to as parent and child component.

Let’s create our notification component

We will add some more code to this component to make our notification bar component. Let’s create a variable that we can use to show a notification with. Change your script tag with this:

export default {
  name: 'NotificationBar',
  data () {
    return {
      notificationErrors: [{'color': 'red', id: 0, text: 'Oh, we are having some issues'}]

So, what did we do exactly? We have added the data function to our JavaScript. This function returns all variables that you want to use in this component. These variables are isolated, which means that other components can’t touch them easily. We have added the variable ‘notificationErrors’. If you were to do this without Vue in vanilla JavaScript, then it would have been like this:

var notificationErrors = [{'color': 'red', id: 0, text: 'Oh, we are having some issues'}]

notificationErrors is an array of object(s). We will use this object in the template part. Add the following inside of the div in the template part (you will have two open divs in this case):

  v-for="i in notificationErrors"
  :class="'full-background ' + i.color"

So what are we doing here exactly? We are creating a new div for every notification that we have. We add a class, depending on what value the color key has in the object and we show the text inside this div. Vue requires us to add a key to every div that is created in a for loop and we do that with the :key="i.id" . Also notice the class part. We add a : before the class name. Which is short for v-bind: . This means that we can use variables in the class. In this case, we first have static text which has to put in single quotes. Then we add our variable to it with the i.color part.

If we were to do this with Django, then it would have looked like this:

{% for i in notificationErrors %}
    <div key="{{i.id}}" class="full-background {{i.color}}">
{% endfor %}

Let’s also add some styling in the <style scoped> part to make it look like a bar:

.full-background {
  padding: 10px;
  z-index: 0;
  position: relative;
  text-align: center;
  color: white;

For now, that’s our NofiticationBar component. It’s not reactive, we can’t change the data in it yet, but we will get to that later. Let’s show the component on our index page now.
Currently, the / url is routed to our HelloWorld.vue component. It’s the one that comes with the Vue boilerplate. Let’s create a new folder in our components directory and call it home . Make a new .vue file which we will call Home.vue , copy-paste the empty component structure in this file. Change the name of that component to ‘Home’.

The point of the two folders that we have created is to organize our components a bit. We will end up with about 10 components and if you don’t organize them, it can get messy quickly. You are free to organize them as you want, there are no strict guidelines here. In this case, we will put all general components in the general part and all specific page components in specific page folders.

Let’s go to the router (in router/index.js ). This router is here to make different pages for our app. It’s quite similar to the one for Django. With the router, we will always get a component to be shown. As you can see, we have a line that’s called import HelloWorld from '@/components/HelloWorld . We just removed the HelloWorld component, so this will error when we visit our site. Let’s change that to our new Home component: import Home from '@/components/home/Home' .

The router instance itself looks like this:

export default new Router({
  routes: [
       path: '/',
       name: 'HelloWorld',
       component: HelloWorld

It’s pretty much self-explainable, but the path defines part of the URL. Name is the name of this URL (similar to name="something" in Django) and the component is the component it should show. Let’s change both HelloWorld s to Home .

If you go back to your browser and check out the page, then it should look like this:

It’s quite… empty. This is normal. Our new component is an empty one, so it doesn’t actually show something. Yet, we still have that Vue logo there. That’s actually coming from App.vue . You will find it outside of the components folder. This is the base file. If you have anything that should be on all pages (think of headers and footers), then this is the place to put it. And that’s exactly where our Notification component should be added too. This is how it currently looks like:

  <div id="app">
    <img src="./assets/logo.png">

export default {
  name: 'App'
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;

As you can see, there is an image tag ( <img src="./assets/logo.png"> ) which is why it shows the image on our page. Next to that, we have a <router-view/> . This will be replaced with a component based on what page we are (according to our router file). You can even nest router-views in components, but we will get to that later. When we go to our home page, the <router-view/> part will be replaced by our empty home component. Easy enough, right?

Let’s add our Notification component to our app. It’s currently a standalone component which isn’t imported anywhere. Go to your App.vue file and import the notification component with: import NotificationBar from '@/components/general/NotificationBar' . You should place this right above the export default { line. This allows us to use the external component in the App component. Up next, we will have to register this component as a component we want to use in the template. We can register it like this:

components: {

You should put these 3 lines under name: 'App' . Don’t forget to add a comma after 'App' . Up next, replace the image tag in your template with <NotificationBar /> . This will import the component at that place.

Finally, we have to add a bit of styling here. This styling will be used throughout the application, so we will add this in App.vue :slight_smile:

body {
  font-family: Montserrat;
body, html {
  margin: 0px;
  padding: 0px;
h2, h3, h1, h4 {
  margin-top: 5px;
  margin-bottom: 5px;
a, a:focus, a:visited, a:hover {
  color: #000;
  text-decoration: none;
.issue, .yellow {
  background: #F1C21A;
.down, .red {
  background: #CD5C5C;
.up, .green {
  background: #2EE779;

emove the other default styling that is in the <style> block in App.vue . Then go to your index.html file in the root of your VueJS project and add this part in the header:

<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700" rel="stylesheet">

When we go to our website now, we will get a blank page with an error message.

Okay, great. So now we have our error messaging bar. We will add some fancy transition effects to this later on in the course.

1 Like

Добрый день!

А продолжение будет?