Partial page updates
Use partials to fetch a new page while replacing, appending, or prepending only named regions of the current document.
Mark a region and opt in to client navigation
Wrap the content to update in a Partial with a stable, unique name. Add data-hum-client-nav to an ancestor to intercept same-origin links and GET/POST forms inside it. Matching partials from the fetched page are applied without replacing the surrounding shell.
// routes/docs/partials/[[topic]].tsx — the first demo on this page
import { Partial } from "@humjs/core/client";
export default function PartialsPage({ url }) {
const topic = url.searchParams.get("topic") ?? "start";
return (
<div data-hum-client-nav>
<a href="/docs/partials/handlers" data-hum-partial="/docs/partials?topic=handlers">
Handlers
</a>
<Partial name="topic">
<p>{topics[topic]}</p>
</Partial>
</div>
);
}Keep the partial name consistent between responses. A normal full-page navigation still works when client navigation is not enabled.
Links and forms
Links inside an opted-in region navigate without a full reload. GET and POST forms are also supported; other form methods use normal browser submission. Add data-hum-partial to a link or form when you want to fetch a different URL than the one used for the visible navigation or form action.
// the link navigates to /docs/partials/handlers, but the fetch
// that updates the "topic" region asks for /docs/partials?topic=handlers
<a href="/docs/partials/handlers" data-hum-partial="/docs/partials?topic=handlers">
Handlers
</a>data-hum-client-nav={false} to opt out inside an enabled ancestor.View Transitions
Hum automatically uses the browser’s View Transitions API for client-side partial navigations when it is available. The transition covers the partial DOM updates and current-link state; no extra attribute or JavaScript setup is needed. Browsers without the API apply the updates normally. You can customize the animation with the standard View Transition pseudo-elements, for example:
::view-transition-old(root) {
animation: 180ms ease-out both fade-out;
}
::view-transition-new(root) {
animation: 180ms ease-out both fade-in;
}
@keyframes fade-out {
to { opacity: 0; }
}
@keyframes fade-in {
from { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
::view-transition-group(root),
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0s;
}
}Choose how new content is applied
The default mode replaces the region’s contents. Use append or prepend for feeds and lists; the existing DOM children are retained and new content is added at the selected edge. The second demo below does both: the list region appends the next batch while the region holding the form is replaced, so the button can move from “Load more” to the end of the list.
replaceReplace the current region contents (default).
appendAdd the fetched content after existing children.
prependAdd the fetched content before existing children.
// handlers: what the "Load more" form below submits to
export const handlers = define.handlers({
GET: () => page({ hasMore: true }),
POST: async (c) => {
const form = await c.req.formData();
const batch = Number(form.get("batch"));
const start = batch * LOAD_MORE_BATCH_SIZE;
return page({
batch,
hasMore: start + LOAD_MORE_BATCH_SIZE < LOAD_MORE_ITEMS.length,
});
},
});
// one region appends the new items, the other replaces the form
<div data-hum-client-nav>
<Partial name="load-more-items" mode={batch === undefined ? "replace" : "append"}>
{itemsForBatch.map((item) => <li>{item}</li>)}
</Partial>
<Partial name="load-more-control">
<form method="post" action="/docs/partials">
<input type="hidden" name="batch" value={nextBatch} />
<button>Load more</button>
</form>
</Partial>
</div>If a response does not contain any partial regions, Hum falls back to a full navigation. The URL and browser history stay in sync, and Back / Forward restores the prior page state.
Try it
Update one region
These links change the URL and replace only the matching partial. The surrounding panel stays in place.
Current topic
Pick a topic to update just this panel.
Append mode demo
Load more items
Submit the form to fetch the next two items. The list appends them; only the form area is replaced.
- 1Append new content without replacing what is already on screen.
- 2Keep the request and rendering on the server.
Previous: Route handlers →