Skip to content

Commit 1d2e52d

Browse files
authored
docs: sync repos (#677)
* docs: sync repos * fix links
1 parent 05c4dcf commit 1d2e52d

File tree

23 files changed

+152
-89
lines changed

23 files changed

+152
-89
lines changed

apps/svelte.dev/content/docs/kit/20-core-concepts/10-routing.md

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,22 @@ A `+page.svelte` component defines a page of your app. By default, pages are ren
3737
<a href="/">Home</a>
3838
```
3939

40+
Pages can receive data from `load` functions via the `data` prop.
41+
4042
```svelte
4143
<!--- file: src/routes/blog/[slug]/+page.svelte --->
4244
<script>
43-
/** @type {import('./$types').PageData} */
44-
export let data;
45+
/** @type {{ data: import('./$types').PageData }} */
46+
let { data } = $props();
4547
</script>
4648
4749
<h1>{data.title}</h1>
4850
<div>{@html data.content}</div>
4951
```
5052

53+
> [!LEGACY] In Svelte 4
54+
> In Svelte 4, you'd use `export let data` instead
55+
5156
> [!NOTE] Note that SvelteKit uses `<a>` elements to navigate between routes, rather than a framework-specific `<Link>` component.
5257
5358
### +page.js
@@ -153,21 +158,29 @@ But in many apps, there are elements that should be visible on _every_ page, suc
153158

154159
To create a layout that applies to every page, make a file called `src/routes/+layout.svelte`. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this...
155160

156-
```html
157-
<slot></slot>
161+
```svelte
162+
<script>
163+
let { children } = $props();
164+
</script>
165+
166+
{@render children()}
158167
```
159168

160-
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `<slot>` for the page content. For example, let's add a nav bar:
169+
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `@render` tag for the page content. For example, let's add a nav bar:
170+
171+
```svelte
172+
<!---- file: src/routes/+layout.svelte --->
173+
<script>
174+
let { children } = $props();
175+
</script>
161176
162-
```html
163-
/// file: src/routes/+layout.svelte
164177
<nav>
165178
<a href="/">Home</a>
166179
<a href="/about">About</a>
167180
<a href="/settings">Settings</a>
168181
</nav>
169182
170-
<slot></slot>
183+
{@render children()}
171184
```
172185

173186
If we create pages for `/`, `/about` and `/settings`...
@@ -196,8 +209,8 @@ We can create a layout that only applies to pages below `/settings` (while inher
196209
```svelte
197210
<!--- file: src/routes/settings/+layout.svelte --->
198211
<script>
199-
/** @type {import('./$types').LayoutData} */
200-
export let data;
212+
/** @type {{ data: import('./$types').LayoutData, children: import('svelte').Snippet }} */
213+
let { data, children } = $props();
201214
</script>
202215
203216
<h1>Settings</h1>
@@ -208,7 +221,7 @@ We can create a layout that only applies to pages below `/settings` (while inher
208221
{/each}
209222
</div>
210223
211-
<slot></slot>
224+
{@render children()}
212225
```
213226

214227
You can see how `data` is populated by looking at the `+layout.js` example in the next section just below.
@@ -239,8 +252,8 @@ Data returned from a layout's `load` function is also available to all its child
239252
```svelte
240253
<!--- file: src/routes/settings/profile/+page.svelte --->
241254
<script>
242-
/** @type {import('./$types').PageData} */
243-
export let data;
255+
/** @type {{ data: import('./$types').PageData }} */
256+
let { data } = $props();
244257
245258
console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...]
246259
</script>
@@ -370,13 +383,13 @@ export async function fallback({ request }) {
370383
371384
Throughout the examples above, we've been importing types from a `$types.d.ts` file. This is a file SvelteKit creates for you in a hidden directory if you're using TypeScript (or JavaScript with JSDoc type annotations) to give you type safety when working with your root files.
372385
373-
For example, annotating `export let data` with `PageData` (or `LayoutData`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
386+
For example, annotating `let { data } = $props()` with `PageData` (or `LayoutData`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
374387
375388
```svelte
376389
<!--- file: src/routes/blog/[slug]/+page.svelte --->
377390
<script>
378-
/** @type {import('./$types').PageData} */
379-
export let data;
391+
/** @type {{ data: import('./$types').PageData }} */
392+
let { data } = $props();
380393
</script>
381394
```
382395

apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ export function load({ params }) {
2424
```svelte
2525
<!--- file: src/routes/blog/[slug]/+page.svelte --->
2626
<script>
27-
/** @type {import('./$types').PageData} */
28-
export let data;
27+
/** @type {{ data: import('./$types').PageData }} */
28+
let { data } = $props();
2929
</script>
3030
3131
<h1>{data.post.title}</h1>
3232
<div>{@html data.post.content}</div>
3333
```
3434

35+
> [!LEGACY] In Svelte 4
36+
> In Svelte 4, you'd use `export let data` instead
37+
3538
Thanks to the generated `$types` module, we get full type safety.
3639

3740
A `load` function in a `+page.js` file runs both on the server and in the browser (unless combined with `export const ssr = false`, in which case it will [only run in the browser](page-options#ssr)). If your `load` function should _always_ run on the server (because it uses private environment variables, for example, or accesses a database) then it would go in a `+page.server.js` instead.
@@ -85,13 +88,13 @@ export async function load() {
8588
```svelte
8689
<!--- file: src/routes/blog/[slug]/+layout.svelte --->
8790
<script>
88-
/** @type {import('./$types').LayoutData} */
89-
export let data;
91+
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
92+
let { data, children } = $props();
9093
</script>
9194
9295
<main>
93-
<!-- +page.svelte is rendered in this <slot> -->
94-
<slot />
96+
<!-- +page.svelte is `@render`ed here -->
97+
{@render children()}
9598
</main>
9699
97100
<aside>
@@ -115,13 +118,13 @@ Data returned from layout `load` functions is available to child `+layout.svelte
115118
<script>
116119
+++import { page } from '$app/stores';+++
117120
118-
/** @type {import('./$types').PageData} */
119-
export let data;
121+
/** @type {{ data: import('./$types').PageData }} */
122+
let { data } = $props();
120123
121124
+++ // we can access `data.posts` because it's returned from
122125
// the parent layout `load` function
123126
let index = $derived(data.posts.findIndex(post => post.slug === $page.params.slug));
124-
let next = $derived(data.posts[index - 1];)+++
127+
let next = $derived(data.posts[index + 1]);+++
125128
</script>
126129
127130
<h1>{data.post.title}</h1>
@@ -330,7 +333,7 @@ export async function load({ fetch, setHeaders }) {
330333
}
331334
```
332335

333-
Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. You cannot add a `set-cookie` header with `setHeaders` — use `cookies.set(name, value, options)` instead.
336+
Setting the same header multiple times (even in separate `load` functions) is an error. You can only set a given header once using the `setHeaders` function. You cannot add a `set-cookie` header with `setHeaders` — use `cookies.set(name, value, options)` instead.
334337

335338
## Using parent data
336339

@@ -365,8 +368,8 @@ export async function load({ parent }) {
365368
```svelte
366369
<!--- file: src/routes/abc/+page.svelte --->
367370
<script>
368-
/** @type {import('./$types').PageData} */
369-
export let data;
371+
/** @type {{ data: import('./$types').PageData }} */
372+
let { data } = $props();
370373
</script>
371374
372375
<!-- renders `1 + 2 = 3` -->
@@ -504,8 +507,8 @@ This is useful for creating skeleton loading states, for example:
504507
```svelte
505508
<!--- file: src/routes/blog/[slug]/+page.svelte --->
506509
<script>
507-
/** @type {import('./$types').PageData} */
508-
export let data;
510+
/** @type {{ data: import('./$types').PageData }} */
511+
let { data } = $props();
509512
</script>
510513
511514
<h1>{data.post.title}</h1>
@@ -645,8 +648,8 @@ export async function load({ fetch, depends }) {
645648
<script>
646649
import { invalidate, invalidateAll } from '$app/navigation';
647650
648-
/** @type {import('./$types').PageData} */
649-
export let data;
651+
/** @type {{ data: import('./$types').PageData }} */
652+
let { data } = $props();
650653
651654
function rerunLoadFunction() {
652655
// any of these will cause the `load` function to rerun

apps/svelte.dev/content/docs/kit/20-core-concepts/30-form-actions.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,8 @@ export const actions = {
140140
```svelte
141141
<!--- file: src/routes/login/+page.svelte --->
142142
<script>
143-
/** @type {import('./$types').PageData} */
144-
export let data;
145-
146-
/** @type {import('./$types').ActionData} */
147-
export let form;
143+
/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
144+
let { data, form } = $props();
148145
</script>
149146

150147
{#if form?.success}
@@ -154,6 +151,9 @@ export const actions = {
154151
{/if}
155152
```
156153
154+
> [!LEGACY] In Svelte 4
155+
> In Svelte 4, you'd use `export let data` and `export let form` instead to declare properties
156+
157157
### Validation errors
158158
159159
If the request couldn't be processed because of invalid data, you can return validation errors — along with the previously submitted form values — back to the user so that they can try again. The `fail` function lets you return an HTTP status code (typically 400 or 422, in the case of validation errors) along with the data. The status code is available through `$page.status` and the data through `form`:
@@ -339,8 +339,8 @@ The easiest way to progressively enhance a form is to add the `use:enhance` acti
339339
<script>
340340
+++import { enhance } from '$app/forms';+++
341341

342-
/** @type {import('./$types').ActionData} */
343-
export let form;
342+
/** @type {{ form: import('./$types').ActionData }} */
343+
let { form } = $props();
344344
</script>
345345

346346
<form method="POST" +++use:enhance+++>
@@ -390,8 +390,8 @@ If you return a callback, you may need to reproduce part of the default `use:enh
390390
<script>
391391
import { enhance, +++applyAction+++ } from '$app/forms';
392392

393-
/** @type {import('./$types').ActionData} */
394-
export let form;
393+
/** @type {{ form: import('./$types').ActionData }} */
394+
let { form } = $props();
395395
</script>
396396

397397
<form
@@ -427,11 +427,8 @@ We can also implement progressive enhancement ourselves, without `use:enhance`,
427427
import { invalidateAll, goto } from '$app/navigation';
428428
import { applyAction, deserialize } from '$app/forms';
429429

430-
/** @type {import('./$types').ActionData} */
431-
export let form;
432-
433-
/** @type {any} */
434-
let error;
430+
/** @type {{ form: import('./$types').ActionData }} */
431+
let { form } = $props();
435432

436433
/** @param {{ currentTarget: EventTarget & HTMLFormElement}} event */
437434
async function handleSubmit(event) {

apps/svelte.dev/content/docs/kit/20-core-concepts/50-state-management.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,14 @@ You might wonder how we're able to use `$page.data` and other [app stores]($app-
9090
import { setContext } from 'svelte';
9191
import { writable } from 'svelte/store';
9292
93-
/** @type {import('./$types').LayoutData} */
94-
export let data;
93+
/** @type {{ data: import('./$types').LayoutData }} */
94+
let { data } = $props();
9595
9696
// Create a store and update it when necessary...
97-
const user = writable();
98-
$: user.set(data.user);
97+
const user = writable(data.user);
98+
$effect.pre(() => {
99+
user.set(data.user);
100+
});
99101
100102
// ...and add it to the context for child components to access
101103
setContext('user', user);
@@ -125,8 +127,8 @@ When you navigate around your application, SvelteKit reuses existing layout and
125127
```svelte
126128
<!--- file: src/routes/blog/[slug]/+page.svelte --->
127129
<script>
128-
/** @type {import('./$types').PageData} */
129-
export let data;
130+
/** @type {{ data: import('./$types').PageData }} */
131+
let { data } = $props();
130132
131133
// THIS CODE IS BUGGY!
132134
const wordCount = data.content.split(' ').length;
@@ -148,8 +150,8 @@ Instead, we need to make the value [_reactive_](/tutorial/svelte/state):
148150
```svelte
149151
/// file: src/routes/blog/[slug]/+page.svelte
150152
<script>
151-
/** @type {import('./$types').PageData} */
152-
export let data;
153+
/** @type {{ data: import('./$types').PageData }} */
154+
let { data } = $props();
153155
154156
+++ let wordCount = $state(data.content.split(' ').length);
155157
let estimatedReadingTime = $derived(wordCount / 250);+++

apps/svelte.dev/content/docs/kit/25-build-and-deploy/90-adapter-vercel.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ export function load() {
140140
```svelte
141141
<!--- file: +layout.svelte --->
142142
<script>
143-
/** @type {import('./$types').LayoutServerData} */
144-
export let data;
143+
/** @type {{ data: import('./$types').LayoutServerData }} */
144+
let { data } = $props();
145145
</script>
146146
147147
<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>

apps/svelte.dev/content/docs/kit/30-advanced/10-advanced-routing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ You can also put a `+page` directly inside a `(group)`, for example if `/` shoul
193193

194194
### Breaking out of layouts
195195

196-
The root layout applies to every page of your app — if omitted, it defaults to `<slot />`. If you want some pages to have a different layout hierarchy than the rest, then you can put your entire app inside one or more groups _except_ the routes that should not inherit the common layouts.
196+
The root layout applies to every page of your app — if omitted, it defaults to `{@render children()}`. If you want some pages to have a different layout hierarchy than the rest, then you can put your entire app inside one or more groups _except_ the routes that should not inherit the common layouts.
197197

198198
In the example above, the `/admin` route does not inherit either the `(app)` or `(marketing)` layouts.
199199

@@ -260,11 +260,11 @@ Not all use cases are suited for layout grouping, nor should you feel compelled
260260
<!--- file: src/routes/nested/route/[email protected] --->
261261
<script>
262262
import ReusableLayout from '$lib/ReusableLayout.svelte';
263-
export let data;
263+
let { data, children } = $props();
264264
</script>
265265
266266
<ReusableLayout {data}>
267-
<slot />
267+
{@render children()}
268268
</ReusableLayout>
269269
```
270270

apps/svelte.dev/content/docs/kit/30-advanced/20-hooks.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ export async function handle({ event, resolve }) {
3737

3838
> [!NOTE] Requests for static assets — which includes pages that were already prerendered — are _not_ handled by SvelteKit.
3939
40-
If unimplemented, defaults to `({ event, resolve }) => resolve(event)`. To add custom data to the request, which is passed to handlers in `+server.js` and server `load` functions, populate the `event.locals` object, as shown below.
40+
If unimplemented, defaults to `({ event, resolve }) => resolve(event)`.
41+
42+
### locals
43+
44+
To add custom data to the request, which is passed to handlers in `+server.js` and server `load` functions, populate the `event.locals` object, as shown below.
4145

4246
```js
4347
/// file: src/hooks.server.js

apps/svelte.dev/content/docs/kit/30-advanced/65-snapshots.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ To do this, export a `snapshot` object with `capture` and `restore` methods from
1111
```svelte
1212
<!--- file: +page.svelte --->
1313
<script>
14-
let comment = '';
14+
let comment = $state('');
1515
1616
/** @type {import('./$types').Snapshot<string>} */
1717
export const snapshot = {

apps/svelte.dev/content/docs/kit/30-advanced/67-shallow-routing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ For this to work, you need to load the data that the `+page.svelte` expects. A c
5151
import Modal from './Modal.svelte';
5252
import PhotoPage from './[id]/+page.svelte';
5353
54-
export let data;
54+
let { data } = $props();
5555
</script>
5656
5757
{#each data.thumbnails as thumbnail}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: Auth
3+
---
4+
5+
Auth refers to authentication and authorization, which are common needs when building a web application. Authentication means verifying that the user is who they say they are based on their provided credentials. Authorization means determining which actions they are allowed to take.
6+
7+
## Sessions vs tokens
8+
9+
After the user has provided their credentials such as a username and password, we want to allow them to use the application without needing to provide their credentials again for future requests. Users are commonly authenticated on subsequent requests with either a session identifier or signed token such as a JSON Web Token (JWT).
10+
11+
Session IDs are most commonly stored in a database. They can be immediately revoked, but require a database query to be made on each request.
12+
13+
In contrast, JWT generally are not checked against a datastore, which means they cannot be immediately revoked. The advantage of this method is improved latency and reduced load on your datastore.
14+
15+
## Integration points
16+
17+
Auth [cookies](@sveltejs-kit#Cookies) can be checked inside [server hooks](hooks#Server-hooks). If a user is found matching the provided credentials, the user information can be stored in [`locals`](hooks#Server-hooks-handle).
18+
19+
## Guides
20+
21+
[Lucia](https://lucia-next.pages.dev/) is a reference for session-based web app auth. It contains example code snippets and projects for implementing session-based auth within SvelteKit and other JS projects. You can add code which follows the Lucia guide to your project with `npx sv create` when creating a new project or `npx sv add lucia` for an existing project.
22+
23+
An auth system is tightly coupled to a web framework because most of the code lies in validating user input, handling errors, and directing users to the appropriate next page. As a result, many of the generic JS auth libraries include one or more web frameworks within them. For this reason, many users will find it preferrable to follow a SvelteKit-specific guide such as the examples found in [Lucia](https://lucia-next.pages.dev/) rather than having multiple web frameworks inside their project.

0 commit comments

Comments
 (0)