Javascript is required
·
7 min read

Building a Vue 3 Desktop App With Pinia, Electron and Quasar

Building a Vue 3 Desktop App With Pinia, Electron and Quasar Image

Recently, I planned to rewrite my "Scrum Daily Standup Picker" Electron application in Vue 3. I wrote the initial release in Angular, but I wanted to refactor the code base and rewrite it in Vue 3.

Why? Because I love Vue and want to have a public showcase that I can reference to potential customers.

Why Quasar?

Quasar is an MIT licensed open-source Vue.js based framework that targets SPA, SSR, PWA, mobile app, desktop app, and browser extension all using one codebase. It handles the build setup and provides a complete collection of Material Design compliant UI components.

Quasar's motto is:

Write code once and simultaneously deploy it as a website, a Mobile App and/or an Electron App.

Using Quasar drastically saves development time due to these reasons:

  • It's based on Vue.js.
  • It provides many UI components that follow Material Design guidelines.
  • It has a regular release cycle inclusive of new features.
  • It provides support for each build mode (SPA, SSR, PWA, Mobile app, Desktop app & Browser Extension).
  • It has its own CLI that provides a pleasant developer experience. For example, we can build our application as SPA, mobile, or desktop app within the same project folder.

Read more about why Quasar might be a good choice for your next project.

Install Quasar CLI

Info

The source code for the following demo is available at GitHub

bash
1# Node.js >=12.22.1 is required.
2
3$ yarn global add @quasar/cli
4# or
5$ npm install -g @quasar/cli

Let's start by creating a new project using the Quasar CLI:

bash
1 quasar create vue3-electron-demo
2
3  ___
4 / _ \ _   _  __ _ ___  __ _ _ __
5| | | | | | |/ _` / __|/ _` | '__|
6| |_| | |_| | (_| \__ \ (_| | |
7 \__\_\\__,_|\__,_|___/\__,_|_|
8
9
10
11? Project name (internal usage for dev) vue3-electron-demo
12? Project product name (must start with letter if building mobile apps) Quasar App
13? Project description A Quasar Framework app
14? Author Michael Hoffmann <michael.hoffmann@mokkapps.de>
15? Pick your CSS preprocessor: SCSS
16? Check the features needed for your project: ESLint (recommended), TypeScript
17? Pick a component style: Composition
18? Pick an ESLint preset: Prettier
19? Continue to install project dependencies after the project has been created? (recommended) NPM

We chose SCSS as our CSS preprocessor, ESLint & Typescript as additional features, Vue 3's Composition API and Prettier for code formatting.

Warning

Do not choose Vuex as we will add another state library in the next chapter. If you accidentally added Vuex, remove it manually from your package.json.

Read the official docs for additional information about the Quasar CLI.

Add Pinia as Vue store library

We'll use Pinia as Vue store library, which is now the recommended state library for Vue.

First, we need to install Pinia:

bash
1yarn add pinia
2# or with npm
3npm install pinia

To be able to register Pinia at our Vue application instance we need to create a Quasar Boot File:

A common use case for Quasar applications is to run code before the root Vue app instance is instantiated, like injecting and initializing your own dependencies (examples: Vue components, libraries…) or simply configuring some startup code of your app.

Our boot file is called pinia.ts and is located at src/boot:

1import { boot } from 'quasar/wrappers'
2import { createPinia } from 'pinia'
3
4export default boot(({ app }) => {
5  app.use(createPinia())
6})

We also need to add this new file to quasar.conf.js:

1module.exports = configure(function (ctx) {
2  return {
3    ...
4    // app boot file (/src/boot)
5    // --> boot files are part of "main.js"
6    // https://quasar.dev/quasar-cli/boot-files
7    boot: ['pinia'],
8    ...
9  }
10}

Now, we can create a new folder called pinia in src.

Warning

We cannot name this folder store as this name is reserved for the official Vuex integration.

A basic store could look like this:

1import { defineStore } from 'pinia'
2
3// useStore could be anything like useUser, useCart
4// the first argument is a unique id of the store across your application
5const useStore = defineStore('storeId', {
6  state: () => {
7    return {
8      counter: 0,
9      lastName: 'Michael',
10      firstName: 'Michael',
11    }
12  },
13  getters: {
14    fullName: (state) => `${state.firstName} ${state.lastName}`,
15  },
16  actions: {
17    increment() {
18      this.counter++
19    },
20  },
21})
22
23export default useStore

We can use this store in any Vue component:

1<template>Counter: {{ store.counter }}</template>
2
3<script setup lang="ts">
4import { useStore } from '@/stores/counter'
5
6const store = useStore()
7</script>

Now we can run the Vue application using the Quasar CLI:

bash
quasar dev

The Vue application is served at http://localhost:8080:

Quasar Dev Mode

Setup Electron

Info

Read this introduction if you are new to Electron.

To develop/build a Quasar Electron app, we need to add the Electron mode to our Quasar project:

bash
quasar mode add electron