Laravel 12 CRUD with TailwindCSS & Blade: Beginner's Guide (2025)

Author

Kritim Yantra

Jun 27, 2025

Laravel 12 CRUD with TailwindCSS & Blade: Beginner's Guide (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.

๐Ÿ“‹ Table of Contents

  1. Project Setup
  2. Database Configuration
  3. Creating the Model & Migration
  4. Building the Controller
  5. Creating Blade Views
  6. Adding Routes
  7. Final Touches

๐Ÿ›  1. Project Setup

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,
    }),
  ],
});

๐Ÿ—ƒ 2. Database Configuration

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

๐Ÿ“ 3. Creating the Model & Migration

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

๐ŸŽฎ 4. Building the Controller

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');
    }
}

๐Ÿ–ฅ 5. Creating Blade Views

Layout File

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>

Index View

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 View

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

Show View

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

Edit View

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

๐Ÿ›ฃ 6. Adding Routes

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);

๐ŸŽ‰ 7. Final Touches

Start the development server:

php artisan serve
npm run dev

Now visit http://localhost:8000/posts to see your CRUD application in action!

๐Ÿ”‘ Key Features Implemented

  • โœ… Create: Add new posts
  • โœ… Read: View all posts and single posts
  • โœ… Update: Edit existing posts
  • โœ… Delete: Remove posts
  • โœ… Pagination: Automatic pagination
  • โœ… Validation: Form validation
  • โœ… Responsive Design: Works on all devices
  • โœ… Modern UI: Clean TailwindCSS styling

๐Ÿš€ Next Steps

  • Add user authentication
  • Implement file uploads
  • Add comments functionality
  • Create an API version

Congratulations! You've built a complete CRUD application with Laravel 12 and TailwindCSS. Happy coding! ๐ŸŽ‰

Ajay Yadav

Ajay Yadav

Senior Full-Stack Engineer

7 + Years Experience

Transforming Ideas Into Digital Solutions

I architect and build high-performance web applications with modern tech:

Laravel PHP 8+ Vue.js React.js Flask Python MySQL

Response time: under 24 hours โ€ข 100% confidential

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts