spice up your Golang app with a GUI — part 4: Single Page Application with Vue.js

video @ https://youtu.be/CwdYG8rTOdY

This tutorial would be broken into several stories; each of them exploring a separate concept so that you can read only the interesting pieces instead of everything. This is the 4th story in the series talking about the creation of a Single Page Application with Vue.js. Links of the stories:

source code @ here:


a brief history of web applications and Javascript

Traditional web applications are typically used for displaying data retrieved from server side. Based on this major responsibility, the webapp is less feature packed and maybe just a few fancy Javascript effects and that’s it. Instead, lots of work are done through the server side code. Examples are the ASP / ASP.net, JSP, PHP and so on.

Later on, a new technology known as ajax has evolved. Thanks to this technology, Javascript code can now make request to the server side WITHOUT issuing a page reload (in the traditional webapps mentioned above, a page reload is required per “action” and actions could be asking for the latest book categories or display products on the 5th page etc). Starting from then, some of the presentation code starts to shift back to Javascript (client side) and server side code can focus more on business logic BUT still maintain certain degrees of the presentation code logic.

For recent years, browser technologies have gone through a lot of improvements and getting much much more powerful than before. Along with the browser’s revolution, so did Javascript! In the old days, Javascript was just a language for fun (usually for adding fancy visual effects on the webapp) and nowadays Javascript could be a serve-side / backend language too (check node.js) plus ECMAScript standards 5 and 6 have made Javascript more and more complete; similarly a lot of frameworks add capabilities to the Javascript language through transpilation — for example, typescript added Object Oriented Programming capabilities to pure Javascript syntax (finally you can use Interface, Class, Inheritance etc).

SPA — Single Page Applications

Lately, a new type of webapp has evolved, known as SPA — Single Page Applications. Some characteristics as follows:

  • actively self updates the UI / webpage contents
  • no page reload in general; instead components of the webapp are updated dynamically by Javascript
  • server side requests are made through ajax and asynchronous operations could be handled through promises or equivalent workarounds
  • the UI screen is decomposed into components which could be re-used

So SPA is kind of like building an application through components; and Javascript glues the presentation logic (components) with the server-side data. The advantage of such approach is that maintainability is much easier, instead of maintaining the whole web page as a unit (rather big and bulky); now the unit of maintenance is based on a much smaller component. Take an example, if the presentation logic of a panel needs to be updated, simply update that component and the rest of the web page / app should not be affected. Of course, we do assume that the interface between the component and the server side code remain intact at this point.

Concept is rather simple, but it would be handy if a framework is available to provide some basic integration functions. One of the most well known framework facilitating SPA is react.js — powered by Facebook. React.js is a powerful framework and some concepts as follows:

  • completely separate the UI code with the business and presentation logic
  • everything on the webapp is a component in general
  • a rich set of integration and utility functions available

However the downside of react.js is the learning curve; it wasn’t easy to grasp all the concepts when developing a webapp with react.js; especially when we need to use redux on controlling the application states…

In order to make the SPA development a bit more pleasant; I have chosen Vue.js instead. Vue is like an easier version of react.js, yet still very powerful and more developer friendly. Though community support wasn’t as much as react.js…

revamp on the index.html

Okay, after all those history lesson earlier; let’s get back to our webapp development. Before we can use Vue.js, we need to install the framework code. Basically 4 approaches are available:

  • script include — either download the source of Vue and include/import it to the html
  • cdn include — include the Vue source through cdn
  • npm — if you are a node.js developer, use npm to install the dependencies for your webapp is possible
  • vue cli — we can also install the cli (command line interface) and create a vue webapp skeleton. (this approach is very similar to the npm way; the only difference is all package dependencies are generated plus a sample webapp is created for us)

For more information, do checkout the official documentation

The approach I would pick is the simplest one — cdn include. So all we need is an internet connection and all good :)

PS. for serious development, npm approach should be considered as more tools are available to optimise our Javascript code (e.g. webpack)

Let’s add back some cdn includes, also adding bootstrapp css includes on the HTML header section.

<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

<!-- vuex -->
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
<script src="https://unpkg.com/vuex"></script>
<!-- JQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- Bootstrap tooltips -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"></script>
<!-- Bootstrap core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<!-- MDB core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.8.11/js/mdb.min.js"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Bootstrap core CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.8.11/css/mdb.min.css" rel="stylesheet">

