Requests and responses

Return the updated HTML

Let the server render the changed state and return the exact fragment the target needs.

Return the representation the target needs after the server has decided the new state. HTMX does not merge partial updates for you. Whatever HTML you send becomes the new content for that target.

For a task list target, a successful create can return the complete list:

<ul id="task-list">
  <li>Send invoice</li>
  <li>Book train</li>
</ul>

Returning only the new row is smaller, but returning the full list also keeps sorting, totals, empty states, and permissions consistent. Choose the smallest fragment that contains the complete changed state. If three things on screen must change together, return one fragment that covers all three.

Validation is also HTML. If a form targets itself with outerHTML, return the form with safe values and field-specific messages:

<form id="new-task" action="/tasks" method="post" hx-post="/tasks"
  hx-target="this" hx-swap="outerHTML">
  <p class="error">Enter a title.</p>
  <!-- labeled controls with the safe submitted values -->
</form>

Render the fragment through the same server templates used by full pages. Do not duplicate escaping and presentation rules in client JavaScript. One template path means one escaping policy, and you avoid the classic bug where the full page escapes user input but the HTMX partial does not.

Test the endpoint directly. Hit the route with curl or your browser and read the raw response. It should be valid in the target’s HTML context and should never expose private fields merely because only part of the page is returned. A fragment is still a server response with the same auth rules as a full document.

When the target is a table body or list, return only the rows that belong inside that container. Returning a wrapping <table> into a <tbody> target produces invalid DOM even when the server template looks fine in isolation.

Try this on your own project: fetch one HTMX endpoint outside the page and confirm the HTML is safe to drop into the target without extra client cleanup.

Lesson completed