How to set up a project with Nuxt 3 and Vuetify 3 with themes and Icon Fonts

How to set up a project with Nuxt 3 and Vuetify 3 with themes and Icon FontsIn this article, I will guide you through the setup process to use Vuetify 3 with Nuxt 3! I will also show you the basic configurations you should need to know to get up and running in just a few minutes! So let's get started!
Categoriesvue3vuetify3project setupnuxt
Date
2023-09-26
Hire me on Upwork!

Creating a Nuxt 3 Project

Nuxt 3 is based on Vue3, if you are already familiar with vue3, great!

If you think you should catch up a little on it, I could highly recommend the course:

Vue - The Complete Guide (incl. Router & Composition API) * by Maximilian Schwarzmüller. This is the course I learned vue with, and in my opinion the best course out there to learn vue. It is completely updated for vue3.

To make this article fit for all editor choices, I will use the CLI to create the project.

To set up your nuxt project run

npx nuxi init nuxt-app

In Your desired folder.

Set up nuxt3 with vuetify cli

You may need to install nuxi, the new nuxt cli, just type y if you were asked.

Then the project will be set up, this step takes less than a second, and we are ready to go.

Then navigate into your nuxt-app directory, or move the content of this directory to your wished location. I move it to my root folder since I like to have the package.json directly contained in my root folder.

Then run

npm install

as always to initially load all the dependencies.

When everything is done, run

npm run dev

To spin up the vite server and make nuxt available on http://localhost:3000/.

The first big difference to nuxt 2 is that this will take less than a minute since nuxt 3 is vite powered.

You will now see the beautiful landing page of Nuxt 3.

Install Vuetify 3 inside Nuxt 3

Vuetify 3 is currently also in beta. To use it run:

npm install vuetify@next

This will install the latest beta version of vuetify from npm.

Also install the vuetify vite Plugin as described here.

npm install -D vuetify@next vite-plugin-vuetify

Then create a plugins directory if you haven't.

Inside this directory, create a file named vuetify.ts.

Paste the following code into it:

// plugins/vuetify.ts

import { createVuetify } from 'vuetify'

export default defineNuxtPlugin(nuxtApp => {
    const vuetify = createVuetify({
        // your config will come here
    })

    nuxtApp.vueApp.use(vuetify)
})

In your nuxt.config.js paste the following code: note: By Using the vuetify/vite plugin you will have automatic imports. So you do not need to explicitly import things like components or directives. Vite will do this for you as you need them. Thanks to KaelWD for pointing this out!

// nuxt.config.ts

