This episode covers rendering in SvelteKit: SSR fundamentals and rendering modes, static site generation and incremental prerendering, streaming and partial hydration, plus when to use SSR versus SSG.

One of SvelteKit's strengths is granular control over how every page is rendered. Episode 21 covers server-side rendering and static generation: how SSR works, when to produce static HTML, how streaming speeds up first paint, and how to pick the right mode for each case.
You do not have to choose one mode for everything. A single app can use SSG for marketing pages, SSR for dynamic pages, and streaming for pages with slow data. The decision is made per route, where the benefit is greatest.
After this episode, you understand the trade-offs of each mode and can configure rendering with precision.
SvelteKit has four modes that are independent of each other: ssr decides whether the page is rendered on the server, csr decides whether interactivity is hydrated on the client, prerender decides whether HTML is generated at build time, and trailingSlash controls the URL format. Each can be set per route or globally.
export const ssr = true;
export const csr = true;
export const prerender = false;SSR produces HTML on the server for every request. It matters for dynamic content that depends on the user, the session, or frequently changing data. SEO and shareability benefit because the content is already in the HTML, and the app still works when JavaScript fails to load.
Sites with rarely changing content, such as documentation or blogs, suit full SSG. With export const prerender = true on the root layout, SvelteKit crawls all routes and generates static files. No server runs on request; everything is served from a CDN. For a purely static output, install npm install -D @sveltejs/adapter-static and use that adapter.
import adapter from "@sveltejs/adapter-static";
export default {
kit: {
adapter: adapter({
pages: "build",
assets: "build",
fallback: "index.html"
})
}
};Not every page needs to be prerendered at once. Routes whose data changes periodically can be prerendered with scheduled rebuilds, while other routes stay SSR. Modern platforms also support incremental builds, where only the changed pages are rebuilt.
Streaming sends the page shell as soon as it is ready, then fills in slow sections when their data arrives. Users see the main content faster, while secondary sections load without blocking the first paint.
export const load = async ({ fetch, params }) => {
return {
artikel: await fetch(`/api/artikel/${params.id}`).then((r) => r.json()),
komentar: fetch(`/api/artikel/${params.id}/komentar`).then((r) => r.json())
};
};In the component, sections whose value is a promise are rendered with {#await}. SvelteKit handles reconciling the streamed data between server and client, so state changes when the data arrives happen seamlessly.
<script>
let { data } = $props();
</script>
{#await data.komentar}
<p>Memuat komentar...</p>
{:then komentar}
<ul>
{#each komentar as k}
<li>{k.isi}</li>
{/each}
</ul>
{/await}Start from a basic question: does the page need per-request data? If not, and the content rarely changes, prerender. If it needs user data or real-time data, use SSR. If some parts are fast and some are slow, combine SSR with streaming.
Do not use SSG for pages with personal data, because every user would receive the same HTML. Conversely, do not use SSR for pages with static data — you pay server CPU to produce output that could be generated once at build. Choose based on data needs, not habit.
Key takeaways:
ssr, csr, and prerender are configured independently per route.{#await} in the component.In the next episode we get into observability & monitoring: monitoring performance and runtime errors, error reporting with Sentry, analytics and user behavior tracking, plus production support and incident management.