Laravel Inertia Vue Admin Tailwind
October 13, 2024 · AI Conversations
Here’s how you can set this up:
### 1. Set Up Laravel with Inertia.js and Vue.js for Frontend
– **Install Laravel:**
If you haven't already, install a fresh Laravel app:
composer create-project laravel/laravel my-app
– **Install Inertia.js:**
Inertia allows you to build modern single-page applications (SPAs) using Vue.js or React, without the complexity of a full SPA framework like Nuxt or Next.
Install Inertia.js server-side adapter:
composer require inertiajs/inertia-laravel
Then, install the client-side Vue adapter:
npm install @inertiajs/inertia @inertiajs/inertia-vue3
– **Set up Inertia Middleware:**
Add the middleware to the `web` middleware group in `app/Http/Kernel.php`:
'web' => [
AppHttpMiddlewareHandleInertiaRequests::class,
// Other middlewares...
],
– **Install Vue.js:**
You can scaffold the Vue setup for Inertia:
npm install vue@next vue-loader@next
npm install @vitejs/plugin-vue --save-dev
After that, create the `app.js` file to initialize Inertia with Vue:
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/inertia-vue3'
createInertiaApp({
resolve: name => require(`./Pages/${name}`),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el)
},
})
– **Configure Webpack (or Vite if using Laravel 9+):**
Update `webpack.mix.js` or Vite configuration to compile your Vue components:
mix.js('resources/js/app.js', 'public/js')
.vue()
.postCss('resources/css/app.css', 'public/css', [
require('tailwindcss'),
]);
– **Frontend Views (Inertia + Vue):**
Create your Vue.js frontend components inside `resources/js/Pages/` and route to them via Laravel using Inertia. In `routes/web.php`, for example:
use InertiaInertia;
Route::get('/', function () {
return Inertia::render('Home');
});
This will render the `resources/js/Pages/Home.vue` component.
### 2. Set Up Blade with Tailwind CSS for Admin Panel
You can configure a different set of routes for the admin panel, using Blade views with Tailwind for styling.
– **Create Admin Route:**
In your `routes/web.php`, create a separate route group for the admin panel, specifying that it will use Blade views:
Route::group(['prefix' => 'admin', 'middleware' => ['auth']], function () {
Route::get('/', function () {
return view('admin.dashboard');
})->name('admin.dashboard');
});
– **Blade Views for Admin:**
Create your admin dashboard and other Blade views inside the `resources/views/admin/` directory. For example, create `dashboard.blade.php`:
<x-admin-layout>
<div class="p-6">
<h1 class="text-2xl font-bold">Admin Dashboard</h1>
<!-- Admin Content Goes Here -->
</div>
</x-admin-layout>
– **Admin Layout:**
Create a reusable Blade layout for your admin panel. You can create a `resources/views/layouts/admin.blade.php`:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel</title>
@vite('resources/css/app.css')
</head>
<body class="bg-gray-100">
<div class="min-h-screen flex flex-col">
<header class="bg-white shadow">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
Admin Navigation
</div>
</header>
<main class="flex-grow">
{{ $slot }}
</main>
<footer class="bg-white shadow py-4">
<div class="max-w-7xl mx-auto">
Footer Content
</div>
</footer>
</div>
</body>
</html>
– **Tailwind CSS for Admin:**
Since you're already using Tailwind in your Laravel app (with either Mix or Vite), you can reuse the same configuration for both the frontend and admin. Ensure your `app.css` is loaded in the Blade views for the admin panel.
### 3. Combining Both
Now that you have both Inertia.js + Vue.js for the frontend and Blade + Tailwind for the admin, you can manage the separation of concerns by:
– Using **Inertia.js routes** for the user-facing side of the application (e.g., `/`, `/products`, `/profile`, etc.).
– Using **Blade routes** for the admin side (e.g., `/admin`, `/admin/users`, `/admin/settings`, etc.).
In your routes file, this might look something like:
use InertiaInertia;
Route::get('/', function () {
return Inertia::render('Home');
});
Route::get('/about', function () {
return Inertia::render('About');
});
// Admin Routes
Route::group(['prefix' => 'admin', 'middleware' => ['auth']], function () {
Route::get('/', function () {
return view('admin.dashboard');
})->name('admin.dashboard');
});
### 4. Authentication (Optional)
If you're using **Laravel Breeze**, **Jetstream**, or **Fortify** for authentication, you can configure different layouts and views for logged-in users (admin) and guest users (frontend). You can conditionally load Blade templates for the admin panel and Vue components for the frontend based on the user roles.
—
This setup allows you to mix Inertia.js and Vue.js for a SPA-like frontend experience, while keeping Blade and Tailwind for a more traditional server-rendered admin dashboard.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel - @yield('title')</title>
@vite('resources/css/app.css')
<!-- You can add any additional head content like scripts or meta tags -->
</head>
<body class="bg-gray-100 font-sans leading-normal tracking-normal">
<div class="flex h-screen">
<!-- Sidebar -->
<div class="w-64 bg-gray-800 text-gray-200 flex-shrink-0">
<div class="flex items-center justify-center h-16 bg-gray-900">
<h1 class="text-xl font-bold">Admin Panel</h1>
</div>
<nav class="mt-10">
<a href="{{ route('admin.dashboard') }}" class="block py-2.5 px-4 rounded hover:bg-gray-700 transition duration-200">
Dashboard
</a>
<a href="#" class="block py-2.5 px-4 rounded hover:bg-gray-700 transition duration-200">
Users
</a>
<a href="#" class="block py-2.5 px-4 rounded hover:bg-gray-700 transition duration-200">
Settings
</a>
<!-- Add more navigation links as needed -->
</nav>
</div>
<!-- Main Content Area -->
<div class="flex-1 flex flex-col">
<!-- Header -->
<header class="bg-white shadow-md">
<div class="container mx-auto px-6 py-4">
<div class="flex justify-between items-center">
<h2 class="text-lg font-semibold">@yield('title', 'Admin Dashboard')</h2>
<div class="flex items-center space-x-4">
<span class="text-gray-600">{{ Auth::user()->name }}</span>
<a href="{{ route('logout') }}" class="text-gray-600 hover:text-gray-900"
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
Logout
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="hidden">
@csrf
</form>
</div>
</div>
</div>
</header>
<!-- Content -->
<main class="flex-1 overflow-y-auto bg-gray-100">
<div class="container mx-auto px-6 py-8">
@yield('content')
<!-- If you're using slots for Blade components: -->
{{ $slot ?? '' }}
</div>
</main>
<!-- Footer -->
<footer class="bg-white shadow-md">
<div class="container mx-auto px-6 py-4 text-gray-600">
<p>© {{ date('Y') }} Admin Panel. All rights reserved.</p>
</div>
</footer>
</div>
</div>
</body>
</html>
### Layout Explanation:
1. **Sidebar**:
The sidebar includes links for navigation. You can modify or add additional links as needed. It’s styled with Tailwind classes for a clean, modern look.
2. **Header**:
Displays the page title and user information. There’s a logout button that uses a form to log the user out securely via a POST request. It also pulls the authenticated user’s name using `Auth::user()->name`.
3. **Content Area**:
The `@yield('content')` directive is used to insert the main content for each admin page. If you're using Blade components with slots, you can also use `{{ $slot }}` for dynamic content insertion.
4. **Footer**:
A simple footer is added at the bottom of the page.
### Usage Example for an Admin Dashboard Page:
In your `resources/views/admin/dashboard.blade.php`, you can use this layout like so:
@extends('layouts.admin')
@section('title', 'Dashboard')
@section('content')
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">Admin Dashboard</h3>
<p class="mt-1 max-w-2xl text-sm text-gray-500">Overview of the admin functionalities.</p>
</div>
<div class="border-t border-gray-200">
<dl>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm font-medium text-gray-500">Users</dt>
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">Manage users of the system</dd>
</div>
<!-- Add more dashboard items here -->
</dl>
</div>
</div>
@endsection
This structure allows you to build a robust admin panel using Blade templates with Tailwind CSS for styling. You can expand the layout, adding more components like modals or notifications, as needed.
Here are steps to troubleshoot and resolve this issue:
### 1. **Check Your `config/auth.php` File:**
The `auth.php` configuration file is where the authentication guards and providers are defined. Ensure that the configuration is correct.
– **Check the Default Guard and User Provider:**
Open `config/auth.php` and make sure the `guards` and `providers` are properly configured.
Here's an example of a typical configuration:
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => AppModelsUser::class,
],
// Optionally, you can use a database provider:
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
– Ensure that the `provider` defined under the `guards` array matches a valid provider in the `providers` array. For example, `provider` should match `users` in both sections.
– Ensure the `model` under the `users` provider is pointing to the correct `User` model class (`AppModelsUser::class`).
### 2. **Check the User Model:**
If you’re using a custom user model, ensure that the `model` option in the `providers` array points to the correct class. By default, Laravel uses `AppModelsUser`, but if you’ve moved or renamed it, make sure the `model` key is pointing to the correct class.
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => AppModelsUser::class, // Ensure this is correct
],
],
If you are using the default Laravel structure, the `User` model should be in `app/Models/User.php`.
### 3. **Run Configuration Cache Clear Commands:**
If you’ve made changes to your configuration files and they’re not being reflected, try clearing your configuration cache:
php artisan config:clear
php artisan cache:clear
You can also run:
php artisan config:cache
### 4. **Check for Middleware Issues:**
If you’re having this issue after applying middleware to certain routes, ensure that you’ve applied the correct middleware. For example, check that you’re using the correct `auth` middleware in your route definitions.
Example:
Route::group(['middleware' => 'auth'], function () {
Route::get('/admin', [AdminController::class, 'index']);
});
Ensure that `auth` middleware is set up correctly in `app/Http/Kernel.php`:
protected $routeMiddleware = [
'auth' => AppHttpMiddlewareAuthenticate::class,
];
### 5. **Check `.env` File for Authentication Settings:**
Ensure that your `.env` file contains the correct configuration for authentication, specifically for the `SESSION_DRIVER` and `CACHE_DRIVER` values.
For example:
SESSION_DRIVER=file
CACHE_DRIVER=file
If you're using database sessions, ensure that you have run the necessary migration:
php artisan session:table
php artisan migrate
### 6. **Check the Authentication Middleware (Optional):**
If you're overriding the `Authenticate` middleware (which is responsible for handling unauthorized users), check that the `redirectTo()` method is correctly defined and doesn’t interfere with your authentication provider.
Example in `app/Http/Middleware/Authenticate.php`:
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
### 7. **Check Your Custom Authentication Logic (if any):**
If you've customized the authentication logic or guards, ensure that you're providing the correct user provider to Laravel’s authentication system. For example, when using a custom guard, you need to ensure that you're setting the provider correctly.
—
By following these steps, you should be able to resolve the error. The key point is ensuring that your `config/auth.php` file is correctly configured, and that the `provider` is properly set up with a valid user model.