HTMX con Laravel 13: interactividad sin JavaScript usando atributos HTML
HTMX pesa unos 14 kB, no tiene dependencias y convierte cualquier botón o enlace de Blade en una petición AJAX con solo añadir atributos como hx-get: interactividad sin JavaScript que Laravel 13 responde con un simple parcial HTML. En esta guía montas HTMX en un proyecto Laravel 13 y construyes búsqueda en vivo, tablas ordenables y acciones sin recarga, paso a paso.
Qué es HTMX y por qué importa en 2026
HTMX es una librería JavaScript que devuelve la interactividad al HTML: con atributos declarativos da acceso a peticiones AJAX, transiciones CSS, WebSockets y Server-Sent Events sin escribir una línea de JavaScript por tu cuenta. El navegador hace la petición, el servidor devuelve HTML y HTMX coloca ese fragmento donde le digas. Para un desarrollador Laravel, eso significa que el backend sigue siendo la única fuente de verdad: no duplicas lógica en un cliente JavaScript ni mantienes un estado sincronizado entre dos mundos.
La filosofía hypermedia frente a las SPAs
Las aplicaciones de una sola página (SPA) mueven la lógica al cliente: el servidor entrega JSON y un framework de JavaScript construye la interfaz. HTMX defiende el enfoque contrario, el hypermedia: el servidor sigue devolviendo HTML, y las interacciones son peticiones normales que reemplazan fragmentos de la página. Es la misma arquitectura de la web clásica, pero sin la recarga completa. El resultado es menos código, menos estado que sincronizar y una curva de aprendizaje mínima si ya dominas Blade.
Qué ofrece HTMX 2 y qué traerá HTMX 4
HTMX 2.0.0 se publicó el 17 de junio de 2024: retiró el soporte de Internet Explorer, endureció algunos valores por defecto y mantuvo la mayor parte de la API central sin cambios. Desde entonces es la versión estable de referencia, con soporte para todo el ecosistema de atributos hx-*. La versión 4 está en beta activa con lanzamiento previsto para el verano de 2026: es una reescritura de la implementación sobre la API fetch() del navegador, lo que simplifica el código interno y mejora el manejo de peticiones. Para lo que vas a construir hoy, HTMX 2 es más que suficiente y perfectamente estable.
Instalar HTMX en un proyecto Laravel 13
Hay dos vías para incorporar HTMX a tu proyecto Laravel 13: el CDN oficial, ideal para prototipos y proyectos pequeños, o la integración con Vite, recomendada cuando ya usas el bundler de Laravel para el resto de tus assets.
Con CDN en minutos
La vía rápida es añadir la etiqueta script en la sección head de tu layout Blade:
<script src="https://unpkg.com/htmx.org@2"></script>Con esa única línea HTMX queda activo en toda la aplicación. Es la opción perfecta para probar la librería sin tocar la configuración de build. Para producción puedes apuntar a una versión concreta y usar el atributo integrity si quieres fijar el hash.
Con Vite y npm
Si prefieres gestionar HTMX como dependencia, instálalo con npm y decláralo en tu archivo de entrada de JavaScript:
npm install htmx.orgimport htmx from "htmx.org";
window.htmx = htmx;Con esto HTMX se empaqueta junto al resto de tu JavaScript y lo cargas con la directiva @vite de Blade. Esta vía te permite además combinarlo con Alpine.js si en algún momento necesitas un poco de comportamiento de cliente, algo habitual en proyectos reales.
Tu primera petición: hx-get, hx-target y hx-swap
El trío de atributos básico es hx-get, hx-target y hx-swap. El primero define la URL a la que se hace la petición, el segundo el elemento donde se coloca la respuesta y el tercero cómo se inserta. Un botón de recuento de visitas sería así:
<button hx-get="/posts/1/visitas" hx-target="#visitas" hx-swap="innerHTML">
Ver visitas
</button>
<span id="visitas">0</span>Cómo responder con un parcial desde el controlador
En el controlador decides qué devolver según el tipo de petición. Para una petición HTMX devuelves un parcial de Blade; para una petición normal, la vista completa:
public function visitas(Post $post)
{
if ($post->visitas < 100) {
// petición HTMX: solo el fragmento
return view('posts.parcial-visitas', compact('post'));
}
return view('posts.show', compact('post'));
}La cabecera HX-Request y las respuestas parciales
HTMX envía la cabecera HX-Request en todas sus peticiones, y la documentación oficial recomienda responder con parciales cuando está presente. En Laravel puedes comprobarla con el método header del request, o con el paquete helper mauricius/laravel-htmx, que añade utilidades como $request->isHtmxRequest() y atajos para responder a peticiones HTMX. Lo importante es el patrón: una sola ruta que sirve la vista completa o el fragmento según quién pregunte, lo que hace que tu aplicación siga funcionando sin JavaScript.
Búsqueda en vivo sin recargar la página
La búsqueda en vivo es el ejemplo clásico de HTMX en Laravel. Un campo de texto que consulta el servidor mientras escribes y muestra los resultados en una lista, sin recargar la página.
<input type="search" name="q"
hx-get="/buscar"
hx-trigger="input changed delay:300ms"
hx-target="#resultados"
hx-indicator="#buscando">
<div id="resultados"></div>
<div id="buscando" class="htmx-indicator">Buscando...</div>hx-trigger con debounce
El atributo hx-trigger con la sintaxis input changed delay:300ms lanza la petición 300 milisegundos después de que el usuario deje de escribir. Sin ese retardo, cada pulsación de tecla dispararía una consulta a la base de datos. El controlador recibe el término y devuelve el parcial con los resultados:
public function buscar(Request $request)
{
$posts = Post::where('title', 'like', "%{$request->q}%")->limit(10)->get();
return view('posts.resultados', compact('posts'));
}Indicador de carga con hx-indicator
El atributo hx-indicator apunta a un elemento que HTMX muestra automáticamente durante la petición. Para que funcione, ese elemento necesita la clase htmx-indicator, que lo oculta por defecto y lo hace visible cuando hay una petición en curso. Es una forma declarativa de dar feedback de carga sin gestionar estados de espera en JavaScript.
Tabla con ordenación y paginación con HTMX
Una tabla de posts con ordenación por columnas y paginación es otro caso donde HTMX brilla: reutilizas la misma vista parcial para todas las variantes de la tabla.
Ordenar columnas reutilizando la misma vista parcial
<table>
<thead>
<tr>
<th><a hx-get="/posts?orden=titulo" hx-target="#tabla-posts" hx-swap="outerHTML">Título</a></th>
<th><a hx-get="/posts?orden=fecha" hx-target="#tabla-posts" hx-swap="outerHTML">Fecha</a></th>
</tr>
</thead>
<tbody id="tabla-posts">
@include('posts.tabla-body', ['posts' => $posts])
</tbody>
</table>El controlador ordena la consulta según el parámetro recibido y devuelve el mismo parcial tabla-body. Como el destino es el propio tbody y el swap es outerHTML, la tabla se actualiza entera sin recargar. La clave está en que el parcial solo contiene las filas, de modo que sirve tanto para la carga inicial como para cada reordenación.
Paginación con hx-boost y pushState
Para la paginación, cada enlace de página usa hx-get apuntando a la misma tabla. Añadiendo hx-push-url="true" a la petición, HTMX actualiza la URL del navegador mediante la API history del navegador, de modo que el botón atrás funciona y la página es compartible. El enlace de la página siguiente se construye con los helpers de paginación de Laravel, pero en lugar de una recarga completa, solo se reemplaza el contenido de la tabla.
Acciones sin recarga: el botón de me gusta
Las acciones puntuales, como dar a me gusta a un post, son el caso más sencillo de HTMX: una petición POST que actualiza solo el contador afectado.
hx-post y la actualización selectiva del contador
<button hx-post="/posts/1/like" hx-target="#contador-like" hx-swap="innerHTML">
Me gusta
</button>
<span id="contador-like">{{ $post->likes }}</span>public function like(Post $post)
{
$post->increment('likes');
return $post->likes;
}El controlador incrementa el contador y devuelve el número, que HTMX coloca dentro del span. Fíjate en que la respuesta puede ser texto plano: HTMX no exige HTML si lo que quieres reemplazar es un valor simple. Con la cabecera HX-Request puedes además distinguir esta petición y evitar renderizar el layout completo.
HTMX 2 vs Livewire 4: cuándo elegir cada uno
Livewire 4 y HTMX resuelven problemas parecidos con filosofías distintas. Livewire ofrece componentes server-driven con estado: cada componente gestiona su propio ciclo de vida, propiedades y eventos, y el framework se encarga de las actualizaciones. HTMX es más primitivo: atributos que disparan peticiones y parciales que se insertan, sin estado ni componentes. Para interfaces pequeñas y medianas con interacciones puntuales, HTMX suele bastar y mantiene la arquitectura simple. Para UIs complejas con mucho estado compartido, formularios de varios pasos o paneles de administración densos, Livewire te ahorra bastante cableado. La buena noticia es que no son excluyentes: hay proyectos que usan Livewire para los paneles y HTMX para las zonas públicas.
Lo que viene: htmx 4 y la API fetch()
La versión 4 de htmx, en beta activa con lanzamiento previsto para el verano de 2026, reescribe la implementación desde cero sobre la API fetch() del navegador. Esto elimina dependencias internas, simplifica el manejo de errores y deja la puerta abierta a funciones modernas como streams de respuesta. Para quien empieza hoy con HTMX 2, la migración está pensada para ser mayormente transparente, ya que los atributos y la filosofía se mantienen. Si quieres probar lo nuevo, el sitio de la versión 4 documenta las diferencias, pero para producción la apuesta segura sigue siendo la rama 2.x estable.
Conclusión
HTMX con Laravel 13 te devuelve la interactividad sin cambiar tu arquitectura: atributos en Blade, parciales desde el controlador y cero JavaScript que mantener. Empieza por el CDN, construye la búsqueda en vivo y la tabla ordenable, y decide con criterio entre HTMX y Livewire según la complejidad de cada interfaz. Si te interesa el ecosistema de Laravel, en este blog también tienes la guía de Livewire 4 para comparar ambos caminos con detalle, y los artículos sobre Reverb y WebSockets para cuando necesites actualizaciones en tiempo real. Sigue leyendo el blog para más tutoriales prácticos de desarrollo web.