Kritim Yantra
Jun 27, 2025
Want to build a complete CRUD application with Laravel 12 and TailwindCSS? This step-by-step guide will walk you through creating a beautiful, functional application with Create, Read, Update, and Delete operations using Blade templates.
First, create a new Laravel 12 project:
composer create-project laravel/laravel laravel-crud
cd laravel-crud
Install TailwindCSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
Configure tailwind.config.js
:
module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
],
theme: {
extend: {},
},
plugins: [],
}
Add Tailwind to resources/css/app.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
Update vite.config.js
:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
Set up your .env
file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_crud
DB_USERNAME=root
DB_PASSWORD=
Create the database and run migrations:
php artisan migrate
Let's create a Post
model for our CRUD:
php artisan make:model Post -m
Edit the migration file:
// database/migrations/xxxx_create_posts_table.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
Run the migration:
php artisan migrate
Create a controller:
php artisan make:controller PostController --resource
Edit app/Http/Controllers/PostController.php
:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate(5);
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'content' => 'required',
]);
Post::create($request->all());
return redirect()->route('posts.index')
->with('success', 'Post created successfully.');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post)
{
$request->validate([
'title' => 'required',
'content' => 'required',
]);
$post->update($request->all());
return redirect()->route('posts.index')
->with('success', 'Post updated successfully');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')
->with('success', 'Post deleted successfully');
}
}
Create resources/views/layouts/app.blade.php
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laravel CRUD</title>
@vite(['resources/css/app.css'])
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
@if(session('success'))
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
{{ session('success') }}
</div>
@endif
@yield('content')
</div>
</body>
</html>
Create resources/views/posts/index.blade.php
:
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-800">Posts</h1>
<a href="{{ route('posts.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Create New Post
</a>
</div>
<table class="min-w-full bg-white">
<thead>
<tr>
<th class="py-2 px-4 border-b border-gray-200 bg-gray-50 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Title</th>
<th class="py-2 px-4 border-b border-gray-200 bg-gray-50 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody>
@foreach($posts as $post)
<tr>
<td class="py-2 px-4 border-b border-gray-200">{{ $post->title }}</td>
<td class="py-2 px-4 border-b border-gray-200">
<div class="flex space-x-2">
<a href="{{ route('posts.show', $post->id) }}" class="text-blue-500 hover:text-blue-700">View</a>
<a href="{{ route('posts.edit', $post->id) }}" class="text-green-500 hover:text-green-700">Edit</a>
<form action="{{ route('posts.destroy', $post->id) }}" method="POST" onsubmit="return confirm('Are you sure?')">
@csrf
@method('DELETE')
<button type="submit" class="text-red-500 hover:text-red-700">Delete</button>
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="mt-4">
{{ $posts->links() }}
</div>
</div>
@endsection
Create resources/views/posts/create.blade.php
:
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 max-w-md mx-auto">
<h1 class="text-2xl font-bold text-gray-800 mb-6">Create New Post</h1>
<form action="{{ route('posts.store') }}" method="POST">
@csrf
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="title">
Title
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="title" type="text" name="title" required>
</div>
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="content">
Content
</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="content" name="content" rows="5" required></textarea>
</div>
<div class="flex items-center justify-between">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit">
Submit
</button>
<a href="{{ route('posts.index') }}" class="text-gray-600 hover:text-gray-800">
Cancel
</a>
</div>
</form>
</div>
@endsection
Create resources/views/posts/show.blade.php
:
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 max-w-2xl mx-auto">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-800">{{ $post->title }}</h1>
<div class="flex space-x-2">
<a href="{{ route('posts.edit', $post->id) }}" class="text-green-500 hover:text-green-700">Edit</a>
<form action="{{ route('posts.destroy', $post->id) }}" method="POST" onsubmit="return confirm('Are you sure?')">
@csrf
@method('DELETE')
<button type="submit" class="text-red-500 hover:text-red-700">Delete</button>
</form>
</div>
</div>
<div class="prose max-w-none">
{!! nl2br(e($post->content)) !!}
</div>
<div class="mt-6">
<a href="{{ route('posts.index') }}" class="text-blue-500 hover:text-blue-700">โ Back to all posts</a>
</div>
</div>
@endsection
Create resources/views/posts/edit.blade.php
:
@extends('layouts.app')
@section('content')
<div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4 max-w-md mx-auto">
<h1 class="text-2xl font-bold text-gray-800 mb-6">Edit Post</h1>
<form action="{{ route('posts.update', $post->id) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="title">
Title
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="title" type="text" name="title" value="{{ $post->title }}" required>
</div>
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="content">
Content
</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="content" name="content" rows="5" required>{{ $post->content }}</textarea>
</div>
<div class="flex items-center justify-between">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit">
Update
</button>
<a href="{{ route('posts.index') }}" class="text-gray-600 hover:text-gray-800">
Cancel
</a>
</div>
</form>
</div>
@endsection
Update routes/web.php
:
<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return redirect()->route('posts.index');
});
Route::resource('posts', PostController::class);
Start the development server:
php artisan serve
npm run dev
Now visit http://localhost:8000/posts
to see your CRUD application in action!
Congratulations! You've built a complete CRUD application with Laravel 12 and TailwindCSS. Happy coding! ๐
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google