My experiment with HTMX and Astro
Tags: astro, htmx
Published: 2024-06-20 16:44:25

I share my first experience with the [htmx](https://htmx.org) library. I created a simple site ([https://tubog-showcase.ru](https://tubog-showcase.ru)) consisting of a home page with an initial set of apartment cards and 5 buttons that display apartments filtered by number of rooms.

Stack: Astro + HTMX + Tailwind

Implementation is very simple:
``` ts
// src/pages/index.astro

<form
  id='filter-form'
  hx-trigger='change'
  hx-post='/api/cases'
  hx-target='#serch-results'
  hx-swap='innerHTML'
  hx-indicator='#loading'
>
    ...
    <label>
      <input
	type='radio'
	name='rooms'
	value='1'
        class='hidden peer'
      />
      <div class='hover:border-slate-500 peer-checked:opacity-100 peer-checked:shadow-xl peer-checked:border-slate-400'>
	1 комната
      </div>
   </label>

    ...
</form>

<div id='loading'>
  Loading...
</div>

<div id='serch-results'></div>
```
Соответственно, при выборе нового варианта фильтра, по адресу `/api/cases` выполняется POST-запрос с данными о выбранном варианте.

Индикатором рабты запроса является `<div id='loading'>`. Результат (готовый HTML) выводится внутри `<div id='serch-results'></div>`.
На стороне `api` код выглядит примерно так:
``` ts
// src/pages/api/cases.ts

export const POST: APIRoute = async ({ request }) => {

   const formData = await request.formData()
   const rooms = formData.get('rooms')

   // Получаем список комнат на основе rooms
    
   return new Response(
     `
      <div>
         ${filteredFlats.map(flat => ` {some flat html here} `)}
      </div> 
     `,
     {
        status: 200,
	headers: {
	   'Content-Type': 'text/html+htmx',
	},
      }
   )
```
And that's it.

## First Impressions

This approach to create web applications is rather not for me. Implementing with the same React seems simpler and with more potential for improvement. What I didn't like:

- The blurring of application logic. The backend doesn't just return data, but also deals with frontend tasks;
- The need to harmonize the layout on the client side and the server side (in our case it's the default display of maps and search results output).

Yes, I made it a bit more difficult for myself by not using page partials, but their use within the same Astro in conjunction with HTMX seemed a bit too far-fetched to me.

Still, I have a number of tasks where HTMX is a perfect fit: I have several old static sites and sites implemented on CMS like WordPress. For these, the will to add interactivity (especially using page partials) is a great prospect. For sites written in Next or Astro, I haven't seen a use for it yet.

## P.S. An unexpected problem

In this project I've connected View Transitions and it seems to break the HTMX library. As soon as you make a transition between pages, the site ends up static. Fortunately, I came across this [article](https://flaviocopes.com/htmx-and-astro-view-transitions/) which describes the solution: you need to add the following script to the page with HTXM code.
``` ts
// src/pages/index.astro

<script>
  document.addEventListener('astro:page-load', () => {
    const contentElement = document.getElementById('filter-form')
    if (contentElement) { 
      htmx.process(document.body)
    }
  })
</script>
```