Yeap quite a lot of imports and we will go through them later once we need these javascript frameworks / libraries.

on our index.html; add back a button to verify if the above imports are valid:

... js library and css imports ...

<body onload="onStart()">
<button class="btn btn-primary">bootstrap buttons</button>

re-build the app and run the application should yield the following:

go run generateAssets.go
mv generateAssets.go generateAssets.go.disable
go build -o taskApp
mv generateAssets.go.disable generateAssets.go

The build process includes a few more steps now.

  • go run generateAssets.go — required to rebuild the embed contents
  • rename the generateAssets.go to generateAssets.disable — if not, we would have a compilation error, since within the same “main” package, we now have 2 source files containing the main() method which is NOT allowed; hence we rename the file to “disabled” extension and skip it from compilation
  • go build -o taskApp — build the executable and name it as “taskApp”
  • rename the generateAssets.go.disable to generateAssets.go — after the build, revert the naming so that we can update the embed contents again in the future
decorated button

Great! If you see the above decorated button, we should be on the right track. Next we would need to bootstrap the Vue app on the main panel of the page.

PS. When we talk about panel, we are usually referring to an html “div” section.

Before adding the “app” component, we need to design where to put the component files. A possible design on the hierarchy as below:

|_ main.go
|_ www
|_ index.html
|_ asset
|_ favicon.png
|_ css
|_ app.css
|_ component
|_ app.js

within the “www” folder, we created a “component” folder holding all UI code. Since we would embed all resources under the “www” folder, our UI components would be embed into the executable as well.

The application — app.js

