DEV Community

Cover image for Custom Vue 3 boilerplate - Vite, Pinia, Vue Router & Tailwind CSS
richardev
richardev

Posted on • Updated on • Originally published at Medium

Custom Vue 3 boilerplate - Vite, Pinia, Vue Router & Tailwind CSS

Update: I've recreated TypeScript ready version of this boilerplate here.

A while back I realized I'm trashing my beautiful workspace with quite a few repetitive Vue web apps. Shortly before backing them up to never be seen again, it clicked - why not repurpose those reusable parts and simply stack them in a boilerplate? 🤔

Everything is a copy of a copy of a copy

I doubt that many devs like staging same project and repeat same initial commands again and again, therefore in this article "slash" tutorial I will swiftly go over how does one stack and configure a boilerplate.


Boilerplate stack

The stack of this boilerplate is focused on web app front end, therefore I'll keep it simple and use following packages:

Prerequisite

Before we start, I'm assuming you're somewhat acquainted with command line and have Node.js installed. If not - download it here. To check if it's installed, simply run node -v command.

Quickstart - Vue, Router & Store

Let's begin by initializing our boilerplate project.

npm init vue@latest
Enter fullscreen mode Exit fullscreen mode

Now enter the project name. I'll be using vue3-boilerplate. On feature prompt choose to install Pinia and Vue Router.

✔ Project name: vue3-boilerplate
...
✔ Add Vue Router for Single Page Application development? Yes
✔ Add Pinia for state management? Yes
Enter fullscreen mode Exit fullscreen mode

It's time to move into our project folder, install packages and run our boilerplate in development environment.

cd vue3-boilerplate
npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

You should be seeing on your local development environment http://127.0.0.1:5173 this example page:

Vue.js Home Page

You can learn more about building or serving your app in this guide. Oh, and read more about Pinia here. It is very similar to Vuex.

Add Tailwind CSS

👏 Great, we got our base, now we need the looks. Following this guide we are installing Tailwind CSS, its dependencies and then initializing configuration file.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

In your project root you'll now find tailwind.config.js file - let's open it and add our template paths:

module.exports = {
   content: [
      "./index.html",
      "./src/**/*.{vue,js,ts,jsx,tsx}",
   ],
   ...
}
Enter fullscreen mode Exit fullscreen mode

Next we will need to load @tailwind directives, so let's create tailwind.css in our /src/assets folder with following directives:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Now let's load this CSS file by importing it in the very top of /src/assets/main.css file:

@import "./tailwind.css";
...
Enter fullscreen mode Exit fullscreen mode

Since we already import /src/assets/main.css file in /src/main.js, we are good to use Tailwind's utility classes in our project.
Let's test it out by adding some classes inside /src/views/AboutView.vue in <h1> tag:

<template>
   <div class="about">
      <h1 class="text-xl font-medium text-white">This is an about page</h1>
   </div>
</template>
Enter fullscreen mode Exit fullscreen mode

We can also define our CSS properties separately below. To do so, we will need to install SASS package and PostCSS plugin - sass & postcss-import:

npm i -D sass postcss-import
Enter fullscreen mode Exit fullscreen mode

Now let's use @apply with our utility classes:

<template>
   ...
   <h1>This is an about page</h1>
   ...
</template>
<style lang="scss">
   .about {
      @apply lg:min-h-screen lg:flex lg:items-center;

      h1 {
         @apply text-xl font-medium text-white;
      }
   }
</style>
Enter fullscreen mode Exit fullscreen mode

🎉 Awesome! We have our core and we have our looks. What else could we add? 🤔

Add SVG loader (optional)

I like my SVG like I like my app - Component-Driven.🥁 It just so happens that our newly stacked boilerplate can easily import SVG imagery, but there is a catch - you'll have to use it as component, meaning you'll manually have to add SVG code within template tags and import it like that.

Luckily there is this vite-svg-loader package that basically allows you to simply import your .svg files within Vue template as components. Let's proceed by adding it to our boilerplate:

npm install vite-svg-loader --save-dev
Enter fullscreen mode Exit fullscreen mode

