Build a Single-Page App with Go and Vue

This article was originally published on the Okta developer blog. Thank you for supporting the partners who make SitePoint possible.

Single-Page Applications (SPAs) improve user experience by offering rich UI interactions, fast feedback, and the relief of knowing you don’t need to download and install a traditional application. Browsers are now operating systems and websites are apps. While a SPA isn’t always the answer, for apps that rely on snappy user interaction they are increasingly common.

To the end user, a well-designed SPA feels like rainbows and unicorns. From the developer perspective, reality can be much the opposite. Tough problems long-since solved on the backend like authentication, routing, state management, data binding, and more become time-consuming frontend challenges. Luckily for us, JavaScript frameworks like Vue, React, and Angular exist to help us craft powerful applications and focus more of our time on critical functionality and not reinventing the wheel.

About Vue.js

--ADVERTISEMENT--

Who better to describe Vue than its creator, Evan You?

Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is designed from the ground up to be incrementally adoptable, and can easily scale between a library and a framework depending on different use cases. It consists of an approachable core library that focuses on the view layer only, and an ecosystem of supporting libraries that helps you tackle complexity in large Single-Page Applications.

Here are some of Vue’s benefits:

A gentle learning curve and low barrier to entry

Provides the ability to bootstrap your app withvue-cli,saving you the hassle of setting up webpack and complex build pipelines

Explosive community growth! Vue now has more stars on GitHub than React and Angular

It’s flexible enough to adopt at a reasonable pace, component by component

Create Your Vue + Go App

In this tutorial, you will create a single-page application that shows love to open source projects on GitHub. For the frontend you’ll use Vue and popular tooling like vuex, vue-cli, vuetify, and vue-router. On the backend, you’ll use Go to write a REST API and persist your data in MongoDB.

Authentication and user management can be a major pain, so you’ll use JSON Web Token (JWT) based authentication when making requests from the SPA and Okta’s Go JWT Verifier as a middleware on your backend to validate the user’s token on every request.

Once complete, users will be able to authenticate via OpenID Connect (OIDC), search for projects on GitHub, favorite those projects and even add notes where needed!

Create the Vue and Go Directory Structure

For the sake of simplicity, let’s write the REST API and the SPA in the same project, starting with the project directory in the Go workspace.

Go projects live inside the directory the environment variable $GOPATH points to. In order to find the current $GOPATH value, run: go env GOPATH. To learn more about GOPATH, including how to set it yourself, refer to the official Go documentation on the topic.

If you’re totally new to Go, check out this article in order to understand how projects are organized inside the GOPATH directory.

With the GOPATH defined, you now can create a directory for your project:

mkdir -p $GOPATH/src/github.com/{YOUR_GITHUB_USERNAME}/kudo-oos

To get your SPA off the ground quickly, leverage the scaffolding functionality from vue-cli. The CLI will prompt you with a series of options – pick the technology appropriate for this project: vue.js, vuex, and, webpack.

Install vue-cli by running:

yarn global add @vue/cli

Then, create a new Vue project:

mkdir -p pkg/http/web
cd pkg/http/web
vue create app

You will be prompted with a series of questions about the project’s build details. For this app pick all the default choices.

Congratulations, you have created your Vue.js SPA! Try it out by running:

Add Vuetify

Vuetify is a collection of Vue.js components that abstracts Material Design’s concepts. Vuetify provides out-of-the box features including a grid system, typography, basic layout, and also components like cards, dialogs, chips, tabs, icons and so on. Vuetify will pave your way to a rich UI!

When installing vuetify, you will be prompted with a series of questions. For the sake of simplicity just go with the default choices again.

vue add vuetify

Spin up your SPA again to see vuetify in action.

yarn serve

Add Authentication to Your Vue App with Okta

Writing secure user auth and building login pages are easy to get wrong and can be the downfall of a new project. Okta makes it simple to implement all the user management functionality quickly and securely. Get started by signing up for a free developer account and creating an OIDC application in Okta.

Once logged in, create a new application by clicking “Add Application”.

Select the “Single-Page App” platform option.

The default application settings should be the same as those pictured.

Next, install the Okta Vue SDK by running the following command:

yarn add @okta/okta-vue

Create Your Vue App Routes

For this app, you need only 4 routes, all of which require authentication except for the login route.

The root route / is our landing page where the login component will be rendered. Once the user has authenticated, we redirect them to the /me route where the bulk of the functionality takes place: The user should be able to query for OSS projects via GitHub’s REST API, favorite projects returned from the query, see more details about the project, and leave a note describing why the project is important to them.

Take note that both the /me and repo/:id have a meta: { requiresAuth: true } property specifying that the user must be authenticated to access that area of the app. The Okta plugin will use it to redirect the user the the Okta’s login page if not authenticated.

First, create pkg/http/web/app/src/routes.js and define the following routes:

Make sure to add your domain and client_id where indicated – these values can be found on the application overview page in the Okta Developer Console. Calling Vue.use(Auth, ...) will inject an authClient object into your Vue instance which can be accessed by calling this.$auth anywhere inside your Vue instance. This is what you’ll use to make sure a user is logged in and/or to force the user to identify themself!

Create Vue Components

