admin/.nuxt-guide
koh 7f02e92304
Some checks failed
Build / build (push) Has been cancelled
Initial commit
2025-04-28 13:51:59 +07:00
..
2025-04-28 13:51:59 +07:00

Free Nuxt 3.x Vue 3.x Tailwind 4.x Dashboard

This guide will help you integrate your Nuxt.js 3.x application with Admin One - free Vue 3 Tailwind 4 Admin Dashboard with dark mode.

Please note: this document is work in progress and Nuxt 3 is in Release Candidate state, so some things can be missing and warnings may occur.

Table of contents

... TOC is coming soon

Install Nuxt.js 3.x app with Tailwind CSS

Check Nuxt installation guide for more information.

  • Run npx nuxi init sample-app
  • then cd sample-app
  • and npm install

Then, let's install TailwindCSS. Check Tailwind Nuxt installation guide for more information.

# Install tailwind
npm install -D @nuxtjs/tailwindcss @tailwindcss/forms

# Install other required packages
npm i @mdi/js chart.js numeral

# Install Pinia (official Vuex 5). --legacy-peer-deps is required because of the package dependencies issue
npm install --legacy-peer-deps pinia @pinia/nuxt

Copy styles, components and scripts

Now clone justboil/admin-one-vue-tailwind project somewhere locally (into any separate folder)

Next, copy these files from justboil/admin-one-vue-tailwind project directory to nuxt project directory:

  • Copy tailwind.config.js to /
  • Copy src/components to components/
  • Copy src/layouts to layouts/
  • Copy src/stores to stores/
  • Copy src/colors.js src/config.js src/menuAside.js src/menuNavBar.js to configs/
  • Copy src/css to assets/css/
  • Copy public/favicon.png to public/

Prepare items

In nuxt.config.ts

import { defineNuxtConfig } from 'nuxt'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  buildModules: ['@pinia/nuxt'],
  postcss: {
    plugins: {
      tailwindcss: {},
      autoprefixer: {}
    }
  },
  css: ['@/assets/css/main.css']
})

In tailwind.config.js

Replace content:

module.exports = {
  content: [
    './composables/**/*.{js,vue,ts}',
    './components/**/*.{js,vue,ts}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
    './plugins/**/*.{js,ts}',
    'app.vue'
  ]
  // ...
}

In App.vue

<script setup>
// import { useDarkModeStore } from '@/stores/darkMode.js'
// import { darkModeKey } from '@/config.js'

useHead({
  titleTemplate: (titleChunk) => {
    const titleBase = 'Admin One Vue 3 Tailwind'

    return titleChunk ? `${titleChunk} - ${titleBase}` : titleBase
  }
})

// const darkModeStore = useDarkModeStore()

// const currentStoredDarkMode =
//   typeof localStorage !== 'undefined' && localStorage[darkModeKey] === '1'

// if (
//   (!currentStoredDarkMode &&
//     typeof window !== 'undefined' &&
//     window.matchMedia('(prefers-color-scheme: dark)').matches) ||
//   currentStoredDarkMode
// ) {
//   darkModeStore.set(true)
// }
</script>

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>

In stores/main.js

Remove axios, as you'll likely going to use Nuxt's useFetch. Then add some sample data for clients and history.

// import axios from 'axios'

export const useMainStore = defineStore('main', {
  state: () => ({
    // ...

    clients: [
      {
        id: 19,
        avatar: 'https://avatars.dicebear.com/v2/gridy/Howell-Hand.svg',
        login: 'percy64',
        name: 'Howell Hand',
        company: 'Kiehn-Green',
        city: 'Emelyside',
        progress: 70,
        created: 'Mar 3, 2021'
      },
      {
        id: 11,
        avatar: 'https://avatars.dicebear.com/v2/gridy/Hope-Howe.svg',
        login: 'dare.concepcion',
        name: 'Hope Howe',
        company: 'Nolan Inc',
        city: 'Paristown',
        progress: 68,
        created: 'Dec 1, 2021'
      },
      {
        id: 32,
        avatar: 'https://avatars.dicebear.com/v2/gridy/Nelson-Jerde.svg',
        login: 'geovanni.kessler',
        name: 'Nelson Jerde',
        company: 'Nitzsche LLC',
        city: 'Jailynbury',
        progress: 49,
        created: 'May 18, 2021'
      },
      {
        id: 22,
        avatar: 'https://avatars.dicebear.com/v2/gridy/Kim-Weimann.svg',
        login: 'macejkovic.dashawn',
        name: 'Kim Weimann',
        company: 'Brown-Lueilwitz',
        city: 'New Emie',
        progress: 38,
        created: 'May 4, 2021'
      }
    ],
    history: [
      {
        amount: 375.53,
        name: 'Home Loan Account',
        date: '3 days ago',
        type: 'deposit',
        business: 'Turcotte'
      },
      {
        amount: 470.26,
        name: 'Savings Account',
        date: '3 days ago',
        type: 'payment',
        business: 'Murazik - Graham'
      },
      {
        amount: 971.34,
        name: 'Checking Account',
        date: '5 days ago',
        type: 'invoice',
        business: 'Fahey - Keebler'
      },
      {
        amount: 374.63,
        name: 'Auto Loan Account',
        date: '7 days ago',
        type: 'withdrawal',
        business: 'Collier - Hintz'
      }
    ]
  }),
  actions: {
    // ...

    fetch(sampleDataKey) {
      // axios
      //   .get(`data-sources/${sampleDataKey}.json`)
      //   .then(r => {
      //     if (r.data && r.data.data) {
      //       this[sampleDataKey] = r.data.data
      //     }
      //   })
      //   .catch(error => {
      //     alert(error.message)
      //   })
    }
  }
})

Rename layouts

  • Rename layouts/LayoutGuest.vue to default.vue
  • Rename layouts/LayoutAuthenticated.vue to authenticated.vue

Copy pages

Let's copy views/LoginView.vue with a guest layout and views/HomeView.vue with an authenticated layout.

These pages will then be available under / and /dashboard url paths.

LoginView.vue

Copy views/LoginView.vue to pages/index.vue

Then, wrap the entire template with <div> and replace <LayoutGuest> with <NuxtLayout>

Why we need a div wrapper? If you use <NuxtLayout> within your pages, make sure it is not the root element (or disable layout/page transitions) — Info

<script setup>
// import LayoutGuest from '@/layouts/LayoutGuest.vue'
// ...
</script>

<template>
  <div>
    <NuxtLayout>
      <!-- ... -->
    </NuxtLayout>
  </div>
</template>

HomeView.vue

Copy views/HomeView.vue to pages/dashboard.vue

Then, wrap the entire template with <div> and replace <LayoutGuest> with <NuxtLayout> with a name prop.

<script setup>
// import LayoutAuthenticated from '@/layouts/LayoutAuthenticated.vue'
// ...
</script>

<template>
  <div>
    <NuxtLayout name="authenticated">
      <!-- ... -->
    </NuxtLayout>
  </div>
</template>

Details are coming soon...

Remove/update imports

Nuxt automatically imports any components in your components/ directory. So, you may safely remove that imports from <script setup>. The only exception is for components/Charts, so charts import should be left as is.

Contributions open

WIP - work in progress. Some things are missing. Contributions open.