Claude Skills Guide

Claude Code Laravel Livewire Real-Time Workflow Tutorial

Building real-time web applications has never been easier than with Laravel Livewire. When combined with Claude Code’s AI-assisted development capabilities, you can rapidly create interactive, real-time features without writing extensive JavaScript. This tutorial walks you through building a complete real-time workflow using Laravel Livewire and Claude Code.

Setting Up Your Laravel Livewire Project

Before creating real-time features, ensure your development environment is properly configured. Claude Code can help you set up a Laravel project with Livewire in minutes.

First, create a CLAUDE.md file in your project root to establish the context:

This is a Laravel 11+ application with Livewire 3.x for real-time features.
- Using Alpine.js for client-side interactions
- MySQL database with Laravel's query builder
- Laravel Breeze for authentication

Initialize your Laravel project and install Livewire:

composer create-project laravel/laravel real-time-app
cd real-time-app
composer require livewire/livewire
npm install && npm run dev

Creating Your First Real-Time Component

The foundation of any Livewire application is the component. Let’s create a real-time notification system that demonstrates Livewire’s reactive capabilities.

Ask Claude Code to generate the component structure:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Notification;

class NotificationPanel extends Component
{
    public $notifications = [];
    public $unreadCount = 0;

    protected $listeners = ['refreshNotifications' => 'loadNotifications'];

    public function mount()
    {
        $this->loadNotifications();
    }

    public function loadNotifications()
    {
        $this->notifications = auth()->user()
            ->notifications()
            ->latest()
            ->take(10)
            ->get();

        $this->unreadCount = auth()->user()
            ->unreadNotifications()
            ->count();
    }

    public function markAsRead($notificationId)
    {
        $notification = Notification::find($notificationId);
        $notification->markAsRead();
        $this->loadNotifications();
    }

    public function render()
    {
        return view('livewire.notification-panel');
    }
}

Implementing Real-Time Updates with polling

Livewire provides multiple approaches for real-time updates. The simplest is polling, which periodically refreshes the component data.

Add the polling attribute to your component’s root element in the Blade template:

<div wire:poll.5s="loadNotifications">
    <div class="notification-header">
        <h3>Notifications</h3>
        @if($unreadCount > 0)
            <span class="badge">{{ $unreadCount }} unread</span>
        @endif
    </div>

    <ul class="notification-list">
        @foreach($notifications as $notification)
            <li class="{{ $notification->read_at ? 'read' : 'unread' }}">
                <p>{{ $notification->data['message'] }}</p>
                <small>{{ $notification->created_at->diffForHumans() }}</small>
                @if(!$notification->read_at)
                    <button wire:click="markAsRead('{{ $notification->id }}')">
                        Mark as Read
                    </button>
                @endif
            </li>
        @endforeach
    </ul>
</div>

The wire:poll.5s directive automatically refreshes the component every 5 seconds, creating a real-time feel without WebSocket complexity.

Using Laravel Echo for True Real-Time Events

For production applications requiring instant updates, integrate Laravel Echo with Pusher or a WebSocket server. Claude Code can help you configure this setup.

Install the required packages:

composer require pusher/pusher-php-server
npm install laravel-echo pusher-js

Configure your broadcasting in config/broadcasting.php:

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'useTLS' => true,
    ],
],

Create a broadcast event for notifications:

<?php

namespace App\Events;

use App\Models\Notification;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class NotificationSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $notification;
    public $userId;

    public function __construct(Notification $notification)
    {
        $this->notification = $notification;
        $this->userId = $notification->notifiable_id;
    }

    public function broadcastOn()
    {
        return new Channel('user.' . $this->userId);
    }

    public function broadcastWith()
    {
        return [
            'id' => $this->notification->id,
            'message' => $this->notification->data['message'],
            'created_at' => $this->notification->created_at->toIso8601String(),
        ];
    }
}

Update your Livewire component to listen for these events:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Notification;

class NotificationPanel extends Component
{
    public $notifications = [];
    public $unreadCount = 0;

    protected $listeners = [
        'echo:user.{auth()->id()},NotificationSent' => 'handleNewNotification',
    ];