The vue-router library contains a number of components to help developers create dynamic and rich UIs. One of them, router-view, renders the component for the matched route. In our case, when the user accesses the root route/,vue-routerwill render theLogincomponent as configured inrouters.js`.

Open ./kudo-oos/pkg/http/web/app/src/components/App.vue and copy in the following code.

For every route other than the matched route component, Vue will render the Footer component. Create ./kudo-oos/pkg/http/web/app/src/components/Footer.vue and copy in the following code to create that footer component.

SearchBar is the first component rendered in Home. When the user enters a query into the text input in the Sidebar, the component triggers a call to the Github API. SearchBar simply emits an event to its parent, Home, which contains the githubQuery.

./kudo-oos/pkg/http/web/app/src/components/SearchBar.vue should look like this:

Thanks to @keyup.enter="onSearchSubmition", whenever the user hits enter onSearchSubmition emits search-submitted with the query value. How do we capture this event you may ask? Simple! On the Home component, when you mounted the Sidebar component you also added a “listener” v-on:search-submitted="githubQuery" that calls githubQuery on every search-submitted event.

The Sidebar is also responsible for logging the user out. Okta Vue SDK offers a handy method to clean up the session using the method this.$auth.logout(). Whenever the user logs out, they can be redirected to the login page.

The second component rendered in Home is the GithupRepo. This component is used inside two tabs: the first tab Kudos represents the user’s favorites OSS projects and the Search tab renders the OSS projects returned from GitHub.

Your SPA uses vuex to manage state in one centralized store accessible by all components. Vuex also ensures that access to the store is performed in a predictable fashion respecting a few rules. To read the state, you need to define getters, synchronous changes to the state must be done via mutations, and asynchronous changes are done via actions.

To install vuex, run:

yarn add vuex

You now need to create ./kudo-oos/pkg/http/web/app/src/store.js with actions, mutations and getters. Your initial data is { kudos: {}, repos: [] }. kudos holds all the user’s favorites OSS projects asa JavaScript Object where the key is the project id and the value is the project itself. repos is an array that holds the search results.

There are two cases in which you may need to mutate state. First, when the user logs in you need to fetch the user’s favorites OSS projects from the Go server and set the repos in the store by calling resetRepos. Second, when the user favorites or unfavorites an OSS project, you need update the kudos in the store by calling resetKudos to reflect that change on the server.

resetKudos is synchronous method that is called by actions inside asynchronous functions after each call to the Go server.

The Home component uses the gettersallKudos and repos to render the list of Kudos and SearchResults. In order to know whether a repo has been favorited or not, your app needs to call the isKudo getter.

Inside actions you are performing ajax calls to the Go server. Every request made to the server must be authenticated or the server will respond with a client error. When the user logs in, an access token is created and can be accessed by calling: await Vue.prototype.$auth.getAccessToken(). This asynchronous function returns an access token required to send authenticated requests to the server.

The Go server exposes a REST API for the kudo resource. You will implement methods to make ajax calls in order to create with createKudo, update with updateKudo, delete with deleteKudo, and list all kudos withgetKudos. Notice that these methods call the perform method by passing the endpoint and the HTTP verb. perform, in turn, populates the request Authorization header with the access token so the Go server can validate the request.

Each GithubRepo has a router-link to /repo/:id that renders the GithubRepoDetails component. GithubRepoDetails shows details about the OSS project, like how many times the project has been of starred and the amount of open issues. The user can also leave a note describing why the project is special by clicking the Kudo button. The message is sent to Go server button by calling updateKudo.

Note that we are calling router.beforeEach(Vue.prototype.$auth.authRedirectGuard()) to look for routes tagged with meta: {requiresAuth: true} and redirect the user to the authentication flow if they are not logged in.

Create a REST API with Go

Now that users can securely authenticate on the frontend, you need to create a HTTP server written in Go to handle the requests, validate whether the user is authenticated, and perform CRUD operations.

I like using the dep tool to manage dependencies, so be sure to install it from here before continuing.

You now need a structure to represent a GitHub repository. Start by creating ./kudo-oos/pkg/core/kudo.go and define the following struct to represent a “kudo” (someone giving kudos to a specific repo).

Define Go HTTP Handlers

Your REST API exposes the kudo resource to support clients like your SPA. A normal SPA will expose endpoints so clients can create, update, delete, and list resources. For instance, when the user logs in, a request is made to fetch all the kudos for the authenticated user via GET /kudos.

# Fetches all open source projects favorited by the user
GET /kudos
# Fetches a favorited open source project by id
GET /kudos/:id
# Creates (or favorites) a open source project for the logged in user
POST /kudos
# Updates a favorited open source project
PUT /kudos/:id
# Deletes (or unfavorites) a favorited open source project
DELETE /kudos/:id

To support this, you need to add new file named ./kudo-oos/pkg/http/handlers.go and define your HTTP handlers using the fabulous httprouter library.

Run the Go +Vue SPA

There are many ways to run backend and frontend apps. The simplest way (for development purposes) is to just use good old fashioned Make.

A Makefile contains build instructions for your website. It’s like an old-school version of gulp, grunt, and the more hip Node tools. To get started, create a file named Makefile in the root of your project folder and copy in the following code.

Your app is now ready to test! Run the following commands to get going.

make setup
make run_server
make run_client

Your Go webserver should be listening on 0.0.0.0:4444 and your SPA should be serving files from http://localhost:8080. Visit http://localhost:8080 to play around with your new app!

Learn More About Go and Vue

Vue.js is a powerful and straightforward framework with phenomenal adoption and community growth. In this tutorial, you learned to build a fully-functional, secure SPA with Vue and Go.
To learn more about Vue.js, head over to https://vuejs.org or check out these other great resources from the @oktadev team: