From d9aed992053020e9b8f423ad93296356ebde4176 Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Mon, 29 Sep 2025 17:54:30 +0200 Subject: [PATCH 01/12] docs: clarify that SSR is required for SSG with content (#14471) --- documentation/docs/20-core-concepts/40-page-options.md | 4 +++- documentation/docs/25-build-and-deploy/50-adapter-static.md | 2 ++ documentation/docs/60-appendix/60-glossary.md | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index 727274c80911..2f3eefdc506c 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -125,7 +125,9 @@ export const ssr = false; // If both `ssr` and `csr` are `false`, nothing will be rendered! ``` -If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an SPA. +If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). + +SvelteKit's SSR mode can also used by `adapter-static` to [prerender static page content (SSG)](adapter-static#Usage). > [!NOTE] If all your page options are boolean or string literal values, SvelteKit will evaluate them statically. If not, it will import your `+page.js` or `+layout.js` file on the server (both at build time, and at runtime if your app isn't fully static) so it can evaluate the options. In the second case, browser-only code must not run when the module is loaded. In practice, this means you should import browser-only code in your `+page.svelte` or `+layout.svelte` file instead. diff --git a/documentation/docs/25-build-and-deploy/50-adapter-static.md b/documentation/docs/25-build-and-deploy/50-adapter-static.md index 2b50d91515e3..74877a174d74 100644 --- a/documentation/docs/25-build-and-deploy/50-adapter-static.md +++ b/documentation/docs/25-build-and-deploy/50-adapter-static.md @@ -44,6 +44,8 @@ export const prerender = true; > [!NOTE] You must ensure SvelteKit's [`trailingSlash`](page-options#trailingSlash) option is set appropriately for your environment. If your host does not render `/a.html` upon receiving a request for `/a` then you will need to set `trailingSlash: 'always'` in your root layout to create `/a/index.html` instead. +> [!NOTE] `adapter-static` relies on SvelteKit's server-side rendering (SSR) features to prerender static page content in the build phase. If SSR is disabled on a page, the `prerender` option will only generate an empty 'shell' page for it. To prerender content on pages, you just ensure they have SSR enabled, i.e. they should _not_ have the page option [`ssr`](page-options#ssr) set to `false` in their page & layout ancestry. + ## Zero-config support Some platforms have zero-config support (more to come in future): diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index 25f300918ec2..99b72d7929a9 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -42,6 +42,8 @@ Pre-rendered pages are not limited to static content. You can build personalized In SvelteKit, you can control prerendering with [the `prerender` page option](page-options#prerender) and [`prerender` config](configuration#prerender) in `svelte.config.js`. +If you are prerendering all your pages, you are doing [Static Site Generation](#SSG). + ## PWA A progressive web app (PWA) is an app that's built using web APIs and technologies, but functions like a mobile or desktop app. Sites served as [PWAs can be installed](https://web.dev/learn/pwa/installation), allowing you to add a shortcut to the application on your launcher, home screen, or start menu. Many PWAs will utilize [service workers](service-workers) to build offline capabilities. @@ -62,7 +64,9 @@ In SvelteKit, you can [build SPAs with `adapter-static`](single-page-apps). Static Site Generation (SSG) is a term that refers to a site where every page is prerendered. One benefit of fully prerendering a site is that you do not need to maintain or pay for servers to perform SSR. Once generated, the site can be served from CDNs, leading to great “time to first byte” performance. This delivery model is often referred to as JAMstack. -In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be prerendered using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. +In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be [prerendered](#prerendering) using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. + +Note that you will probably want to keep the `ssr` page option enabled to ensure that [content is pre-rendered in the build phase](adapter-static#Usage). ## SSR From 38e665426862ee5b876e4139fcfd6866e58e343a Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 22:38:44 +0800 Subject: [PATCH 02/12] Apply suggestion from @teemingc --- documentation/docs/60-appendix/60-glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index 99b72d7929a9..474c8fe66908 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -64,7 +64,7 @@ In SvelteKit, you can [build SPAs with `adapter-static`](single-page-apps). Static Site Generation (SSG) is a term that refers to a site where every page is prerendered. One benefit of fully prerendering a site is that you do not need to maintain or pay for servers to perform SSR. Once generated, the site can be served from CDNs, leading to great “time to first byte” performance. This delivery model is often referred to as JAMstack. -In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be [prerendered](#prerendering) using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. +In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be [prerendered](#Prerendering) using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. Note that you will probably want to keep the `ssr` page option enabled to ensure that [content is pre-rendered in the build phase](adapter-static#Usage). From 3377fb1d5dc0bde44b38e6dcfea91709c2271284 Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:00:35 +0100 Subject: [PATCH 03/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/20-core-concepts/40-page-options.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index 2f3eefdc506c..50c6cace8db9 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -117,7 +117,9 @@ export const prerender = true; ## ssr -Normally, SvelteKit renders your page on the server first and sends that HTML to the client where it's [hydrated](glossary#Hydration). If you set `ssr` to `false`, it renders an empty 'shell' page instead. This is useful if your page is unable to be rendered on the server (because you use browser-only globals like `document` for example), but in most situations it's not recommended ([see appendix](glossary#SSR)). +Normally, SvelteKit renders your page on the server before sending that HTML to the client where it's [hydrated](glossary#Hydration). This is also required for prerendering to save the full contents of a page. + +If you set `ssr` to `false`, it renders an empty 'shell' page instead. This is useful if your page is unable to be rendered on the server (because you use browser-only globals like `document` for example), but in most situations it's not recommended ([see appendix](glossary#SSR)). ```js /// file: +page.js From 2ddad1bcaefb98aba49ebf04c0f51c8441d07d9d Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:01:21 +0100 Subject: [PATCH 04/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/20-core-concepts/40-page-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index 50c6cace8db9..fefa0a4365ac 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -127,7 +127,7 @@ export const ssr = false; // If both `ssr` and `csr` are `false`, nothing will be rendered! ``` -If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). +If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). You should not do this if your goal is to build a (statically generated site)[glossary#SSG]. SvelteKit's SSR mode can also used by `adapter-static` to [prerender static page content (SSG)](adapter-static#Usage). From b1faefa0515fd9047dc47969a7f5028ffa3163b1 Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:01:46 +0100 Subject: [PATCH 05/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/20-core-concepts/40-page-options.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index fefa0a4365ac..7f7b9f185abf 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -129,7 +129,6 @@ export const ssr = false; If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). You should not do this if your goal is to build a (statically generated site)[glossary#SSG]. -SvelteKit's SSR mode can also used by `adapter-static` to [prerender static page content (SSG)](adapter-static#Usage). > [!NOTE] If all your page options are boolean or string literal values, SvelteKit will evaluate them statically. If not, it will import your `+page.js` or `+layout.js` file on the server (both at build time, and at runtime if your app isn't fully static) so it can evaluate the options. In the second case, browser-only code must not run when the module is loaded. In practice, this means you should import browser-only code in your `+page.svelte` or `+layout.svelte` file instead. From 3371f7ddf47f55da86969e749155a6bbd206947e Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:03:21 +0100 Subject: [PATCH 06/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/25-build-and-deploy/50-adapter-static.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/25-build-and-deploy/50-adapter-static.md b/documentation/docs/25-build-and-deploy/50-adapter-static.md index 74877a174d74..86bdc4d4e155 100644 --- a/documentation/docs/25-build-and-deploy/50-adapter-static.md +++ b/documentation/docs/25-build-and-deploy/50-adapter-static.md @@ -44,7 +44,7 @@ export const prerender = true; > [!NOTE] You must ensure SvelteKit's [`trailingSlash`](page-options#trailingSlash) option is set appropriately for your environment. If your host does not render `/a.html` upon receiving a request for `/a` then you will need to set `trailingSlash: 'always'` in your root layout to create `/a/index.html` instead. -> [!NOTE] `adapter-static` relies on SvelteKit's server-side rendering (SSR) features to prerender static page content in the build phase. If SSR is disabled on a page, the `prerender` option will only generate an empty 'shell' page for it. To prerender content on pages, you just ensure they have SSR enabled, i.e. they should _not_ have the page option [`ssr`](page-options#ssr) set to `false` in their page & layout ancestry. +> [!NOTE] You must ensure SvelteKit's [`ssr`](page-options#ssr) option isn't set to `false`. Otherwise, prerendering will save an empty 'shell' page instead of the fully rendered content. ## Zero-config support From 595810618725c6627da89150854875fd38b91465 Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:04:10 +0100 Subject: [PATCH 07/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/60-appendix/60-glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index 474c8fe66908..882c3eb5e397 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -36,7 +36,7 @@ Traditional applications that render each page view on the server — such as th Prerendering means computing the contents of a page at build time and saving the HTML for display. This approach has the same benefits as traditional server-rendered pages, but avoids recomputing the page for each visitor and so scales nearly for free as the number of visitors increases. The tradeoff is that the build process is more expensive and prerendered content can only be updated by building and deploying a new version of the application. -Not all pages can be prerendered. The basic rule is this: for content to be prerenderable, any two users hitting it directly must get the same content from the server, and the page must not contain [actions](form-actions). Note that you can still prerender content that is loaded based on the page's parameters as long as all users will be seeing the same prerendered content. +For content to be prerenderable, any two users hitting it directly must get the same content from the server, and the page must not contain [actions](form-actions). Note that you can still prerender content that is loaded based on the page's parameters as long as all users will be seeing the same prerendered content. Prerendering all of your pages is also known as [Static Site Generation](#SSG). Pre-rendered pages are not limited to static content. You can build personalized pages if user-specific data is fetched and rendered client-side. This is subject to the caveat that you will experience the downsides of not doing SSR for that content as discussed above. From 9cf1d055b46c1d152572cb96d0f5ec5cba8aa9a3 Mon Sep 17 00:00:00 2001 From: Thor Galle Date: Fri, 6 Feb 2026 16:05:10 +0100 Subject: [PATCH 08/12] Apply suggestion from @teemingc Co-authored-by: Tee Ming --- documentation/docs/60-appendix/60-glossary.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index 882c3eb5e397..faa5a9aa2d26 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -42,7 +42,6 @@ Pre-rendered pages are not limited to static content. You can build personalized In SvelteKit, you can control prerendering with [the `prerender` page option](page-options#prerender) and [`prerender` config](configuration#prerender) in `svelte.config.js`. -If you are prerendering all your pages, you are doing [Static Site Generation](#SSG). ## PWA From 7fe073e73603a4be44898cb3c4f7b09b5dedf23e Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 7 Feb 2026 13:50:36 +0800 Subject: [PATCH 09/12] Update documentation/docs/60-appendix/60-glossary.md --- documentation/docs/60-appendix/60-glossary.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index faa5a9aa2d26..0433deef8ae8 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -65,7 +65,6 @@ Static Site Generation (SSG) is a term that refers to a site where every page is In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be [prerendered](#Prerendering) using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. -Note that you will probably want to keep the `ssr` page option enabled to ensure that [content is pre-rendered in the build phase](adapter-static#Usage). ## SSR From f861131359e62c0b68d4c0ce521f058bdc33ed8f Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 7 Feb 2026 13:51:36 +0800 Subject: [PATCH 10/12] Apply suggestion from @teemingc --- documentation/docs/60-appendix/60-glossary.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/docs/60-appendix/60-glossary.md b/documentation/docs/60-appendix/60-glossary.md index 0433deef8ae8..7186b86f62e1 100644 --- a/documentation/docs/60-appendix/60-glossary.md +++ b/documentation/docs/60-appendix/60-glossary.md @@ -65,7 +65,6 @@ Static Site Generation (SSG) is a term that refers to a site where every page is In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be [prerendered](#Prerendering) using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. - ## SSR Server-side rendering (SSR) is the generation of the page contents on the server. Returning the page contents from the server via SSR or prerendering is highly preferred for performance and SEO. It significantly improves performance by avoiding the introduction of extra round trips necessary in a SPA, and makes your app accessible to users if JavaScript fails or is disabled (which happens [more often than you probably think](https://kryogenix.org/code/browser/everyonehasjs.html)). While some search engines can index content that is dynamically generated on the client-side, it is likely to take longer even in these cases. From cc91ed1b2dd611f3084b1d46485e7555201b1e05 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 7 Feb 2026 13:51:43 +0800 Subject: [PATCH 11/12] Apply suggestion from @teemingc --- documentation/docs/20-core-concepts/40-page-options.md | 1 - 1 file changed, 1 deletion(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index 7f7b9f185abf..2d6dbd5e4de4 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -129,7 +129,6 @@ export const ssr = false; If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). You should not do this if your goal is to build a (statically generated site)[glossary#SSG]. - > [!NOTE] If all your page options are boolean or string literal values, SvelteKit will evaluate them statically. If not, it will import your `+page.js` or `+layout.js` file on the server (both at build time, and at runtime if your app isn't fully static) so it can evaluate the options. In the second case, browser-only code must not run when the module is loaded. In practice, this means you should import browser-only code in your `+page.svelte` or `+layout.svelte` file instead. ## csr From 370ea530b81b5d8f00611714c30f85233568b18d Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 7 Feb 2026 13:57:11 +0800 Subject: [PATCH 12/12] Update documentation/docs/20-core-concepts/40-page-options.md Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> --- documentation/docs/20-core-concepts/40-page-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/20-core-concepts/40-page-options.md b/documentation/docs/20-core-concepts/40-page-options.md index 2d6dbd5e4de4..d9023c341eee 100644 --- a/documentation/docs/20-core-concepts/40-page-options.md +++ b/documentation/docs/20-core-concepts/40-page-options.md @@ -127,7 +127,7 @@ export const ssr = false; // If both `ssr` and `csr` are `false`, nothing will be rendered! ``` -If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). You should not do this if your goal is to build a (statically generated site)[glossary#SSG]. +If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an [SPA](glossary#SPA). You should not do this if your goal is to build a [statically generated site](glossary#SSG). > [!NOTE] If all your page options are boolean or string literal values, SvelteKit will evaluate them statically. If not, it will import your `+page.js` or `+layout.js` file on the server (both at build time, and at runtime if your app isn't fully static) so it can evaluate the options. In the second case, browser-only code must not run when the module is loaded. In practice, this means you should import browser-only code in your `+page.svelte` or `+layout.svelte` file instead.