Home / Blog / The Definitive Guide To Building Cross Platform Apps With Vue (Quasar)
The Definitive Guide To Building Cross Platform Apps With Vue (Quasar)

The Definitive Guide To Building Cross Platform Apps With Vue (Quasar)

Luke Diebold
Luke Diebold
August 12th 2024

Quasar is a VueJs framework that can build apps for mobile, desktop and the web. It comes with a meticulously crafted, material design component library… and documentation with loads of examples!

Building apps with Quasar is like surfing a wave 🌊. It takes a bit of knowledge before you can stand up, but once you do... It. feels. A-MAZING!.

This guide touches on 11 aspects of Quasar that will set your Quasar journey on fire ️‍🔥. If you understand these 11 things:

  • you'll rarely run into "brick walls" (and if you're anything like me, you CAN’T STAND brick walls that feel impossible to climb)
  • clients will be baffled at what you can build in a day
  • you'll know when to solve a problem with Quasar, and when to look outside the framework

If you're new to Quasar, this article will help get you started so that the docs make more sense.
If you run a team that uses Quasar, this article will be a starting point for new devs.
If you're already a pro with Vue, this post is designed to be easy to skim, so you can cherry pick what you need to know.

That's enough preamble... Let's get to it!

1. Playgrounds (Trying Things Out)

There are three official places you can try a Quasar app in your browser:

There's also Quasar Play. an insanely cool experiment - built by Quasar core team member Popescu Dan - that uses vue-repl with Quasar.

2. Creating A Quasar App (Yes. Typescript is supported!)

Before we get started, let's install the Quasar cli globally:

npm install -g @quasar/cli

try running quasar in your terminal to see what it can do!

Now, there's a few ways to build a Quasar app. You'll almost certainly want to use Quasar's CLI:

yarn create quasar

follow the prompts, and be sure to enable linting!

I personally like to use ESLint with the standard preset (in other words, without prettier!):

✔ Check the features needed for your project: › Linting (vite-plugin-checker + ESLint)
✔ Pick an ESLint preset: › Standard

Straight up, we can run our app in the following modes...

no more configuration required!

spa (the default)

quasar dev

electron (windows, mac, linux)

quasar dev -m electron

ssr

quasar dev -m ssr

bex (browser extension)

quasar dev -m bex

Trouble installing the Quasar CLI? Prefix the above commands with your package manager (e.g. yarn quasar dev)

And that's it!

To build for android or ios, you'll need to do a little more setup (we walk through this in detail in the Quasar Fundamentals Course). Once setup, you can easily get started with the following commands:

Android

quasar dev -m capacitor -T android

iOS

quasar dev -m capacitor -T ios

Notice that we use capacitor to build our mobile app? This means if we have any "mobile app" related problems, or want to add "mobile app" plugins, we research "capacitor". For example instead of "how to add GPS to a Quasar app" we'd search "how to add GPS to a Capacitor app". This way, you'll have a lot more luck finding what you're looking for!

There you have it! It's kinda ridiculous how easy this stuff is right?

Quasar's done a monstrous amount of work to allow us to build apps for any platform, in seconds!

