Data and rendering
Stream useful loading UI
Use loading.tsx and focused Suspense boundaries so slow data does not leave navigation without feedback.
8 minute lesson
Server rendering can stream route output. A loading.tsx file gives the route segment an immediate fallback while its page is prepared.
Use a route-level loading file for a broad page skeleton. Use <Suspense> closer to a slow component when the rest of the page can render first. Make the fallback resemble the space it will replace so the page does not jump when content arrives.
The route fallback is prefetched during navigation and wraps the page below its shared layout. This lets navigation feel immediate while the server finishes the segment. On a direct request, streaming still depends on the server and hosting path delivering chunks rather than buffering the entire response.
Prefer the narrowest meaningful boundary. If only the recent-notes list is slow, keeping the heading and create button outside Suspense leaves useful work available. Several tiny boundaries can create visual noise and a waterfall, so split by user-visible units rather than by every asynchronous function.
// app/notes/loading.tsx
export default function Loading() {
return <p aria-live="polite">Loading notes…</p>
}
Add an intentional delay, create a route loading file, and navigate through a Link. Then replace the broad fallback with Suspense around only the slow list. Compare client navigation and a direct load, including the layout space reserved by each fallback.
Lesson completed