new Vue({
el: '#app',
data: function () {
return {
msg: 'vue app created',

The above is a simple Vue app’s structure, every Vue app needs to have a “home” which is declared in the “el” parameter — we can see that the home should be any HTML component matching the css selector “#app”; meaning the target component has the value “app” for the “id” attribute.

Next we have a “data” section — data refers to the local states of this component. In our app component, a “msg” state is created to validate if our component has been loaded correctly.

PS. Since states are LOCAL; they could only be shared to child component(s) as read-only values. We would talk about how to modify parent states in a later stage.

Our index.html would need some change as well:

<body onload="onStart()">
<!-- app entry point -->
<div id="app">
<button class="btn btn-primary">bootstrap buttons</button>

<!-- load back all vue related components; app.js MUST be the last one -->
<script src="./component/app.js"></script>


Note that we added a new “div” with id=app ← this is where our app component could mount. Within the component, we have our good old button, plus a line {{msg}}. In order to display a local state directly, use {{state_name}} syntax.

Lastly, remember to import our app.js file.

PS. IMPORTANT! If we are using the cdn import approach; all our components (*.js) MUST be imported at the very end. The reason is when the components start to bootstrap; the HTML content (i.e. div with id=app) is not yet available! Hence would fail to mount.

now re-build and run the app again would yield:

app.js running

The Splash-Screen component

Our daily task app has a splash screen displaying the loading progress before showing the webapp’s layout. Splash screen is a useful component for our webapp to preload resources including images, javascript libraries, css files etc.

To component-ize, we would create a new file — splash.js:

This time we use Vue.component() to create the splash-screen component; similarly within the method, we would provide the details for the component to work:

  • data — the local states of this component
  • mounted — a callback function and invoked when the component has been mounted to the webapp. Should only be called once in a lifetime unless the component has been fully destroyed from cache.
  • methods — either the presentation or business logic (e.g. event handlers) of the component
  • template — the component’s looks / appearance; which is a pile of HTML contents
<div class="splash-container" v-bind:class="getContainerClass()">
<div class="splash-inner-container">
<div class="splash-caption"
style="margin-top: 180px; margin-bottom: 20px;">
<img src="../asset/favicon.png" width="50px; margin-right: 12px;">

<div class="splash-progress-container">
<div id='splash-progress-bar' class="splash-progress-bar"></div>

The above template covers a lot of important concepts. Let’s take a closer look line by line.


The first line declares the primary HTML tag of this component which is a “div”, everything looks normal until v-bind:class=”getContainerClass()”. v-bind:class — means that we are going to add dynamic values to the “class” attribute of this “div” tag. The dynamic logic depends on function getContainerClass():

getContainerClass: function () {
let _c = {};
if (this.show) {
_c['core-display-block'] = true;
_c['core-display-none'] = false;
} else {
_c['core-display-block'] = false;
_c['core-display-none'] = true;
return _c;

if local state “show” is true → would return a css class “core-display-block” AND remove a css class “core-display-none” (if available earlier); vice versa for “show” is false. The important thing is this method MUST return an Object or the object in stringified format (i.e. convert the object to a string format). By returning different css classes, the corresponding UI’s appearance would change accordingly and hence possible to add visual effects or even creating a swap page effect (e.g. the main page contains 3 tabs, when a particular tab is clicked, the page’s content would change — all these could be done through css manipulations as well)


Near the end of the component, we found that there is a div with class=“splash-progress-bar”. This progress-bar is exactly where we create the animation, the animation code is located in the “mounted” callback. Remember mounted means the component / app has been mounted to the corresponding location within the HTML, so we can treat it as a MUST called life cycle method and it is triggered just when component UI is ready to be rendered.

mounted: function() {
let instance = this;
let ePBar = document.querySelector('#splash-progress-bar');
let w = 1;
let hInterval = setInterval(function () {
if (w >= 100) {
instance.show = false;
} else {
ePBar.style.width = w + '%';
}, 50);
  • we first created a variable named “instance” pointing to “this” instance; in general “this” should represent the Vue component itself. This step is essential when we need to use methods like setInterval or setTimeout in which the “this” variable is polluted to be the context of those methods — means that we could not access the Vue component’s methods anymore!
  • next, we get back our “div” element through css selector “#splash-progress-bar”; this div instance is the secret source to the animation
  • by default, the width of the “progress-bar” is only 1%; and what we want to do is throughout 5 secs, the progress bar would grow bits by bits till it reaches 100% width. This growth / animation is very simple, we would need to setup a regular interval and at each interval, a corresponding function would be called to update the progress bar’s width. In order to create such interval callbacks, use the setInterval()
  • “setInterval()” requires a function to operate at each interval plus a number indicating how long an interval expires. What we did is straightforward, if the width of the progress bar is greater than or equals to 100, we would stop the looping by calling clearInterval() also we would set the local state “show” to false. Or else, just update the progress bar’s width by “ePBar.style.width = w + ‘%’;” which is a css manipulation.
  • Modifying the local state “show” to false is essential, if you still remember we have a “getContainerClass()” method earlier. Once “show” is set to false, the “progress-bar” screen would NOT be shown anymore~ And that’s exactly what we want, right?

re-build the app and run it would yield:

Yep, that’s it~ Very simple isn’t it! All the magic is done through simple css manipulations. One more point to stress here is even though within our progress bar loading intervals, we didn’t really load any resources; however if we do need to pre-load some heavy loading images or text or establish server-side connections — this splash screen buffer is a good place to do so.

Take an example: our app might need to load main.png, establish an Elasticsearch connection plus retrieve personal profile from Elasticsearch index; hence our splash screen progress might be the following:

  • at 20% — when main.png is loaded
  • at 60% — when Elasticsearch connection is established
  • at 90% — when personal profile is retrieved (but not yet rendered)
  • at 100% — when the main UI / page has been rendered successfully; so time to hide our progress bar splash screen

That means, we still use the setInterval() method; however within each interval, we would instead check the availability of the above resources and determine when and how much to set on the progress bar’s width.

Moving on…

We have gone through a bunch of things again:

  • history of webapps and why SPA
  • installation of Vue.js framework / library on our index.html
  • create the first app — app.js
  • create the first UI component; our splash screen!
  • uncovering the power of css to create animation of a progress bar

In the next story of the tutorial, we would cover a Form-Input component to collect information from the user and make use of the input data to create our Note component. Happy coding and stay tuned





a java / golang / flutter developer, a big data scientist, a father :)

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How to develop Wireframes and Web Applications with Polymer.js

How To Remove Spaces Using JQuery

A Minimalist React App With 2 Routes — From A React Beginner (Part 1)

Bundling ESDOC plugins together

Better Text Ellipsis with Javascript

A tale of two allocations

Let’s Write a JavaScript Library in ES6 using Webpack and Babel

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
devops terminal

devops terminal

a java / golang / flutter developer, a big data scientist, a father :)

More from Medium

How to use Nodemon in Loopback 4 NodeJs Project

How To Display TwicPics Images When Working Offline With Nuxt.js

Stores with Dependency Injection in Vue 2 with Inversify

How to Create Your First Web Automation with Playwright in JavaScript