3. Stricter Linting (Don't Skip This!!!)

The first thing I do in a new Quasar project, is enable stricter linting.
This will change your life!!!

.eslintrc.js

module.exports = {
  // ...
  extends: [
    // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
    'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
  ],
  // ...
}

See how we commented out plugin:vue/vue3-strongly-recommended and commented in plugin:vue/vue3-recommended? You'll love this 💜.

The main benefit?…

When you save a file, your code will format in a way that's readable.
This is a HUGE productivity win!

Next, you'll want to ensure linting works properly in your editor. We go through this step by step in the Quasar Fundamentals Course.

4. API Explorer

Every Quasar component, plugin and directive comes with an API card.

If you understand Quasar's API cards, you understand 90% of Quasar.

It's the difference between a dev saying "I find Quasar's docs confusing" vs "Quasar has the best docs on the PLANET!".

Of course, the Quasar Fundamentals Course covers api cards in detail, though we'll touch on all the sections now! Below is an image of the QTable API card:

  • Props, Slots and Events (red squares) are the most important to know.
  • Methods and ComputedProps (orange squares) you'll want to learn, yet are lower priority.
  • Also note the "filter" (blue square). It's very handy!
API Explorer

Let's go over basic examples of how all these categories are used with the QTable component!

Prop Examples

Prop Examples

Props are the easiest to understand. If you know Vue, chances are you already know how to use props and can skip this section.

Here's how props used in Quasar:

Passing a string

<template>
  <q-table title="Friends" />
</template>

Passing a ref/expression

<script setup>
import { ref } from 'vue'

const fullscreen = ref(false)
</script>

<template>
  <q-table
    :rows="users"
    :fullscreen="fullscreen"
  />
</template>

Boolean (true)

<q-table
  :rows="users"
  hide-pagination
/>

Boolean (dynamic)

<script setup>
import { ref } from 'vue'

const fullscreen = ref(false)
</script>

<template>
  <q-table
    :rows="users"
    :fullscreen="fullscreen"
  >
</template>

Event Examples

Event Examples

Events are the second easiest to understand. If you know Vue, chances are you already know how to use events and can skip this section.

Here's how events are used in Quasar:

<script setup>
function onRowClicked(event, row) {
  console.log(`you clicked on "${row.name}"`)
}
</script>

<template>
  <q-table
    :rows="users"
    @row-click="onRowClicked"
  />
</template>

If an event starts with @update:, then the data on that event can be modeled.
For example: @update:fullscreen means we can do the following:

<script setup>
import { ref } from 'vue'

const fullscreen = ref(false)
</script>

<template>
  <q-table
    :rows="users"
    v-model:fullscreen="fullscreen"
  />
</template>

Slot examples

In the context of Quasar, think of "Slot" as "I'm taking total control".
Slots allow you to completely rewrite things like table cells, rows, the header, the footer and much more!

If you're new to slots, take as much time as you need to thoroughly understand the following examples:

Basic Slot

<q-table :rows="users">
  <template #top-right>
    Put literally <q-chip label="anything" /> you like here!
  </template>
</q-table>

Named Slots

Some slots are dynamically generated. In the following example, our table has a name column, and we "tap into" every name cell to take total control of what it looks like.

<q-table
    :rows="users"
    :columns="[{ name: 'name', field: 'name', label: 'Name' }]"
>
  <!-- In this example, "name" is dynamic -->
  <template #body-cell-name>
    <!-- We can now write custom code for our "name" data cell -->
    <q-td>
      You're now in <strong>total control</strong> of this cell!
    </q-td>
  </template>
</q-table>

Using Slot Scopes

The example above is incomplete for two reasons:

  1. It's missing the name value
  2. The q-td loses some of the functionality q-table provides, because it's missing props

That second reason is difficult to explain in the scope of this article, and is covered in more detail in the Quasar Fundamentals Course. Basically, we need to give the q-td more “knowledge” of the tables state.

Let’s fix those two issues to complete the example:

<q-table :rows="users">
  <template #body-cell-name="scope">
    <!-- passing the scope to q-td solves problem 2 -->
    <q-td :props="scope">
      <!-- using scope.value solves problem 1 -->
      <q-chip :label="scope.value" />
    </q-td>
  </template>
</q-table>

Using events on the scope

Sometimes, Quasar will give you access to events when using slots.

Read this next paragraph as many times as you need to understand!

"""
When using QTable, If we use quasar's #pagination slot, we're saying "I'm going to take complete control over how pagination works". The problem is that we would then need to rewrite a lot of code, such as nextPage(), prevPage(), firstPage(), lastPage() etc. Instead of rewriting this code, Quasar makes those functions available through the scope. For example scope.nextPage(), scope.prevPage(), scope.firstPage(), scope.lastPage() etc.
"""

Here's a minimal example:

<q-table :rows="users">
  <template #pagination="scope">
      <q-btn @click="scope.prevPage()" />
      <q-btn @click="scope.nextPage()" />
  </template>
</q-table>

It doesn't feel right to leave you with an incomplete example! so here's how you can take total control over the design of pagination, while leaning on Quasar's scope!

<q-table :rows-per-page-options="[2]" :rows="users">
  <template #pagination="scope">
    <q-btn
      color="pink"
      icon="first_page"
      @click="scope.firstPage()"
      :disable="scope.isFirstPage"
      flat
      round
    />

    <q-btn
      color="pink"
      icon="arrow_back"
      :disable="scope.isFirstPage"
      @click="scope.prevPage()"
      flat
      round
    />

    <q-pagination
      color="pink"
      v-model="scope.pagination.page"
      :max="scope.pagesNumber"
    />

    <q-btn
      @click="scope.nextPage()"
      color="pink"
      icon="arrow_forward"
      :disable="scope.isLastPage"
      flat
      round
    />

    <q-btn
      color="pink"
      icon="last_page"
      @click="scope.lastPage()"
      :disable="scope.isLastPage"
      flat
      round
    />
  </template>
</q-table>

Understand that example above and you'll never feel powerless using Quasar! 💪

5. Boot Files

If there's one thing new Quasar developers have trouble understanding it's this:

Quasar does NOT have a main.js file. Whenever you need to access main.js, you use a "boot file" instead.

  • If you need to add a Vue plugin (Vue.use() or app.use()), you need a boot file
  • If you need to hook into your app before any components start loading, you need a boot file
  • If you're following a Vue guide online where main.js is accessed, you need a boot file

To further add clarity, here's a basic overview of how a Quasar app starts:

  1. The vue app is created (createApp())
  2. The “Quasar Vue plugin” is installed
  3. The store is created and installed
  4. The router is created and installed
  5. One by one, every boot file is run

Said another way, Quasar does all the prep it needs - which will be slightly different depending on the target platform - then it runs the boot files. That's why we don't have a main file when working with Quasar. It's automatically created for us.

So how do we create, and use a boot file?…

Creating and using a boot file

We can easily generate a boot file using quasar (or yarn quasar if you haven't installed Quasar globally):

quasar new boot some-vue-plugin

Then to use the boot file, we add it to our quasar.config.js file:

export default configure((ctx) => {
  return {
    boot: [
      'some-plugin' // <<<
    ],
  }
})

And that's it! Anything you place inside the boot function is kinda like adding to your main.js file!

import SomeVuePlugin from 'some-plugin'

export default boot(({ app, router, store, ssrContext }) => {
  app.use(SomeVuePlugin)
})

In the above example, I've destructured the 4 main things you'll want to know about:

  • app: your "Vue App" (the result of const app = createApp(rootElement))
  • router: Vue router instance
  • store: Pinia store (Vuex is supported, but deprecated)
  • ssrContext: only available in ssr mode

Now let's take a look at some examples...

1. Installing a Vue plugin

This is actually kind of rare these days. Most "Vue Plugins" don't need to be installed but there are a few!

import { boot } from 'quasar/wrappers'
import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'

export default boot(({ app, store }) => {
  const i18n = createI18n({
    locale: 'en-US',
    globalInjection: true,
    messages
  })

  app.use(i18n)
})

2. Installing a Pinia plugin (Pinia ORM)

Remember, we have access to store (which is the Pinia store) in our boot file. We can use that store to install Pinia plugins:

import { createORM } from 'pinia-orm'

export default boot(({ store }) => {
  store.use(createORM())
})

3. Creating a global variable (wretch)

We can easily create global variables within a boot file. This example uses wretch (a thin wrapper around the fetch api)

boot/wretch.js

import { boot } from 'quasar/wrappers'
import wretch from 'wretch'

const api = wretch('https://jsonplaceholder.typicode.com/')

export default boot(({ app }) => {
  app.config.globalProperties.$wretch = wretch
  app.config.globalProperties.$api = api
})

export { api }

We can now use $api directly in our components, or using this.$api in the options API.

In a component:

<q-btn
    label="Get Posts"
    @click="$api.get('posts')"
/>

Options API:

<script setup>
defineOptions({
    methods: {
        async fetchPosts() {
            const data = await this.$api.get('posts').json()
        }
    }
})
</script>

I personally prefer to use the composition API, and also avoid globals entirely:

<script setup>
import { api } from 'src/boot/wretch'

async fetchPosts() {
    const data = await api.get('posts').json()
}
</script>

4. A "side effect import"

Sometimes we just need an import statement that we'd usually put in a main file. For example, when installing UnoCSS we need to import virtual:uno.css. This is crazy simple to do inside a boot file!
quasar new boot unocss

import 'virtual:uno.css'

NOTE! This is just an example of a "side effect import". There are more steps required to install UnoCSS which we cover in the Quasar Fundamentals Course.

6. Utility Classes

Quasar's utility classes are very well documented! They exist in two places:

  1. Quasar Docs -> Style and Identity (left drawer)
  2. Quasar Docs -> Layout and Grid -> Flex Grid (also left drawer)

The Quasar Fundamentals Course shows many examples! Here, let's cover a couple of the main ones, then you can dig deeper once you get a feel for how Quasar's utility classes work!

Colors

Your brand colors can be changed in src/css/quasar.variables.scss. The main one's you'll want to change are primary, secondary and accent :

$primary   : #88b865;
$secondary : #0777BF;
// etc

Primary Colors

Quasar comes with a palette of colors built in. colors from 1-10 are variations on the primary color, 1 being the lightest, 10 the darkest.
For example:

  • red-1 lightest red:

    Red-1

  • red-10 darkest red:

    Red-10

  • indigo-8 a somewhat dark indigo:

    Indigo-8

If no number is provided, then -6 is used. For example, red is the same as red-6

Accent Colors

colors from 11-14 are "accent colors".
For example:

  • teal-11:

    Teal-11

  • purple-14:

    Deep-Purple-14

Using Colors

There are three main ways to use Quasar colors

  • components color="blue-10", and in some cases text-color="grey-10"
  • utility class (background) bg-purple-1
  • utility class (text) text-blue-grey-10

Here are some examples, showing colors in action!

<template>
  <q-btn color="teal" />

  <q-chip
    label="email"
    color="teal-2"
    text-color="teal-10"
  />

  <q-card class="bg-indigo">
    <q-toolbar class="bg-primary text-white">
      <q-toolbar-title>
        Spy X Family
      </q-toolbar-title>
    </q-toolbar>

    <q-card-section class="text-grey-1">
      Elegance!
    </q-card-section>
  </q-card>

  <q-btn
    color="accent"
    icon="person"
    fab
  />
</template>

We also have JavaScript utilities for working with colors!

import { colors } from 'quasar'
const { getPaletteColor } = colors

console.log(getPaletteColor('primary')) // '#1976d2'
console.log(getPaletteColor('red-2')) // '#ffcdd2'

Spacing (Margins and Padding)

Quasar had utility classes for margins and paddings way before it was cool 😎

Here are some examples, followed by an explanation:

<div class="q-mt-xl" />
<div class="q-mr-md" />

<div class="q-pa-lg" />
<div class="q-pl-xs" />

Here's how we create a spacing class with Quasar:

  1. Prefix: q-
  2. Kind: p for padding, m for margin
  3. Side: t for top, r for right, a for all etc
  4. Another -
  5. Size: xs, sm, md, lg, xl or none

In other words: q-[kind][side]-[size]

confused? I don’t blame you! This will make a lot more sense as you look at examples so…

Here's a couple more! We'll also introduce x (left AND right) and y (top AND bottom) for the sides.
See if you can visualize where the margins/paddings are in your head while reading these examples:

<div class="q-mt-md q-px-lg" />
<div class="q-ma-sm q-py-lg" />

Typography

Quasar has typography utility classes that will cover your basic needs!

The basics

There are utility classes for body text, subtitles and captions:

<div class="text-body1">Great for the body of a blog</div>
<div class="text-subtitle1">A little bit extra...</div>
<div class="text-caption">often used under a photo</div>

Headings

Usually, a h tag will give you the styling you need. You'll likely want to pair it with your own margins:

<h1 class="q-mt-none q-mb-md">Quasar, All The Platforms!</h1>

Sometimes, we want h tag sizes, without the h tag. For that we have utility classes:

<div class="text-h5">Looks good at the top of a card</div>

Font weights

We have weights from thin through to bolder:

<div class="text-weight-thin">Thin</div>
<div class="text-weight-light">Light</div>
<div class="text-weight-regular">Regular</div>
<div class="text-weight-medium">Medium</div>
<div class="text-weight-bold">Bold</div>
<div class="text-weight-bolder">Bolder</div>

Alignment

And here are the alignment classes you'll commonly use:

<div class="text-center">center</div>
<div class="text-right">right</div>
<div class="text-left">left</div>

Visibility

Quasar has a lot of helpful visibility classes!

You'll likely be most interested in the platform related utility classes.
Here are some examples:

<!-- "only" classes -->
<div class="desktop-only">You're on a desktop computer!</div>
<div class="platform-android-only">I see you're on android. Nice!</div>

<!-- "hide" classes -->
<div class="touch-hide">This is NOT a touch device</div>
<div class="electron-hide">Looks like this site was built with electron 👀</div>

We also have the basics like hidden, invisible and transparent.

A Couple More!

Here's a couple other utility classes I use all the time:

  • relative-position
  • fixed, fixed-top-right, fixed-bottom-left etc
  • absolute, absolute-top-right, absolute-bottom-left etc
  • scroll (CSS tweaks to make scroll work well on ALL platforms)
  • cursor-pointer (for things that are "clickable" in the UI)

The following pattern is a great way to make a button float outside a card using absolute and relative-position!

<!-- "relative-position" means "absolute" will be relative to this card -->
<q-card class="relative-position q-ma-xl">
  <img src="<https://cdn.quasar.dev/img/mountains.jpg>" />

  <q-card-section>
    <div class="text-h6">Beautiful Mountains</div>
    <div class="text-subtitle1">by Quasar Dev</div>
  </q-card-section>

  <!-- "absolute-top-right" tells this button to go to the top right of the card -->
  <!-- Yes, we sneak in a style tag and that's okay! -->
  <q-btn
    class="absolute-top-right"
    style="top: -12px; right: -12px"
    fab
    icon="fullscreen"
    color="accent"
  />
</q-card>

7. Utility Functions

At the bottom of Quasar's docs menu is a little know, yet wildly helpful menu. Quasar Utils:

Utility Functions

Quasar offers pockets of functionality for common tasks. The ones I've found most handy are:

  1. Date Utils (manipulate dates without high cost of other libraries)
  2. Color Utils (Manipulate colors, and translate colors from Quasar's palette)
  3. Scrolling Utils (Scrolling to an element can be surprisingly difficult. These utils make it easy)
  4. Other Utils (openURL(), debounce(), exportFile(), copyToClipboard etc)

Here's how Quasar utilities usually work, using date as an example:

// we import all of `date`
import { date } from 'quasar'
// destructuring to keep only what is needed
const { addToDate } = date

const newDate = addToDate(new Date(), { days: 7, months: 1 })

The important part to note here is const { addToDate } = date, especially if file size is important for your project. It helps with tree shaking, and means only addToDate is included and NOT every function in date.

Here are some useful utils to get you started!
Date

  • formatDate(): great for displaying dates! You'll often use it within a computed
  • extractDate(): for those times when we have a date string in a weird format
  • isSameDate(): the third param is unit which is helpful! Can easily check if two dates are the same day/year/month etc

Color

  • rgbToHsv(): if you want total control over a color
  • lighten(): particularly helpful on the primary/secondary
  • changeAlpha(): add a little opacity to a color!
  • getPaletteColor(): warning - not cheap to run, but good to know we can extract colors from the palette

Other Utils

  • openURL(): takes care of quirks with Capacitor and Electron when opening a url
  • copyToClipboard(): try using this with a yellow Notify and the mdiContentCopy icon!
  • debounce(): stop users from spamming your server!
  • uid(): quick way to spin up a uuid… though consider using the uuid library if the id is for the backend

8. Icon Genie - Generating ALL Your App Icons

Generating icons for every single platform is a nightmare. Creating the icons is half the battle! We then need to put them in the right location so that capacitor, electron, cordova and your website know how to find them…

For that reason, Quasar comes with a phenomenal tool for generating icons called Icon Genie.

With one command, you can generate every icon you need to deploy your project. Here's the basic setup:

First, install Icon Genie:

npm i -g @quasar/icongenie

Then, put your png icon in the root of your project (or anywhere you like). We recommend the dimensions are at least 1024x1024 px.

Run the icongenie generate command and tell Icon Genie where your icon is located:

icongenie generate -i ./your-icon.png

You will need to update your index.html/index.template.html file!
Take note of the end of the command. It tells you how to update your index file so that it knows how to find your new icons:

 * You will need the following tags in your /index.html or /src/index.template.html:

<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png">
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
<link rel="icon" type="image/ico" href="favicon.ico">

And that's it! Icon Genie looks through your Quasar project, identifies the platforms you're using, generates the icon files you'll need, and puts them in the right location! Not bad for a single command eh?

This was just an intro. If you need more advanced features take a look at the Command List. Icon Genie can also:

  • work with Profile Files
  • include a --background to better generate splash screens
  • verify your apps icons and splash screens (helpful in CI/CD)

9. Plugins

Plugins are thoroughly covered in the Quasar Fundamentals Course!

You may want to think of plugins, as "functions that make common tasks in your app a easier". This article will give you a brief overview of how they work, using the Notify Plugin as an example.

All plugins must be installed. Quasar adds a little bit of code to our app to make plugins work, and for that reason we need to install them:
quasar.config.js

export default configure((ctx) => {
  // ...
  framework: {
    plugins: [
      'Notify'
    ]
  }
  // ...
})

All we did here, was add Notify to the list of plugins. Notify is built into Quasar, so no further setup is required.

We can now use this plugin anywhere in our app:

import { Notify } from 'quasar'

Notify.create({
  message: '10 Points To Gryffindor!',
  color: 'green-6'
})

The code above will even work in a boot file. For example, you may want to notify the user that they're not logged in, and are being redirected to the login page. Of course, there's a whole lot more the Notify plugin has to offer but I'll leave you with the docs for that!

Here are three other Quasar plugins you'll use all the time:

  1. Dialog: great for "End-user license agreement" and confirmation dialogs!
  2. Loading: Stop the user from clicking around when something important is loading
  3. Meta: Better SEO for your website!

10. Configuring Quasar (Vue Router History Mode, Vite and Dev Server)

There's a couple of bits and pieces you'll likely need to know about when configuring a Quasar project. Let's cover them here:

Vue Router - History Mode

By default, quasar uses "hash mode" for routing because it's easier to deploy. This means all route paths will be prefixed with a hash:

/#/friends/quasarcast

This works fine, but if you'd rather use history mode you can enable it:
quasar.config.js > build

build: {
  // ...
  vueRouterMode: 'history', // available values: 'hash', 'history'
  // ...
}

Adding Vite Plugins

As your project grows, there's a good chance you'll need to tap into Vite. Especially for adding plugins:

quasar.config.js > build

build: {
  vitePlugins: [
    ['unocss/vite', {}],
  ]
}

You can also extend Vite's config through build.extendViteConf

Dev Server: Changing the Port, and Proxy

There's a couple of reasons you may want to change the port:

  1. running two apps at the same time
  2. port 9000 is already taken

We can easily change it in our config file:
quasar.config.js > devServer

devServer: {
  port: 9001
}

Consider using an environment variable to make the port dynamic:
quasar.config.js > devServer

devServer: {
  port: process.env.DEV_SERVER_PORT ?? 9000
}

Devs will often use a server proxy when accessing their api to avoid CORS issues. We can do that with Quasar:
quasar.config.js > devServer

devServer: {
  proxy: {
    '/api': {
      target: '<http://jsonplaceholder.typicode.com>',
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\\/api/, '')
    },
  },
},

11. Testing (Vitest and Cypress)

Setting up testing is a breeze with Quasar! We have official App Extensions (AE’s) for:

  • Vitest: unit tests
  • Cypress: end-to-end (e2e), and component tests

The docs for both are fantastic, so we won’t cover installation and usage. The rest of this section assumes both of the above AE’s have been installed.

Cypress includes something called "component tests". This is a lightning fast way to test components in isolation with a gorgeous UI.

If you're new to testing, here's how I recommend you start:

  1. yarn test:e2e (requires Cypress AE): Write end to end tests (e2e) using cypress. Checking the home page loads, and a logging in test is a good place to start
  2. yarn test:component (requires Cypress AE): When you need to create a custom component - especially a "base" component that other components rely on - use component tests
  3. yarn test:unit or yarn test:unit:ui (requires Vitest AE): When testing composables, and other "javascripty" stuff!

Having said that, it depends on where your pain points are...

  • Are you working on composables that keep breaking? Then start with Vitest
  • Does your login page or payment gateway mess up every now and then? Then write some e2e tests with Cypress
  • Do you have a lot of complex, custom components? Then write some Cypress component tests

Final Words…

Often when learning a new language or framework, it’s important to go wide before going deep. We need an overview of what’s possible so we can effectively read the docs, and know where to look when we hit brick walls (that’s why we covered boot files early in this article… not knowing where main.js is can be a frustrating brick wall!).

I’m hoping this article provided the width you need, to start diving deep and building the apps of your dreams. I also hope you get to feel the love I’ve felt for Quasar. This framework led me to my dream job, gave me the power to build anything I set my mind to, and gave me a standard to strive for (especially when building my own components). You can learn more about my personal story here.

Thankyou for reading ❤️. I’d like to leave you with a couple places to go next:

  • Quasar Fundamentals Course: I spent months crafting a video series on getting up and running with Quasar. This is where you should go next
  • Quasar Discord: This is where we hang out and answer questions!
  • Donate To Quasar: Quasar is remarkably stable, especially considering the scope of the project. It’s insane that we get to use it for free, so please take the time to Donate To Quasar 💙

Start learning Vue.js for free

Luke Diebold
Luke Diebold
Discouraged from studying computer science in school, Luke was determined to prove that anyone can learn anything. After studying Musical Theatre and Classical Piano, he rediscovered coding at Agripath, where he fell in love with Quasar. He began creating YouTube videos to help others build amazing apps with Quasar, which led to contractor work. Now a web developer and CTO of Fuellox, Luke builds Quasar apps and shares his passion at events like “Quasar.Conf” and “Vue.js Nation.”

Comments

Latest Vue School Articles

10 Practical Tips for Better Vue Apps

10 Practical Tips for Better Vue Apps

Take your Vue.js skills to the next level with these 10 practical tips including: script setup, provide/inject, defineExpose, toRefs, and more
Daniel Kelly
Daniel Kelly
Building a &#8220;Procrastination Timer&#8221; with Vue 3 Composition API

Building a “Procrastination Timer” with Vue 3 Composition API

Learn to build a timer app with Vue.js and get a first hand look at how well Claude.ai understands the Vue Composition API
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 200.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.