htmx

HTMX hx-replace-url Causes Partial HTML on Page Refresh — How to Serve Full Pages?


Question context:

I'm using HTMX to dynamically swap content in my single-page layout. Specifically, I have a navigation bar with buttons like:

    <button 
       hx-get="/home" 
       hx-target="#content" 
       hx-replace-url="/"
    >
      Home
    </button>
    <button 
       hx-get="/about" 
       hx-target="#content" 
       hx-replace-url="/about"
    >
      About
    </button>

and I have a <main> element set up to fetch the initial content on page load:

    <main id="content" hx-get="/home" hx-trigger="load">
    </main>

When I click on a navigation button, the content inside the <main> element is replaced (which is exactly what I want). I also use hx-replace-url="/about" so that the browser’s URL updates to /about.

The Problem: If I refresh the page after the URL has changed to /about, my server (written in Go) only serves the partial HTML intended for the <main> section. As a result, the rest of the page is missing, because the server thinks it’s only supposed to provide the “content” portion.

My Questions:

  1. How should I handle requests to routes like /about so that the user gets the full page (HTML head, nav bar, etc.) instead of just the partial?
    • One idea is to serve index.html for both "/" and "/about" and somehow dynamically set the hx-get depending on the route, for /about it would be something like <main id="content" hx-get="/about" hx-trigger="load">. But I’m not entirely sure how to implement that cleanly on the server side.
  2. Is this the recommended approach for HTMX-driven single-page applications, or is there another “best practice” pattern?

Any guidance on the best way to make this work—so that direct hits to /about (or any other route) always return a full page and not just a partial—would be greatly appreciated. Let me know if I should provide more code or clarification!


Solution

  • @BenderBoy has a good point there. I am not familiar with Go. But on your endpoints you should have access to request and response. Check the "HX-Request" header in the request.

    if (headers['hx-request'] == true) {
      return partial_page;
    } else {
      return full_page;
    }
    

    Depends on your UI framework. But with templating your partial_page would be included in your full_page.