Software Development Build a Single Page Application with Laravel 5.8, Vue.js and Tailwind Published September 5th, 2019

In this article I’m going to build a Single Page Application (SPA) with Laravel 5.8, Vue.js, Vue Router and a Tailwind CSS landing page template.

Build a Single Page Application with Laravel 5.8, Vue.js and Tailwind image
The code for this tutorial is open source on GitHub

In this article I’m going to build a Single Page Application (SPA) with Laravel 5.8, Vue.js, Vue Router and a Tailwind CSS landing page template.

Too long; didn’t read - source code here

Introduction to Single Page Applications (SPAs)

Conventional apps from MVC frameworks like Laravel, Ruby On Rails or Django use Models, Views and Controllers to take information from the database and render them to HTML pages. In modern parlance this is called Server Side Rendering (SSR). It’s good for SEO. Initially with the rise of Angular 1.x and now to React and Vue.js web application development has shifted towards being API focused. Instead of the server configuring how the HTML view is going to look, the server is an API that sends JSON and JSON only. With all major client side Javascript frameworks routing and view logic can be handled on the frontend independent of the server. Moving view and routing logic from the server to the client brings about new challenges.

The advantage of moving responsibility from the server to the client is that apps can be faster and more responsive. There is added complexity though. In this tutorial we’re going to go through instantiating a default Laravel 5.8 project and setting things up for API driven development.

Recommended Resources on API Driven Development with Laravel and Vue

There’s a new docs page for Laravel 5.8 explaining API Authentication. Jeffrey Way did a Laracasts course covering the material. This series from Server Side Up is another helpful resource when learning how to connect Laravel and Vue.js for Single Page Applications.

What we’re building

In this tutorial we’re going to make a single page application where users can apply to join, login once approved. In the process we’ll set up Tailwind CSS for styling, Vue Router for frontend routing and Laravel 5.8 authentication. We’re going to go through the process starting from scratch with a fresh Laravel 5.8 application. Let’s get cracking!

You can see a video of the application in action here and view the open source code on GitHub.

Step 1: Create a Laravel 5 application locally

The first thing we’re going to do is create a default Laravel app. If you have not created a Laravel app before it can be a bit tricky getting configuration set up. Installing MySQL properly with the right PHP versions and file paths can be particularly vexing. Vagrant and Laravel Homestead were created specifically to help developers get started faster without worrying about configuration. I recently published a post with my notes from setting up a new Mac for PHP development here focusing on Vagrant setup. Previously, I published a post about setting up MySQL on my local machine here: installing MySQL on Mac.
If you’re particularly adventurous you could try and set up a Laravel environment using Docker and Laradock. I would not recommend this if you’re a beginner or brand new to PHP/Laravel development. Docker and Kubernetes are powerful tools but require specialized knowledge outside of core Laravel and PHP. Docker is outside of the scope of this tutorial, but if you are interested in learning more I recommend Servers for Hackers as a starting (or even midway) point on your journey.

When creating new Laravel applications I generally refer to this script for the commands I need to run to create a new Laravel app. It may be slightly different depending on if your MySQL database is on your local machine or in the Vagrant virtual machine or on Docker, but it should help as a guide to getting started creating a new Laravel app and common commands you need to run. It includes creating the application, migrating the database and clearing the cache. Some of these commands you can use later in your deployment scripts.

I recommend installing this SEO tools Laravel package. It helps how your results show up in Google.

At this point I’ve got a Laravel 5.8 app running locally on my machine with a MySQL database.

Step 2: Init Tailwind CSS and UI Design

Install the Tailwind npm package:

$ npm i tailwindcss --save-dev
$ npx tailwind init

Npx is the Tailwind CLI command. Running init generates a tailwind.config.js file in your project’s root. Be sure to read more in the getting started section of the Tailwind docs.

Instead of writing our own Webpack config file Laravel provides the Laravel Mix wrapper. Update your webpack.mix.js file to look like:

const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss');
mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css')
     processCssUrls: false,
 	 postCss: [ tailwindcss('./tailwind.config.js') ],

There are some more details in the docs about what’s happening here and a few Github issues discussing what’s going on. If you paste this into your Laravel Mix file and are using Tailwind version 1 you should be good to go.

Import Tailwind in resources/sass/app.scss:

@tailwind base;
@tailwind components;
@tailwind utilities;

That’s it! You should be good to go running Tailwind CSS in your Laravel 5.8 application.

