How the infinite feed works
Each page the server returns ends with a sentinel: a list item carrying kj-get="/api/page.php?p=N+1", kj-trigger="revealed" and kj-swap="outerHTML". When it scrolls into view, it replaces itself with the next page — which ends with the next sentinel. The last page simply doesn't include one.
revealed uses an IntersectionObserver, fires once, and works inside scrollable containers. Use kj-trigger="load" for content that should arrive right after the page renders, such as a slow widget you don't want to block the page on.
- Loading…
Comments with kj-trigger="load"
- Loading comments…
Zero JavaScript. page.php renders six pages of four posts; each page ends with the sentinel for the next.
View the source for this demo
<div class="feed-box" tabindex="0" role="region" aria-label="Infinite feed, scroll to load more">
<ul class="list-plain" id="feed">
<li kj-get="/api/page.php?p=1" kj-trigger="revealed" kj-swap="outerHTML">Loading…</li>
</ul>
</div>
<h4 style="margin:22px 0 8px">Comments with <code>kj-trigger="load"</code></h4>
<ul class="list-plain" kj-get="/api/comments.html" kj-trigger="load"><li>Loading comments…</li></ul>More examples
The sentinel the server appends
<li kj-get="/api/page.php?p=3" kj-trigger="revealed" kj-swap="outerHTML">
Loading page 3…
</li>API
When to fire: any DOM event (with optional debounce), load (immediately), revealed (when scrolled into view, via IntersectionObserver), or every Ns (polling).
How the response is inserted into the target. outerHTML replaces the target entirely; the four position values insert adjacent to it; none makes the request without touching the DOM.
Migrating
hx-trigger="revealed".Related features
Targets & swaps
Control exactly where server HTML lands with kj-target and how it is inserted with kj-swap — innerHTML, outerHTML, beforebegin, afterbegin, beforeend, afterend, textContent or none..
Open →HyperPolling
Keep a panel fresh with kj-trigger="every Ns".
Open →HyperTriggers & debouncing
Choose when requests fire with kj-trigger: any DOM event plus a debounce like keyup delay:400ms — live search and server-side inline validation without JavaScript..
Open →