npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

htmx-ext-route-layout

v0.1.4

Published

Layout-aware boosted navigation for htmx

Readme

htmx-ext-route-layout

Why should you only be able to replace the entire screen?

-- htmx.org

route-layout extension makes htmx boosted navigation layout-aware. A layout route predicts which destination pages share the same layout, allowing matching links and forms to swap only the corresponding outlet instead of the whole page.

Quickstart

Add htmx and the extension scripts:

<script
  src="https://cdn.jsdelivr.net/npm/[email protected]/dist/htmx.min.js" 
  crossorigin="anonymous"
></script>
<script
  src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js" 
  crossorigin="anonymous"
></script>

Declare a layout route and an outlet:

<!-- /example/home -->
<body hx-ext="route-layout" hx-layout="/example/*">
  <h1>Example</h1>
  <main id="content" hx-outlet>
    <a href="/example/clicked">Click me</a>
  </main>
</body>

<!-- /example/clicked -->
<body hx-ext="route-layout" hx-layout="/example/*">
  <h1>Example</h1>
  <main id="content" hx-outlet>
    <p>You clicked me!</p>
    <a href="/">Exit</a>
  </main>
</body>

The /example/clicked link matches hx-layout="/example/*", so it is boosted automatically and swaps only #content. The / exit link does not match the layout route, so it performs a normal page load.

Installation

npm install htmx htmx-ext-route-layout

Attributes

hx-layout

Marks a container as a layout and defines its route scope with a URLPattern string, resolved relative to the current location.

Search parameters are matched separately from URLPattern. If the route pattern defines search parameters, the target URL must include matching values for those parameters. Additional parameters that are not defined in the pattern may be present or omitted. Pattern syntax is not supported for search parameter values, except for a single * wildcard. Prefix or suffix wildcards such as aaa* or *bbb are not supported.

Child links and forms whose href or action matches the layout route are automatically boosted with hx-boost and target the matching hx-outlet element. Set hx-boost="false" to disable this. Links and forms that point to a different origin are not boosted and will trigger a full page load.

Elements with hx-get, hx-post, hx-put, hx-patch, or hx-delete are also matched against the layout route. When they match, the extension applies the same default hx-target and hx-select values.

Every hx-layout should have a corresponding hx-outlet.

All pages that match the route must provide the same HTML layout, except for hx-outlet contents and the document head.

hx-outlet

Marks an element as the render target for a layout. It should have an id for reliable matching in the response document.

  • hx-outlet="<URLPattern>": Associates the outlet with hx-layout="<URLPattern>". The outlet can be anywhere in the document. If it has no ancestor hx-layout with the matching route, it acts as its own layout container.
  • hx-outlet (no value): Associates the outlet with the nearest ancestor hx-layout. It must be a descendant of an element with the hx-layout attribute.

When hx-layout and hx-outlet are on the same element, that element is used as its own outlet if hx-outlet has no value or has the same route as hx-layout. If the routes differ, the layout uses a matching descendant outlet instead.

hx-class:active

Used on <a> elements. When the link points to the current location, the class name specified by this attribute is added to the element. When the link no longer points to the current location, the class is removed.

URL hash fragments are ignored when comparing locations, and search parameters are compared without regard to order.

hx-class:active does not compute the initial active state. Mark it explicitly in the HTML. After a boosted swap, it updates links inside the affected layout while preserving active state outside it.

Headers

HX-Select

The extension sends the effective hx-select value as the HX-Select request header. Servers can use this header to return only the selected fragment instead of the full document.

The value can contain multiple comma-separated selectors. For boosted links and forms, htmx may include head as an additional selector, for example #content, head.

Examples

Layout with navigation outside the outlet

<body hx-ext="route-layout" hx-layout="/app/*">
  <nav>
    <a href="/app/dashboard" hx-class:active="active">Dashboard</a>
    <a href="/app/settings" hx-class:active="active">Settings</a>
  </nav>

  <main id="content" hx-outlet>
    <h1>Dashboard</h1>
    <p>Welcome back.</p>
  </main>
</body>

Layout as an outlet

<body hx-ext="route-layout" hx-outlet="/app/*">
  <nav>
    <a href="/app/dashboard" hx-class:active="active">Dashboard</a>
    <a href="/app/settings" hx-class:active="active">Settings</a>
  </nav>

  <main>
    <div id="content">
      <h1>Dashboard</h1>
      <p>Welcome back.</p>
    </div>
  </main>
</body>

Nested layouts

<body hx-ext="route-layout">
  <div hx-layout="/app/*">
    <nav>
      <a href="/app/dashboard" hx-class:active="active">Dashboard</a>
      <a href="/app/settings" hx-class:active="active">Settings</a>
    </nav>

    <div
      id="app-content"
      hx-outlet="/app/*"
      hx-layout="/app/settings/*"
    >
      <a href="/app/settings/account" hx-class:active="active">Account</a>
      <a href="/app/settings/privacy" hx-class:active="active">Privacy</a>

      <div id="settings-content" hx-outlet>
        <h1>Account</h1>
        <p>Update your account settings.</p>
      </div>
    </div>
  </div>
</body>

For nested layouts, the innermost matching layout takes priority. In this example, settings links target #settings-content instead of the outer #app-content outlet.

Note

hx-layout overrides the default values of these attributes on matching child elements:

| Attribute | htmx default | hx-layout default | |---|---|---| | hx-target | this | outlet | | hx-select | entire response document | same as hx-target |

Elements outside hx-layout keep the htmx defaults.

Set hx-target explicitly to bypass the outlet default:

<a href="/app/modal" hx-target="this">Open in modal</a>

Use hx-select="*" to request the full document instead of selecting only the corresponding outlet:

<a href="/app/dashboard" hx-select="*">Full page</a>

Use hx-target="outlet" as an explicit alias for the outlet selector (same as omitting hx-target):

<a href="/app/dashboard" hx-target="outlet">Dashboard</a>

License

MIT