import { defineNuxtConfig } from 'nuxt'
import vuetify from 'vite-plugin-vuetify'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
// @ts-ignore
export default defineNuxtConfig({
    css: ['vuetify/styles'], // vuetify ships precompiled css, no need to import sass
    vite: {
        // @ts-ignore
        // curently this will lead to a type error, but hopefully will be fixed soon #justBetaThings
        ssr: {
            noExternal: ['vuetify'], // add the vuetify vite plugin
        },
    },
    modules: [
        // @ts-ignore
        // this adds the vuetify vite plugin
        // also produces type errors in the current beta release
        async (options, nuxt) => {
            nuxt.hooks.hook('vite:extendConfig', config => config.plugins.push(
                vuetify()
            ))
        }
    ]
}

And to verify the Installation, we will add a simple card on top of our welcome screen.

<template>
  <div>
    <v-card
class="mx-auto"
width="400"
prepend-icon="mdi-home"
    >
      <templatev-slot:title>
        Hello from Vuetify!
      </template>
      <v-card-text>
        When you see this inside a card, it worked!
      </v-card-text>
    </v-card>
    <NuxtWelcome />
  </div>
</template>

When the installation was successful, you should see something like this: When the installation was successful, you should see this.

Further configuration of Vuetify 3

One thing I like about Vuetify is its clean global configuration.

This also works with Vuetify 3, the concepts are the same, but the syntax is slightly different since also the vue3 syntax has moved on.

Change the global Theme in Vuetify 3

If you would like to set the dark theme as default, you can do this easily in the configuration.

Put this into `createVuetify({` to enable the dark theme as the default theme:

theme: {
    defaultTheme: 'dark'
  }

Or you can also create your own custom themes:

const myAllBlackTheme: ThemeDefinition = {
  dark: false,
  colors: {
    background: '#000000',
    surface: '#000000',
    primary: '#000000',
    'primary-darken-1': '#000000',
    secondary: '#000000',
    'secondary-darken-1': '#000000',
    error: '#000000',
    info: '#000000',
    success: '#000000',
    warning: '#000000',
  }
}

export default createVuetify({
  theme: {
    defaultTheme: 'myAllBlackTheme',
    themes: {
      myAllBlackTheme,
    }
  }
})

Add Icon fonts to Vuetify 3

By default, you can choose the well-known fonts: Material Design Icons (mdi)Material Icons(mi)Font Awesome 4(fa4), and Font Awesome 5(fa5).

To add a font to vuetify simply import the wished font from the icon sets directory and introduce it to vuetify in the exports.

Resolve Vuetify Icons not shown

It could happen that your Icons will not appear after you added them.

I also had this issue when trying this out for the first time.

To fix Vuetify icon's not shown error, make sure to install the corresponding font and add its CSS to your plugin config.

Note that this could possibly change as Vuetify beta evolves, since this procedure is also not mentioned in the documentation.

I will show you how to do this based on using font awesome and mdi.

This also applies if you want to install custom fonts!

Install the font

npm install @fortawesome/fontawesome-free -D

npm install @mdi/font

Add the Fonts CSS to your vuetify plugin.

import* '@mdi/font/css/materialdesignicons.css'

import* '@fortawesome/fontawesome-free/css/all.css'

Make sure you are using a CSS loader.

import { createVuetify } from 'vuetify'

import { aliases, fa } from 'vuetify/iconsets/fa'
import {mdi} from "vuetify/lib/iconsets/mdi";
// make sure to also import the coresponding css
import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
import '@fortawesome/fontawesome-free/css/all.css' // Ensure your project is capable of handling css files
export default defineNuxtPlugin(nuxtApp => {
    const vuetify = createVuetify({ // Replaces new Vuetify(...)
        theme: {
            defaultTheme: 'dark'
        },
        icons: {
            defaultSet: 'fa',
            aliases,
            sets: {
                mdi,
                fa
            }
        },
    })

    nuxtApp.vueApp.use(vuetify)
})

In the above snippet, I use font-awesome as my default icon font and mdi as an additional font.

You can now use your icons!

<v-icon icon="fas fa-plus" /> To render a FontAwesome icon
<v-icon icon="mdi:mdi-minus" /> To render a MDI icon

Solving Vuetify Breakpoints Issue in Nuxt 3 for SSR

While integrating Vuetify with Nuxt 3, you may encounter some issues with Vuetify’s breakpoints during Server-Side Rendering (SSR), as the breakpoint object relies on the window object, which isn’t available on the server. Here’s a well-structured solution to tackle such issues, ensuring a smoother user experience (UX) and optimal rendering of your components.

1. Create a Client-Only Mixin:

Create a mixin, which we will call ClientMixin.js, that holds an isClient data property. This property will be true only when the component is running on the client side:

// mixins/ClientMixin.js
export default {
  data() {
    return {
      isClient: false
    };
  },
  mounted() {
    this.isClient = true;
  }
};

2. Implement a Breakpoints Mixin:

Build a BreakpointsMixin.js, utilizing the ClientMixin, to expose a safeBreakpoint computed property. This property will provide the actual Vuetify breakpoints on the client side or return default values on the server side, preventing potential errors related to SSR.

// mixins/BreakpointsMixin.js
import ClientMixin from '@/mixins/ClientMixin'; // Adjust the import path accordingly

export default {
  mixins: [ClientMixin],
  computed: {
    safeBreakpoint() {
      if (!this.isClient) {
        return {
          xs: false, sm: false, md: false, lg: false, xl: false,
          smAndDown: false, smAndUp: true,
          mdAndDown: false, mdAndUp: true,
          lgAndDown: false, lgAndUp: true
        };
      }
      return this.$vuetify.breakpoint;
    }
  }
};

3. Usage in your Components:

Import BreakpointsMixin in the components where you want to use Vuetify breakpoints. Use the safeBreakpoint computed property instead of $vuetify.breakpoints, to access the breakpoints securely:

<template>
  <!-- Example Component -->
  <v-bottom-navigation v-if="safeBreakpoint.smAndDown">
    <!-- Navigation items here -->
  </v-bottom-navigation>
</template>

<script>
import BreakpointsMixin from '@/mixins/BreakpointsMixin'; // Adjust the import path accordingly

export default {
  mixins: [BreakpointsMixin]
};
</script>

Integrating this technique ensures that your Nuxt 3 project leveraging Vuetify will have optimized and error-free rendering in SSR scenarios. This will give you enhanced stability and improved UX, especially when dealing with responsive design utilizing Vuetify’s breakpoints.

The current state of Vuetify 3

By the time of writing this article July 19, 2022 vuetify supports most of the well-known features from vuetify2 + some fresh new stuff like defaults.

Where defaults are looking really useful to me.

You can define default values like a default elevation globally and apply this to all elements in your application. Or you can use local defaults, applying those values only to elements wrapped into the <v-defaults-provider> tag. I think this could be a huge help to reach consistent designs.

So you can wrap for example a list of cards in a <v-defaults-provider> to give them all a consistent look without having to duplicate all the props over and over again. Or make one global default, to make all the cards in your app have for example the same elevation.

To keep up to date with the Vuetify 3 releases, you can frequently take a look at their release page.

Update 08.12.2022

Vuetify3 has been released on 31. October, and it was definitely not a Halloween shocker.

It is already stable and now also recommended for Production! By now there are still some components missing like Data Tables, so keep this in mind when upgrading!

Conclusion

With Nuxt 3 and Vuetify 3 there are finally coming two of my favorite parts of the vue2 ecosystem to vue3.

Both Nuxt 3 and Vuetify 3 are complete rewrites, and they really did a good job at it.

Vuetify 3 already ported most of the components from vuetify2 and its directives and grid systems. You should definitely try it out!

If you want to keep up to date with the releases of Nuxt 3 and Vuetify 3, I would suggest following their roadmaps.

If you need a domain for a budget, with my link you can register a .com domain starting at $6.98!

You can find the code for this article on my GitHub.

Happy coding,

Alex

Recommended Products for you
recommended for you