I found a landing page template from Tailwind Toolbox and now added that HTML to my resources/views/welcome.blade.php file. After tweaking the template a bit I had a landing page look and feel I was happy with.

I had some fun picking out colors. A word of advice: leave it to the professionals when picking color gradients. I wasn’t happy with the gradients I picked, then saw this article with dozens of color blends. From there I used a Chrome extension color picker and added colors as variables to my resources/sass/_variables.scss file.

In terms of other design resources, Hero Patterns is pretty cool for click background patterns. provides open source illustrative images you can use out of the box.

There is one class called gradient in charge of the CSS background gradient across the site. It looks like this:

.gradient {
    background: linear-gradient(90deg, $brand-1 0%, $brand-2 100%);

Where $brand-1 and $brand-2 are color variables I defined in the _variables.scss file.

With elementary design out of the way, the next step for this app is to make this Laravel app a Single Page Application.

Step 3: SPA Routing Configuration with Laravel and Vue

Once I have a new project created it’s time to tweak things a bit to make this a SPA. This Laracasts course honestly should be your go-to guide for building this type of thing. Jeffrey Way is an awesome teacher. That Laravel course inspired me to write out this post.

The idea behind a SPA is that users can navigate around without the page refreshing. Javascript handles calls to the server, creating a more fluid and slick experience for users.

Instead of Laravel routing we’ll use the official Vue.js router. After it’s installed we need to specify configuration options. The JS entry file resources/js/app.js and looks like this:

import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
let app = new Vue({
   el: '#app',
   router: new VueRouter(routes)

Now that we set up the frontend to handle routing, we need to specify on the Laravel side to always load the welcome Blade template. This is in routes/web.php:

Route::get('/{any?}', function () {
    return view('welcome');

This Laravel route at the bottom of the routes file will declare to always send back the welcome blade file. Once there Vue.js will take over.

I’d like to have the homepage blade template and new pages for logging in and candidate applications. Candidates can’t join the network automatically. I have to approve them first. We’ll cover that more in the next section.

For now I’ll add the routes configuration to have each route render a new Vue.js component. This will create a SPA with Laravel 5.8 and Vue.js!

import Welcome from './pages/Welcome.vue';
import Login from './pages/Login.vue';
import Apply from './pages/Apply.vue';
import Employers from './pages/Employers.vue';

export default {
  mode: 'history',
  routes: [
      path: '/',
      component: Welcome,
      name: 'welocome'
      path: '/login',
      component: Login,
      name: 'login'


  	path: '/apply',
  	component: Apply,
  	name: 'apply'

  	path: '/employers',
  	component: Employers,
  	name: 'employers'


The above example uses named routes. We can link to routes using the name. One advantage of this is we’re able to be explicit about page we’re going to. If we change the URL path later on by linking to the name of the route our links won’t break. The mode: history key value pair lets Vue Router know that we want to use HTML5 history mode. By default Vue router will use hashed URLs like With this setting enabled Vue Routers uses the HTML5 history API, making URLs look regular like The Laravel server configuration posted above will handle the catch all routes and the app will render the appropriate page using Vue.js.

Don’t forget to handle 404 pages. Here’s this helpful Laracasts episode about how to handle the scenario when someone types a page link for your site that doesn’t exist…

Step 4: Vue.js component pages

The final step is actually building these Welcome, Login, Apply and Employers pages. It’s a lot of HTML with Tailwind handling the CSS magic. I don’t want to paste a ton of HTML here, especially with the code open source on GitHub. That said here’s a video of what the site looks like when running locally:

The Vue.js components with the Tailwind CSS classes are all in the resources/js folder. I broke up the Vue components between two folders, “pages” and “components” to keep things organized more clearly between a page components and components that take up part of a page.

Reflections on building this

For me, building this app has been a proof of concept for using Vue Router and Tailwind instead of Blade templates and Bootstrap 4. I currently have built with Blade templates and Bootstrap 4. There are a fair amount of Vue components, especially with the Google Maps pages. Building this app from the ground up helped me think about what’s really necessary on the site and what I’m building. Tailwind CSS does require a lot of specialization and command of CSS and classes. I think it’s the way forward for making a legit looking site. I don’t know if I’ll totally strip Blade and Bootstrap from Employbl but it is a tempting proposition!

Moving forward: Token Based API Authentication

In future tutorials I’d like to expand this application to include functionality for logging users in. I’ve written quite a few tutorials on authentication with Laravel. The Laravel 5.8 documentation includes a new section specifically designated for API authentication here. As linked above the Laracasts course on authentication is another incredible resource.

Related articles