Now add this plugin in our vite.config.js configuration file:

...
import svgLoader from 'vite-svg-loader'
export default defineConfig({
   plugins: [vue(), svgLoader()],
   ...
})
Enter fullscreen mode Exit fullscreen mode

Lastly, to test it out I'm going to change that Vue.js logo code to Vite.js in /src/assets/logo.svg to this one and save it:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2454.32 2457.41"><defs><linearGradient id="a" x1="285.11" y1="1790.44" x2="285.7" y2="1789.74" gradientTransform="matrix(2454.32, 0, 0, -2187.24, -699180.9, 3916163.49)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#41d1ff"/><stop offset="1" stop-color="#bd34fe"/></linearGradient><linearGradient id="b" x1="285.22" y1="1790.33" x2="285.29" y2="1789.46" gradientTransform="matrix(1125.42, 0, 0, -2051.66, -319596.68, 3673197.31)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffea83"/><stop offset="0.08" stop-color="#ffdd35"/><stop offset="1" stop-color="#ffa800"/></linearGradient></defs><path d="M2464.14,381.6,1311.22,2443.21c-23.8,42.57-85,42.82-109.12.46L26.33,381.79C0,335.63,39.47,279.72,91.78,289.08L1245.93,495.37a62.88,62.88,0,0,0,22.27,0l1130-206C2450.35,279.87,2490,335.35,2464.14,381.6Z" transform="translate(-17.94 -17.87)" style="fill:url(#a)"/><path d="M1795.71,18.48,942.53,185.66a31.33,31.33,0,0,0-25.25,28.9L864.8,1101a31.33,31.33,0,0,0,29.41,33.14,31.77,31.77,0,0,0,8.91-.75l237.54-54.82a31.32,31.32,0,0,1,37.73,36.79l-70.57,345.59a31.33,31.33,0,0,0,39.8,36.24l146.72-44.57a31.34,31.34,0,0,1,39.79,36.32L1222,2031.73c-7,33.95,38.14,52.47,57,23.36l12.59-19.44L1986.77,648.19c11.65-23.23-8.44-49.72-33.94-44.79l-244.52,47.18a31.33,31.33,0,0,1-36-39.44L1831.86,57.91a31.34,31.34,0,0,0-36.14-39.43Z" transform="translate(-17.94 -17.87)" style="fill:url(#b)"/></svg>
Enter fullscreen mode Exit fullscreen mode

Then in /src/App.vue file I'll import it as SVG component and replace it with <img class="logo" />.

<script setup>
   ...
   import LogoSVG from './assets/logo.svg?component'
</script>
<template>
   ...
   <LogoSVG alt="Vite logo" class="logo" />
   ...
</template>
Enter fullscreen mode Exit fullscreen mode

🎉Congratulations!

You are a proud owner of your very own boilerplate. 👏

Yes! Napoleon Dynamite


What's next?

You would now want to create an easily pull-able starter kit - for example, in Github - so your boilerplate is always one command away. I actually did just that - you can pull my version of boilerplate here or simply pull it:

npm i @richardev/vue3-boilerplate
Enter fullscreen mode Exit fullscreen mode

Finally, I want to share this list of some useful Vue.js related packages to add to your boilerplate:
NuxtJS - Vue.js Framework
Vue Meta - for Web App SEO
VeeValidate - form validation
Vue Toastification - alerts a.k. toasts

If you have ideas on what to add or remove in this boilerplate, tips on configuring it or you simply have an issue setting it up - I'll appreciate if you reach out in the comments below. 👋

Update: I've recreated TypeScript ready version of this boilerplate here.

Top comments (3)

Collapse
 
richardevcom profile image
richardev • Edited

Update: I've recreated TypeScript ready version of this boilerplate here.

Collapse
 
clabnet profile image
Claudio Barca

Sorry, I think Is there an error for missing sass preprocessor.
After then install it, the about page is blank. see issue #1 on Github repo.

Collapse
 
richardevcom profile image
richardev

Updated. Thank you for your input. 🙏
I had it installed globally at the time and didn't notice, haha.