Skip to content
HTMX Laravel Tips and Tricks Laravel

HTMX vs Livewire in Laravel: Same Feature Built Both Ways

Raheel Shan

Raheel Shan

November 13th, 2026 · 3 min read

HTMX vs Livewire in Laravel: Same Feature Built Both Ways

HTMX and Livewire both let you build dynamic Laravel pages without writing a JavaScript app, but they work differently. HTMX is a small library: your routes return HTML fragments and HTMX swaps them into the page. Livewire is a full-stack framework: you write PHP component classes with state, and Livewire keeps that state in sync with the browser. Pick HTMX when you want plain Blade and full control. Pick Livewire when you want reactive components with less wiring. This post builds the same live search with both so you can compare the code.

Quick answer

  1. HTMX: attributes on HTML, routes that return Blade partials, no component classes, no state on the server.
  2. Livewire: PHP component classes with public properties that stay in sync with the page.
  3. Small, mostly read-only interactions favour HTMX. Forms with lots of state and validation favour Livewire.
  4. You do not have to choose for the whole app. Pick per feature, and avoid mixing both on the same element.

The feature: live product search

We want a text box that filters a list of products as you type. No page reload, results from the database.

Version 1: HTMX

The page is normal Blade. The input tells HTMX what to request and where to put the answer.

<input type="search" name="q" placeholder="Search products"
       hx-get="/products/search"
       hx-trigger="input changed delay:300ms"
       hx-target="#results">

<div id="results">
    @include('products.partials.results', ['products' => $products])
</div>

The route returns only the part that changes:

Route::get('/products/search', function (Request $request) {
    $products = Product::where('name', 'like', '%'.$request->query('q').'%')
        ->limit(10)
        ->get();

    return view('products.partials.results', compact('products'));
});

The partial is a plain Blade file:

@forelse ($products as $product)
    <div>{{ $product->name }}</div>
@empty
    <p>No products found.</p>
@endforelse

That is all. There is no component class and no server-side state. Each keystroke is an ordinary GET request that returns HTML. For a POST request you also send the CSRF token, for example with hx-headers='{"X-CSRF-TOKEN": "{{ csrf_token() }}"}' on the body tag. To go deeper, see Laravel with HTMX: Use Blade Partials as Your API.

Version 2: Livewire

With Livewire the same feature is a component: a PHP class and a view.

<?php

namespace App\Livewire;

use App\Models\Product;
use Livewire\Component;

class ProductSearch extends Component
{
    public string $search = '';

    public function render()
    {
        return view('livewire.product-search', [
            'products' => Product::where('name', 'like', '%'.$this->search.'%')
                ->limit(10)
                ->get(),
        ]);
    }
}
<div>
    <input type="search" wire:model.live.debounce.300ms="search" placeholder="Search products">

    @forelse ($products as $product)
        <div>{{ $product->name }}</div>
    @empty
        <p>No products found.</p>
    @endforelse
</div>

You place it on a page with <livewire:product-search />. There is no route and no partial: the component owns the state ($search) and re-renders itself when it changes. To learn what happens on each keystroke, read how Livewire works under the hood.

What differs between them

  • State: HTMX has no server state. Every request carries what it needs in the URL or form. Livewire keeps component state and sends it back and forth with each update.
  • Where the logic lives: in HTMX it lives in routes and controllers you already know. In Livewire it lives in component classes with lifecycle methods.
  • Code size: simple interactions are a few attributes in HTMX. Livewire has more files, but stateful features (multi-step forms, validation, file uploads) are less code than wiring them by hand.
  • JavaScript you ship: HTMX is one small script. Livewire 3 loads its own JavaScript, which includes Alpine.
  • Learning curve: HTMX is a handful of attributes. Livewire has components, properties, events and lifecycle hooks to learn.
  • Page weight on updates: both send HTML over the wire, but Livewire also sends a state snapshot with each request.

When to choose HTMX

  • You already write Blade and want to add interactivity without a new layer.
  • Pages are mostly read-only: search, filters, pagination, "load more", partial refreshes.
  • You want your server responses to be ordinary HTML you can test and cache like any other route.
  • You do not need shared state between many parts of a page.

For more on keeping partials tidy, see the Blade Partial API pattern for fetching data.

When to choose Livewire

  • A form has many fields, validation rules and conditional sections, and you want the state held in one PHP class.
  • You need file uploads with previews, real-time validation or wizards.
  • Several parts of the page must react to the same state, and you want events between components.
  • Your team prefers writing PHP over wiring HTML attributes.

When to choose neither

If the page needs heavy client-side interaction, such as drag and drop boards, rich editors or offline behaviour, a JavaScript framework fits better. If you want to see how far plain Laravel goes, read Skip Livewire? Why Laravel Blade + AQC + Alpine Might Be All You Need and Livewire without Livewire, Inertia without Inertia, GraphQL without GraphQL.

Can you use both?

Yes, in one application, and even on one page, as long as they own different parts. Do not put HTMX attributes on elements that Livewire manages, because Livewire re-renders those elements and can overwrite what HTMX swapped in.

FAQ

Is HTMX better than Livewire? Neither is better in general. HTMX is lighter and closer to plain Blade. Livewire gives you components and state out of the box. The right one depends on how stateful the feature is.

Is HTMX faster than Livewire? HTMX sends less on each request because it carries no component state, but real speed depends on your queries and the size of the HTML you return. Measure your own page before choosing for speed.

Do I need Alpine.js with Livewire? Livewire 3 includes Alpine, so you can use Alpine directives without installing it. HTMX does not need Alpine.

Can HTMX replace Livewire? For many read-heavy interactions, yes. For stateful forms and real-time validation you would rebuild by hand what Livewire gives you.

Which is better for SEO? Both render the first page on the server, so search engines see real HTML. Content that only appears after a user action is not crawled by either.

Build the interactive parts without React

Live search, tables and forms on server-rendered HTML, with HTMX or jsRibbon and no build step.

Bring the page you want to make interactive and we build the first piece together in 60 minutes.

Book an HTMX and jsRibbon call

Found this useful?

Support the work that goes into these posts.

Support
Comments


Comment created and will be displayed once approved.