aRustyDev / aRustyDev/mdbook-htmx
docs(adr): ADR-0004: hx-boost as Primary Navigation Strategy
- Dominant language
- Rust
- Stars
- 0
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
# ADR-0004: hx-boost as Primary Navigation Strategy
## Status
Accepted
## Context
HTMX provides multiple ways to enable AJAX-powered navigation:
1. **Explicit attributes** - Add `hx-get`, `hx-target`, `hx-swap` to each link
2. **hx-boost** - Single attribute on parent enables AJAX for all descendant links
3. **Hybrid** - Boost for general nav, explicit for special cases
The skeleton files showed both patterns. We need a consistent default.
## Decision Drivers
1. **Progressive Enhancement** - Must work without JavaScript
2. **Simplicity** - Minimize HTMX attribute clutter
3. **Consistency** - Predictable behavior across all links
4. **Escape Hatch** - Allow opting out for specific links
## Options Considered
### Option A: Explicit Attributes Everywhere
Every link specifies full HTMX behavior:
```html
Chapter 1
```
**Pros:**
- Maximum control per-link
- Clear what each link does
**Cons:**
- Verbose, repetitive
- Easy to forget attributes
- Template maintenance burden
- Duplicates href in hx-get
### Option B: hx-boost on Body (Recommended)
Single attribute enables AJAX for all links:
```html
```
**Pros:**
- DRY - single declaration
- All links work with and without JS
- Uses standard `href` (no duplication)
- Consistent behavior
- Progressive enhancement built-in
**Cons:**
- Less granular control
- Must opt-out for external links
- Inherited behavior can surprise
### Option C: hx-boost on Nav Only
Boost only navigation elements:
```html
```
**Pros:**
- Navigation is boosted
- Content links behave normally
**Cons:**
- In-content cross-references still cause full reload
- Inconsistent UX
## Decision
**Use `hx-boost="true"` on `` as default, with escape hatches.**
Configuration:
```toml
[output.htmx]
boost = true # Enable body-level boost
target = "#content" # Default target for boosted links
swap-strategy = "innerHTML"
push-url = true
```
Generated layout:
```html
```
### Escape Hatches
1. **Disable boost on specific link:**
```html
External Link
```
2. **External links auto-excluded:**
HTMX only boosts same-origin links by default.
3. **Download links:**
```html
Download PDF
```
## Rationale
From HTMX documentation and community discussion:
> "hx-boost is actually the most important feature of htmx" - Dev.to article
>
> The first decision we need to make is to eliminate or at least minimize
> the use of hx-get, hx-post, etc. attributes and use boosting only.
Benefits:
1. **Progressive enhancement** - Links work without JS (standard href)
2. **URL integrity** - Browser URL always matches content
3. **Accessibility** - Screen readers see standard links
4. **Simplicity** - One attribute vs many
## Implementation
```rust
fn render_layout(&self, config: &HtmxConfig) -> String {
let mut attrs = vec![];
if config.boost {
attrs.push("hx-boost=\"true\"");
}
if let Some(target) = &config.target {
attrs.push(&format!("hx-target=\"{}\"", target));
}
if let Some(swap) = &config.swap_strategy {
attrs.push(&format!("hx-swap=\"{}\"", swap));
}
if config.push_url {
attrs.push("hx-push-url=\"true\"");
}
format!("", attrs.join(" "))
}
```
## Consequences
### Positive
- Clean, minimal templates
- Consistent navigation behavior
- Works without JavaScript
- Standard links for SEO
### Negative
- All same-origin links boosted (may surprise)
- External links need `target="_blank"` or `hx-boost="false"`
### Mitigation
- Document boost behavior prominently
- Auto-add `hx-boost="false"` to `target="_blank"` links
- Provide `no-boost` CSS class for opt-out
## References
- [HTMX hx-boost Documentation](https://htmx.org/attributes/hx-boost/)
- [Why hx-boost is the most important feature](https://dev.to/yawaramin/why-hx-boost-is-actually-the-most-important-feature-of-htmx-3nc0)
- [Hypermedia Systems - Boosting](https://hypermedia.systems/)
Contributor guide
Assessment
This issue has not been assessed yet.