# Free Laravel Vue 3.x Tailwind 4.x Dashboard
[](https://justboil.github.io/admin-one-vue-tailwind/)
This guide will help you integrate your Laravel application with [Admin One - free Vue 3 Tailwind 4 Admin Dashboard with dark mode](https://github.com/justboil/admin-one-vue-tailwind).
**Admin One** is simple, fast and free Vue.js 3.x Tailwind CSS 4.x admin dashboard with Laravel 12.x integration.
- Built with **Vue.js 3**, **Tailwind CSS 4** framework & **Composition API**
- **Laravel** build tools
- **Laravel Jetstream** with **Inertia + Vue** stack
- **SFC** `
```
Add route in `routes/web.php`. There's a `/dashboard` route already defined by default, so just replace `Inertia::render('Dashboard')` with `Inertia::render('HomeView')`:
```php
Route::get('/dashboard', function () {
return Inertia::render('HomeView');
})->middleware(['auth', 'verified'])->name('dashboard');
```
## Fix router links
Here we replace RouterLink with Inertia Link.
### resources/js/menuAside.js and resources/js/menuNavBar.js
Optionally, you can pass menu via Inertia shared props, so you'll be able to control it with PHP. Here we'd just use JS.
`to` should be replaced with `route` which specifies route name defined in `routes/web.php`. For external links `href` should be used instead. Here's an example for `menuAside.js`:
```javascript
export default [
'General',
[
{
route: 'dashboard',
icon: mdiMonitor,
label: 'Dashboard'
},
// {
// route: "another-route-name",
// icon: mdiMonitor,
// label: "Dashboard 2",
// },
{
href: 'https://example.com/',
icon: mdiMonitor,
label: 'Example.com'
}
]
]
```
Route names reflect ones defined in `routes/web.php`:
```php
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return Inertia::render('Home');
})->name('dashboard');
// Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard-2', function () {
// return Inertia::render('Home2');
// })->name('another-route-name');
```
Now, let's update vue files, to make them work with route names and Inertia links.
### resources/js/components/AsideMenuItem.vue
Replace `RouterLink` imported from `vue-router` with `Link` import in `
```
In `` section:
- In `` remove `v-slot` and `:to` attributes; replace `:is` with `:is="item.route ? Link : 'a'"` and `:href` with `:href="itemHref"`
- Inside `` replace `:class` attribute for both `` components, `` and another `` with `:class="activeInactiveStyle"`
- ...and for `` (also inside ``) replace `:class` attribute with `:class="[{ 'pr-12': !hasDropdown }, activeInactiveStyle]"`
### resources/js/components/BaseButton.vue
Replace `RouterLink` imported from `vue-router` with `Link` import in `
```
Replace `to` prop declaration with `routeName`:
```javascript
const props = defineProps({
// ...
routeName: {
type: String,
default: null
}
// ...
})
```
Fix `const is` declaration, so it returns the `Link` component when `props.routeName` is set:
```javascript
const is = computed(() => {
if (props.as) {
return props.as
}
if (props.routeName) {
return Link
}
if (props.href) {
return 'a'
}
return 'button'
})
```
Remove `:to` and replace `:href` in `` with `:href="routeName ? route(routeName) : href"`:
```vue
```
### resources/js/components/NavBarItem.vue
Replace `RouterLink` imported from `vue-router` with `Link` import in `
```
Then, remove `:to` attribute and set `:href` attribute to `:href="itemHref"` in ``.
## Add Inertia-related stuff
### resources/js/layouts/LayoutAuthenticated.vue
```vue
```
### resources/js/components/UserAvatarCurrentUser.vue
Let's fetch user avatar initials based on username stored in database.
```vue
```
### resources/js/components/NavBarItem.vue
```vue
```
## Upgrading to Premium version
Please make sure you have completed all previous steps in this guide, so you have everything up and running. Then download and uzip the Premium version files. Next, follow steps described below.
### Add deps
```bash
npm i @headlessui/vue -D
```
### Copy files
Copy files to your Laravel project (overwrite free version ones or merge if you have changed something):
- Copy `src/components/Premium` to `resources/js/components/Premium`
- Copy `src/stores` to `resources/js/stores`
- Copy `src/config.js` to `resources/js/config.js`
- Copy `src/sampleButtonMenuOptions.js` to `resources/js/sampleButtonMenuOptions.js`
- Copy `src/colorsPremium.js` to `resources/js/colorsPremium.js`
### Update tailwind.config.js
Replace `tailwind.config.js` in your Laravel project with the Premium one. Make sure to preserve `module.exports.content`:
```js
module.exports = {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./resources/js/**/*.vue',
'./resources/js/**/*.js'
]
// ...
}
```
### Update resources/js/app.js
Add layout store to `resources/js/app.js`:
```js
// Add layout store
import { useLayoutStore } from '@/stores/layout.js'
const layoutStore = useLayoutStore(pinia)
layoutStore.responsiveLayoutControl()
window.onresize = () => layoutStore.responsiveLayoutControl()
```
### Update resources/js/layouts/LayoutAuthenticated.vue
Replace contents of `resources/js/layouts/LayoutAuthenticated.vue` with contents of `src/js/layouts/LayoutAuthenticated.vue` (from the Premium version)
```vue
```
### Use premium login and signup layouts
Optionally, you may update layouts of login and signup, located at `resources/js/Pages/Auth` with Premium version layouts from `src/views/Premium/LoginView.vue` and `src/views/Premium/SignupView.vue`
## Optional steps
### Default style
It's likely, you'll use only one app style. Follow [this guide](https://justboil.github.io/docs/customization/#default-style) to set one of choice.
### Fix .editorconfig
Add to .editorconfig:
```editorconfig
[*.{js,jsx,ts,tsx,vue,html,css}]
indent_size = 2
```
### resources/js/bootstrap.js
Global `lodash` and `axios` aren't needed, as we import them directly when necessary.
## Laravel & Inertia docs
- [Laravel Docs](https://laravel.com/docs)
- [Laravel Jetstream Docs](https://jetstream.laravel.com/)
- [Inertia](https://inertiajs.com/)