    public function mount()
    {
        $this->loadNotifications();
    }

    public function loadNotifications()
    {
        $this->notifications = auth()->user()
            ->notifications()
            ->latest()
            ->take(10)
            ->get();

        $this->unreadCount = auth()->user()
            ->unreadNotifications()
            ->count();
    }

    public function handleNewNotification($data)
    {
        $this->loadNotifications();
        $this->dispatch('notification-received');
    }

    public function render()
    {
        return view('livewire.notification-panel');
    }
}

Initialize Echo in your JavaScript bootstrap file:

import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true
});

Building a Real-Time Workflow: Task Management Example

Let’s combine these concepts into a practical task management workflow. This example demonstrates collaborative real-time updates across multiple users.

Create the task component:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Task;
use App\Events\TaskUpdated;

class TaskBoard extends Component
{
    public $tasks = [];
    public $newTaskTitle = '';

    protected $rules = [
        'newTaskTitle' => 'required|min:3|max:255',
    ];

    protected $listeners = [
        'echo:tasks,TaskUpdated' => 'refreshTasks',
    ];

    public function mount()
    {
        $this->loadTasks();
    }

    public function loadTasks()
    {
        $this->tasks = Task::with('assignee')->get()->groupBy('status');
    }

    public function createTask()
    {
        $this->validate();

        $task = Task::create([
            'title' => $this->newTaskTitle,
            'status' => 'todo',
            'user_id' => auth()->id(),
        ]);

        event(new TaskUpdated($task));
        $this->newTaskTitle = '';
        $this->loadTasks();
    }

    public function updateTaskStatus($taskId, $newStatus)
    {
        $task = Task::findOrFail($taskId);
        $task->update(['status' => $newStatus]);

        event(new TaskUpdated($task));
        $this->loadTasks();
    }

    public function render()
    {
        return view('livewire.task-board');
    }
}

Create the corresponding Blade view with drag-and-drop functionality:

<div>
    <div class="task-input">
        <input 
            type="text" 
            wire:model="newTaskTitle" 
            placeholder="Enter new task..."
            wire:keydown.enter="createTask"
        >
        <button wire:click="createTask">Add Task</button>
    </div>

    <div class="task-board">
        @foreach(['todo', 'in_progress', 'done'] as $status)
            <div class="task-column">
                <h3>{{ ucfirst(str_replace('_', ' ', $status)) }}</h3>
                
                @foreach($tasks[$status] ?? [] as $task)
                    <div class="task-card" draggable="true">
                        <h4>{{ $task->title }}</h4>
                        @if($task->assignee)
                            <span class="assignee">{{ $task->assignee->name }}</span>
                        @endif
                        
                        <select 
                            wire:change="updateTaskStatus('{{ $task->id }}', $event.target.value)"
                            value="{{ $task->status }}"
                        >
                            <option value="todo">To Do</option>
                            <option value="in_progress">In Progress</option>
                            <option value="done">Done</option>
                        </select>
                    </div>
                @endforeach
            </div>
        @endforeach
    </div>
</div>

Best Practices for Livewire Real-Time Development

When building real-time applications with Livewire, follow these best practices to ensure optimal performance and user experience.

Optimize polling intervals: Balance between responsiveness and server load. Use shorter intervals (2-3 seconds) for critical updates and longer intervals (30+ seconds) for less critical data.

Implement proper error handling: Always wrap real-time operations in try-catch blocks and provide user feedback when updates fail.

Use lazy loading for large datasets: For components with significant data, implement pagination or lazy loading to reduce initial page load time.

Secure your real-time channels: Implement proper authentication and authorization for private channels to prevent unauthorized access to sensitive real-time data.

Conclusion

Combining Laravel Livewire with Claude Code creates a powerful workflow for building real-time applications. The AI assistant can help you generate components, debug issues, and optimize performance while you focus on business logic. Start with simple polling-based updates and gradually migrate to full WebSocket implementations as your application scales.

The key to success is understanding when to use each real-time approach—polling for simplicity, WebSockets for instant updates, and proper architectural planning for scalability. With Claude Code guiding your development, you’ll build robust real-time features faster than ever before.

Built by theluckystrike — More at zovo.one