You can always make the server-side render partials based on a request header.

https://github.com/dsego/ssr-playground/blob/main/src/server...

That is what I did. I was using Astro which has full support for partial HTML via the router

I think I understand now, even the partial required submitting everything to the server, which can be skipped if you can have interactivity without unnecessary requests.

Exactly. The partial response was 100kb-200kb of HTML + the backend query time. Of course, depending on your filters. But a large chunk of that was just sending down the form on the left side, which I already had on page load, so that penalty was real.

It was only the right side results of the experience that needed to be refetched when the form changed.

But in HTMX, you are expected to just send the whole dang thing back for every change. Makes sense for a like-button, a dialog, or even a classic form submission.

My refactor cut the HTML response by about 70kb and that made a big difference. The form became fully static and I had a simple Alpine data component that would just sync that state with the URL. Still used a GET on the form and still used the same partial endpoint. Just way less HTML to wait for.

Unless there's a material change to the form, why not just update the changed parts?

I'd also question architectural decisions if you need to send 100kb+ of html down the wire for a partial.

The cards contained a large data table outlining a bunch of attributes across many columns and rows. Not an ideal design but the client wanted those stats included in the card so they were visible right away.

We could have paginated the results, but the client didn’t want that either because you are just promoting the results that happen to land on the first page. You also can’t just CTRL-F and find things that way.

Now, those could have been loaded in dynamically. That isn’t a free solution either though. It means adding a new endpoint, with a new partial, another request-response round trip, plus the error handling in case it fails, etc. etc.

I just ended up being more practical to go with a reactive JS form component to reduce the HTML being sent back and forth.

Why are you expected to send down the whole thing? Maybe I’m missing something, but when you send the request from the form the response is just a partial of the results on the right hand side, using hx-target to specify some div instead of replacing the form. Form just stays there?

To sync the form state based on the current selections in the form. This is often called facets. The form contained many options and as you filtered those options would change. So you need a way to update the form too. Hence, compute the full thing on the server (the form state, the options within the fields, and the results) then send it all back.

Thats not on htmx to decide what html to resend that's your engineering work...

Except you don't. Use hx-vals, hx-include, or even hx-headers to pull in additional data into the request that's outside of the immediate form/component.