Coming soon
diff --git a/content/tutorial/04-advanced-sveltekit/01-hooks/meta.json b/content/tutorial/04-advanced-sveltekit/01-hooks/meta.json
new file mode 100644
index 000000000..a224e7261
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/01-hooks/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Hooks"
+}
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/README.md b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/README.md
deleted file mode 100644
index dd6c3a722..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Sandbox
----
-
-ignore me
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/index.js b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/index.js
deleted file mode 100644
index 281fec0c3..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// line 1
-// line 2
-// line 2
-// line 2
-// line 2
-// line 2
-// line 2
-// line 2
-module.exports = () => 'wooo!!! cjs';
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/package.json b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/package.json
deleted file mode 100644
index a2091cee3..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/cjs-dep/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "type": "commonjs"
-}
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/index.js b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/index.js
deleted file mode 100644
index 38e1306fd..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export default () => 'wooo!!! esm';
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/package.json b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/package.json
deleted file mode 100644
index 47dc78d39..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/node_modules/esm-dep/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "type": "module"
-}
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/lib/b.js b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/lib/b.js
deleted file mode 100644
index 7b9db73a0..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/lib/b.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export function foo() {
- return 42;
-}
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/routes/+page.svelte
deleted file mode 100644
index 1afc09501..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/routes/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-sandbox
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/svelte.config.js b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/svelte.config.js
deleted file mode 100644
index 301e785eb..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/svelte.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import adapter from '@sveltejs/adapter-auto';
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- kit: {
- adapter: adapter()
- }
-};
-
-export default config;
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/vite.config.js b/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/vite.config.js
deleted file mode 100644
index da06c515e..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/vite.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/** @type {import('vite').UserConfig} */
-export default {
- optimizeDeps: {
- include: ['cjs-dep']
- }
-};
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/meta.json b/content/tutorial/04-advanced-sveltekit/01-todo/meta.json
deleted file mode 100644
index 20a00a555..000000000
--- a/content/tutorial/04-advanced-sveltekit/01-todo/meta.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "title": "TODO"
-}
diff --git a/content/tutorial/04-advanced-sveltekit/02-stores/01-page-store/README.md b/content/tutorial/04-advanced-sveltekit/02-stores/01-page-store/README.md
new file mode 100644
index 000000000..641a3f687
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/02-stores/01-page-store/README.md
@@ -0,0 +1,5 @@
+---
+title: page
+---
+
+> Coming soon
diff --git a/content/tutorial/04-advanced-sveltekit/02-stores/02-navigating-store/README.md b/content/tutorial/04-advanced-sveltekit/02-stores/02-navigating-store/README.md
new file mode 100644
index 000000000..48cde502b
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/02-stores/02-navigating-store/README.md
@@ -0,0 +1,5 @@
+---
+title: navigating
+---
+
+> Coming soon
diff --git a/content/tutorial/04-advanced-sveltekit/02-stores/03-updated-store/README.md b/content/tutorial/04-advanced-sveltekit/02-stores/03-updated-store/README.md
new file mode 100644
index 000000000..b892450a8
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/02-stores/03-updated-store/README.md
@@ -0,0 +1,5 @@
+---
+title: updated
+---
+
+> Coming soon
diff --git a/content/tutorial/04-advanced-sveltekit/02-stores/meta.json b/content/tutorial/04-advanced-sveltekit/02-stores/meta.json
new file mode 100644
index 000000000..c70d14efe
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/02-stores/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Stores"
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/README.md b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/README.md
new file mode 100644
index 000000000..e822b7f4f
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/README.md
@@ -0,0 +1,28 @@
+---
+title: Optional parameters
+---
+
+In the first chapter on [routing](/tutorial/pages), we learned how to create routes with [dynamic parameters](/tutorial/params).
+
+Sometimes it's helpful to make a parameter optional. A classic example is when you use the pathname to determine the locale — `/fr/...`, `/de/...` and so on — but you also want to have a default locale.
+
+To do that, we use double brackets. Rename the `[lang]` directory to `[[lang]]`.
+
+The app now fails to build, because `src/routes/+page.svelte` and `src/routes/[[lang]]/+page.svelte` would both match `/`. Delete `src/routes/+page.svelte`. (You may need to reload the app to recover from the error page).
+
+Lastly, edit `src/routes/[[lang]]/+page.server.js` to specify the default locale:
+
+```js
+/// file: src/routes/[[lang]]/+page.server.js
+const greetings = {
+ en: 'hello!',
+ de: 'hallo!',
+ fr: 'bonjour!'
+};
+
+export function load({ params }) {
+ return {
+ greeting: greetings[params.lang +++?? 'en'+++]
+ };
+}
+```
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+layout.svelte
new file mode 100644
index 000000000..1b7838205
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+layout.svelte
@@ -0,0 +1,8 @@
+
+ default
+ english
+ german
+ french
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..88e87e748
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/+page.svelte
@@ -0,0 +1 @@
+hello!
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.server.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.server.js
new file mode 100644
index 000000000..3318ab14e
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.server.js
@@ -0,0 +1,11 @@
+const greetings = {
+ en: 'hello!',
+ de: 'hallo!',
+ fr: 'bonjour!'
+};
+
+export function load({ params }) {
+ return {
+ greeting: greetings[params.lang]
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.svelte
new file mode 100644
index 000000000..a791437ec
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-a/src/routes/[lang]/+page.svelte
@@ -0,0 +1,5 @@
+
+
+{data.greeting}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/+page.svelte
new file mode 100644
index 000000000..5d003dc7d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/+page.svelte
@@ -0,0 +1 @@
+__delete;
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.server.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.server.js
new file mode 100644
index 000000000..ded09d03b
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.server.js
@@ -0,0 +1,11 @@
+const greetings = {
+ en: 'hello!',
+ de: 'hallo!',
+ fr: 'bonjour!'
+};
+
+export function load({ params }) {
+ return {
+ greeting: greetings[params.lang ?? 'en']
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.svelte
new file mode 100644
index 000000000..a791437ec
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[[lang]]/+page.svelte
@@ -0,0 +1,5 @@
+
+
+{data.greeting}
diff --git a/content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/lib/a.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[lang]/__delete
similarity index 100%
rename from content/tutorial/04-advanced-sveltekit/01-todo/01-sandbox/app-a/src/lib/a.js
rename to content/tutorial/04-advanced-sveltekit/03-advanced-routing/01-optional-params/app-b/src/routes/[lang]/__delete
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/README.md b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/README.md
new file mode 100644
index 000000000..d003c037a
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/README.md
@@ -0,0 +1,22 @@
+---
+title: Rest parameters
+---
+
+To match an unknown number of path segments, use a `[...rest]` parameter, so named for its resemblance to [rest parameters in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
+
+Rename `src/routes/[path]` to `src/routes/[...path]`. The route now matches any path.
+
+> Other, more specific routes will be tested first, making rest parameters useful as 'catch-all' routes. For example, if you needed a custom 404 page for pages inside `/categories/...`, you could add these files:
+>
+> ```diff
+> src/routes/
+> ├ categories/
+> │ ├ animal/
+> │ ├ mineral/
+> │ ├ vegetable/
+> +│ ├ [...catchall]/
+> +│ │ ├ +error.svelte
+> +│ │ └ +page.server.js
+> ```
+>
+> Inside the `+page.server.js` file, `throw error(404)` inside `load`.
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-a/src/routes/[path]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-a/src/routes/[path]/+page.svelte
new file mode 100644
index 000000000..1b18eb336
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-a/src/routes/[path]/+page.svelte
@@ -0,0 +1,31 @@
+
+
+{words[depth] ?? '?'}
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-b/src/routes/[...path]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-b/src/routes/[...path]/+page.svelte
new file mode 100644
index 000000000..1b18eb336
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-b/src/routes/[...path]/+page.svelte
@@ -0,0 +1,31 @@
+
+
+{words[depth] ?? '?'}
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-b/src/routes/[path]/__delete b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/02-rest-params/app-b/src/routes/[path]/__delete
new file mode 100644
index 000000000..e69de29bb
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/README.md b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/README.md
new file mode 100644
index 000000000..e39f0efb5
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/README.md
@@ -0,0 +1,20 @@
+---
+title: Param matchers
+---
+
+To prevent the router from matching on invalid input, you can specify a _matcher_. For example, you might want a route like `/colors/[value]` to match hex values like `/colors/ff3e00` but not named colors like `/colors/octarine` or any other arbitrary input.
+
+First, create a new file called `src/params/hex.js` and export a `match` function from it:
+
+```js
+/// file: src/params/hex.js
+export function match(value) {
+ return /^[0-9a-f]{6}$/.test(value);
+}
+```
+
+Then, to use the new matcher, rename `src/routes/colors/[color]` to `src/routes/colors/[color=hex]`.
+
+Now, whenever someone navigates to that route, SvelteKit will verify that `color` is a valid `hex` value. If not, SvelteKit will try to match other routes, before eventually returning a 404.
+
+> Matchers run both on the server and in the browser.
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+layout.svelte
new file mode 100644
index 000000000..287ab0a77
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+layout.svelte
@@ -0,0 +1,26 @@
+
+
+
+ {#each colors as color}
+ #{color}
+ {/each}
+
+
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..9fa39b3ef
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/+page.svelte
@@ -0,0 +1 @@
+color picker
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/colors/[color]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/colors/[color]/+page.svelte
new file mode 100644
index 000000000..6a6c4d6b9
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-a/src/routes/colors/[color]/+page.svelte
@@ -0,0 +1,28 @@
+
+
+
+ #{$page.params.color}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/params/hex.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/params/hex.js
new file mode 100644
index 000000000..e6887590a
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/params/hex.js
@@ -0,0 +1,3 @@
+export function match(value) {
+ return /^[0-9a-f]{6}$/.test(value);
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/routes/colors/[color=hex]/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/routes/colors/[color=hex]/+page.svelte
new file mode 100644
index 000000000..6a6c4d6b9
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/routes/colors/[color=hex]/+page.svelte
@@ -0,0 +1,28 @@
+
+
+
+ #{$page.params.color}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/routes/colors/[color]/__delete b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/03-param-matchers/app-b/src/routes/colors/[color]/__delete
new file mode 100644
index 000000000..e69de29bb
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/README.md b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/README.md
new file mode 100644
index 000000000..9b28d4d5e
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/README.md
@@ -0,0 +1,35 @@
+---
+title: Route groups
+---
+
+As we saw in the [routing introduction](/tutorial/layouts), layouts are a way to share UI and data loading logic between different routes.
+
+Sometimes it's useful to use layouts without affecting the route — for example, you might need your `/app` and `/account` routes to be behind authentication, while your `/about` page is open to the world. We can do this with a _route group_, which is a directory in parentheses.
+
+Create an `(authed)` group by renaming `account` to `(authed)/account` then renaming `app` to `(authed)/app`.
+
+Now we can control access to these routes by creating `src/routes/(authed)/+layout.server.js`:
+
+```js
+/// file: src/routes/(authed)/+layout.server.js
+import { redirect } from '@sveltejs/kit';
+
+export function load({ cookies, url }) {
+ if (!cookies.get('logged_in')) {
+ throw redirect(307, `/login?redirectTo=${url.pathname}`);
+ }
+}
+```
+
+If you try to visit these pages, you'll be redirected to the `/login` route, which has a form action in `src/routes/login/+page.server.js` that sets the `logged_in` cookie.
+
+We can also add some UI to these two routes by adding a `src/routes/(authed)/+layout.svelte` file:
+
+```svelte
+/// file: src/routes/(authed)/+layout.svelte
+
+
+
+```
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+layout.svelte
new file mode 100644
index 000000000..fc8efa3fd
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+layout.svelte
@@ -0,0 +1,8 @@
+
+ home
+ about
+ account
+ app
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..eeec61273
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/+page.svelte
@@ -0,0 +1,3 @@
+home
+
+this is the home page.
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/about/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/about/+page.svelte
new file mode 100644
index 000000000..aa6882d72
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/about/+page.svelte
@@ -0,0 +1,3 @@
+about
+
+this is the about page.
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/account/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/account/+page.svelte
new file mode 100644
index 000000000..8bb052b58
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/account/+page.svelte
@@ -0,0 +1,3 @@
+account
+
+this is the account page
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/app/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/app/+page.svelte
new file mode 100644
index 000000000..9e2673c97
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/app/+page.svelte
@@ -0,0 +1,3 @@
+app
+
+this is the app
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.server.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.server.js
new file mode 100644
index 000000000..4cd9254f9
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.server.js
@@ -0,0 +1,8 @@
+import { redirect } from '@sveltejs/kit';
+
+export const actions = {
+ default: ({ cookies, url }) => {
+ cookies.set('logged_in', 'true', { path: '/' });
+ throw redirect(307, url.searchParams.get('redirectTo') ?? '/');
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.svelte
new file mode 100644
index 000000000..93bbe41a4
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/login/+page.svelte
@@ -0,0 +1,5 @@
+log in
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/logout/+page.server.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/logout/+page.server.js
new file mode 100644
index 000000000..b0e98ae19
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-a/src/routes/logout/+page.server.js
@@ -0,0 +1,8 @@
+import { redirect } from '@sveltejs/kit';
+
+export const actions = {
+ default: ({ cookies }) => {
+ cookies.delete('logged_in', { path: '/' });
+ throw redirect(307, '/');
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.server.js b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.server.js
new file mode 100644
index 000000000..b952a183a
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.server.js
@@ -0,0 +1,7 @@
+import { redirect } from '@sveltejs/kit';
+
+export function load({ cookies, url }) {
+ if (!cookies.get('logged_in')) {
+ throw redirect(307, `/login?redirectTo=${url.pathname}`);
+ }
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.svelte
new file mode 100644
index 000000000..d2e2c27f4
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/+layout.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/account/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/account/+page.svelte
new file mode 100644
index 000000000..8bb052b58
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/account/+page.svelte
@@ -0,0 +1,3 @@
+account
+
+this is the account page
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/app/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/app/+page.svelte
new file mode 100644
index 000000000..9e2673c97
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/(authed)/app/+page.svelte
@@ -0,0 +1,3 @@
+app
+
+this is the app
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/account/__delete b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/account/__delete
new file mode 100644
index 000000000..8bb052b58
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/account/__delete
@@ -0,0 +1,3 @@
+account
+
+this is the account page
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/app/__delete b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/app/__delete
new file mode 100644
index 000000000..8bb052b58
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/04-route-groups/app-b/src/routes/app/__delete
@@ -0,0 +1,3 @@
+account
+
+this is the account page
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/README.md b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/README.md
new file mode 100644
index 000000000..a3484df9d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/README.md
@@ -0,0 +1,16 @@
+---
+title: Breaking out of layouts
+---
+
+Ordinarily, a page inherits every layout above it, meaning that `src/routes/a/b/c/+page.svelte` inherits four layouts:
+
+- `src/routes/+layout.svelte`
+- `src/routes/a/+layout.svelte`
+- `src/routes/a/b/+layout.svelte`
+- `src/routes/a/b/c/+layout.svelte`
+
+Occasionally, it's useful to break out of the current layout hierarchy. We can do that by adding the `@` sign followed by the name of the parent segment to 'reset' to — for example `+page@b.svelte` would put `/a/b/c` inside `src/routes/a/b/+layout.svelte`, while `+page@a.svelte` would put it inside `src/routes/a/+layout.svelte`.
+
+Let's reset it all the way to the root layout, by renaming it to `+page@.svelte`.
+
+> The root layout applies to every page of your app, you cannot break out of it.
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte
new file mode 100644
index 000000000..d6c9a2ffa
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+layout.svelte
@@ -0,0 +1,30 @@
+
+ home
+ a
+ a/b
+ a/b/c
+
+
+
+
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..415b7b290
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/+page.svelte
@@ -0,0 +1 @@
+home
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+layout.svelte
new file mode 100644
index 000000000..502a6de62
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+layout.svelte
@@ -0,0 +1,3 @@
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+page.svelte
new file mode 100644
index 000000000..57f9d4079
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/+page.svelte
@@ -0,0 +1 @@
+a
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+layout.svelte
new file mode 100644
index 000000000..0e7880ef2
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+layout.svelte
@@ -0,0 +1,3 @@
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+page.svelte
new file mode 100644
index 000000000..e96ed3db8
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/+page.svelte
@@ -0,0 +1 @@
+b
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+layout.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+layout.svelte
new file mode 100644
index 000000000..c742401ed
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+layout.svelte
@@ -0,0 +1,3 @@
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+page.svelte
new file mode 100644
index 000000000..232c276f8
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-a/src/routes/a/b/c/+page.svelte
@@ -0,0 +1 @@
+c
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page.svelte
new file mode 100644
index 000000000..5d003dc7d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page.svelte
@@ -0,0 +1 @@
+__delete;
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page@.svelte b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page@.svelte
new file mode 100644
index 000000000..232c276f8
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/app-b/src/routes/a/b/c/+page@.svelte
@@ -0,0 +1 @@
+c
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/meta.json b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/meta.json
new file mode 100644
index 000000000..7fbfd5b4f
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/05-breaking-out-of-layouts/meta.json
@@ -0,0 +1,5 @@
+{
+ "editing_constraints": {
+ "create": ["/src/routes/a/b/c/+page@b.svelte", "/src/routes/a/b/c/+page@a.svelte"]
+ }
+}
diff --git a/content/tutorial/04-advanced-sveltekit/03-advanced-routing/meta.json b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/meta.json
new file mode 100644
index 000000000..79b00249d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/03-advanced-routing/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Advanced routing"
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/README.md b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/README.md
new file mode 100644
index 000000000..f622d5a1e
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/README.md
@@ -0,0 +1,40 @@
+---
+title: Using parent data
+---
+
+As we saw in the introduction to [layout data](/tutorial/layout-data), `+page.svelte` and `+layout.svelte` components have access to everything returned from their parent `load` functions.
+
+Occasionally it's useful for the `load` functions themselves to access data from their parents. This can be done with `await parent()`.
+
+To show how it works, we'll sum two numbers that come from different `load` functions. First, return some data from `src/routes/+layout.server.js`:
+
+```js
+/// file: src/routes/+layout.server.js
+export function load() {
+ return { +++a: 1+++ };
+}
+```
+
+Then, get that data in `src/routes/sum/+layout.js`:
+
+```js
+/// file: src/routes/sum/+layout.js
+export async function load(+++{ parent }+++) {
+ +++const { a } = await parent();+++
+ return { +++b: a + 1+++ };
+}
+```
+
+> Notice that a [universal](/tutorial/universal-load-functions) `load` function can get data from a parent _server_ `load` function. The reverse is not true — a server load function can only get parent data from another server load function.
+
+Finally, in `src/routes/sum/+page.js`, get parent data from both `load` functions:
+
+```js
+/// file: src/sum/+page.js
+export async function load(+++{ parent }+++) {
+ +++const { a, b } = await parent();+++
+ return { +++c: a + b+++ };
+}
+```
+
+> Take care not to introduce waterfalls when using `await parent()`. If you can `fetch` other data that is not dependent on parent data, do that first.
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+layout.server.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+layout.server.js
new file mode 100644
index 000000000..f2504d211
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+layout.server.js
@@ -0,0 +1,3 @@
+export async function load() {
+ return {};
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..982aed344
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/+page.svelte
@@ -0,0 +1,2 @@
+if a = 1 and b = a + 1, what is a + b?
+show answer
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+layout.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+layout.js
new file mode 100644
index 000000000..f2504d211
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+layout.js
@@ -0,0 +1,3 @@
+export async function load() {
+ return {};
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.js
new file mode 100644
index 000000000..f2504d211
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.js
@@ -0,0 +1,3 @@
+export async function load() {
+ return {};
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.svelte
new file mode 100644
index 000000000..f3ebf3235
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-a/src/routes/sum/+page.svelte
@@ -0,0 +1,6 @@
+
+
+{data.a} + {data.b} = {data.c}
+home
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/+layout.server.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/+layout.server.js
new file mode 100644
index 000000000..3ca592053
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/+layout.server.js
@@ -0,0 +1,3 @@
+export async function load() {
+ return { a: 1 };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+layout.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+layout.js
new file mode 100644
index 000000000..5fcf59af0
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+layout.js
@@ -0,0 +1,4 @@
+export async function load({ parent }) {
+ const { a } = await parent();
+ return { b: a + 1 };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+page.js
new file mode 100644
index 000000000..1a2674480
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/01-await-parent/app-b/src/routes/sum/+page.js
@@ -0,0 +1,4 @@
+export async function load({ parent }) {
+ const { a, b } = await parent();
+ return { c: a + b };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/README.md b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/README.md
new file mode 100644
index 000000000..6b7cf8443
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/README.md
@@ -0,0 +1,25 @@
+---
+title: Using both load functions
+---
+
+Occasionally, you might need to use a server load function and a universal load function together. For example, you might need to return data from the server, but also return a value that can't be serialized as server data.
+
+In this example we want to return a different component from `load` depending on whether the data we got from `src/routes/+page.server.js` is `cool` or not.
+
+We can access server data in `src/routes/+page.js` via the `data` property:
+
+```js
+/// file: src/routes/+page.js
+export async function load(+++{ data }+++) {
+ const module = +++data.cool+++
+ ? await import('./CoolComponent.svelte')
+ : await import('./BoringComponent.svelte');
+
+ return {
+ component: module.default,
+ message: +++data.message+++
+ };
+}
+```
+
+> Note that the data isn't merged — we must explicitly return `message` from the universal `load` function.
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.js
new file mode 100644
index 000000000..e3669c214
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.js
@@ -0,0 +1,10 @@
+export async function load() {
+ const module = false
+ ? await import('./CoolComponent.svelte')
+ : await import('./BoringComponent.svelte');
+
+ return {
+ component: module.default,
+ message: 'TODO add a message'
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.server.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.server.js
new file mode 100644
index 000000000..81cfcbeaf
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.server.js
@@ -0,0 +1,6 @@
+export async function load() {
+ return {
+ message: 'this data came from the server',
+ cool: true
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..736bcaa2f
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/+page.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/BoringComponent.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/BoringComponent.svelte
new file mode 100644
index 000000000..2a1aeca6d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/BoringComponent.svelte
@@ -0,0 +1,5 @@
+
+
+{message}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/CoolComponent.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/CoolComponent.svelte
new file mode 100644
index 000000000..5681fe375
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-a/src/routes/CoolComponent.svelte
@@ -0,0 +1,14 @@
+
+
+
+ {message}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-b/src/routes/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-b/src/routes/+page.js
new file mode 100644
index 000000000..826cb1b4a
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/02-using-both-load-functions/app-b/src/routes/+page.js
@@ -0,0 +1,10 @@
+export async function load({ data }) {
+ const module = data.cool
+ ? await import('./CoolComponent.svelte')
+ : await import('./BoringComponent.svelte');
+
+ return {
+ component: module.default,
+ message: data.message
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/README.md b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/README.md
new file mode 100644
index 000000000..9925141c4
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/README.md
@@ -0,0 +1,40 @@
+---
+title: Invalidation
+---
+
+When the user navigates from one page to another, SvelteKit calls your `load` functions, but only if it thinks something has changed.
+
+In this example, navigating between timezones causes the `load` function in `src/routes/[...timezone]/+page.js` to re-run because `params.timezone` is invalid. But the `load` function in `src/routes/+layout.js` does _not_ re-run, because as far as SvelteKit is concerned it wasn't invalidated by the navigation.
+
+We can fix that by manually invalidating it using the [`invalidate(...)`](https://kit.svelte.dev/docs/modules#$app-navigation-invalidate) function, which takes a URL and re-runs any `load` functions that depend on it. Because the `load` function in `src/routes/+layout.js` calls `fetch('https://github.com/api/now')`, it depends on `/api/now`.
+
+In `src/routes/[...timezone]/+page.svelte`, add an `onMount` callback that calls `invalidate('/api/now')` once a second:
+
+```svelte
+/// file: src/routes/[...timezone]/+page.svelte
+
+
+
+ {new Intl.DateTimeFormat([], {
+ timeStyle: 'full',
+ timeZone: data.timezone
+ }).format(new Date(data.now))}
+
+```
+
+> You can also pass a function to `invalidate`, in case you want to invalidate based on a pattern and not specific URLs
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.js
new file mode 100644
index 000000000..782e4759d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.js
@@ -0,0 +1,8 @@
+export async function load({ fetch }) {
+ const response = await fetch('https://github.com/api/now');
+ const now = await response.json();
+
+ return {
+ now
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.svelte
new file mode 100644
index 000000000..0e6e3f44b
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+layout.svelte
@@ -0,0 +1,13 @@
+
+ New York
+ São Paulo
+ London
+ Paris
+ Cairo
+ Shanghai
+ Tokyo
+ Sydney
+ Los Angeles
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+page.js
new file mode 100644
index 000000000..714ceb10d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/+page.js
@@ -0,0 +1,5 @@
+import { redirect } from '@sveltejs/kit';
+
+export async function load() {
+ throw redirect(307, '/Europe/London');
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.js
new file mode 100644
index 000000000..6aa85ca1b
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.js
@@ -0,0 +1,5 @@
+export function load({ params }) {
+ return {
+ timezone: params.timezone
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.svelte
new file mode 100644
index 000000000..22976ce1c
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/[...timezone]/+page.svelte
@@ -0,0 +1,10 @@
+
+
+
+ {new Intl.DateTimeFormat([], {
+ timeStyle: 'full',
+ timeZone: data.timezone
+ }).format(new Date(data.now))}
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/api/now/+server.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/api/now/+server.js
new file mode 100644
index 000000000..cd8acc36d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-a/src/routes/api/now/+server.js
@@ -0,0 +1,5 @@
+import { json } from '@sveltejs/kit';
+
+export function GET() {
+ return json(Date.now());
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-b/src/routes/[...timezone]/+page.svelte
new file mode 100644
index 000000000..6722ef9f0
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/03-invalidation/app-b/src/routes/[...timezone]/+page.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {new Intl.DateTimeFormat([], {
+ timeStyle: 'full',
+ timeZone: data.timezone
+ }).format(new Date(data.now))}
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/README.md b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/README.md
new file mode 100644
index 000000000..bb0503d66
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/README.md
@@ -0,0 +1,42 @@
+---
+title: Custom dependencies
+---
+
+Calling `fetch(url)` inside a `load` function registers `url` as a dependency. Sometimes it's not appropriate to use `fetch`, in which case you can specify a dependency manually with the [`depends(url)`](https://kit.svelte.dev/docs/load#invalidation-manual-invalidation) function.
+
+Since any string that begins with an `[a-z]+:` pattern is a valid URL, we can create custom invalidation keys like `data:now`.
+
+Update `src/routes/+layout.js` to return a value directly rather than making a `fetch` call, and add the `depends`:
+
+```js
+/// file: src/routes/+layout.js
+export async function load({ +++depends+++ }) {
+ +++depends('data:now');+++
+
+ return {
+ now: +++Date.now()+++
+ };
+}
+```
+
+Now, update the `invalidate` call in `src/routes/[...timezone]/+page.svelte`:
+
+```svelte
+/// file: src/routes/[...timezone]/+page.svelte
+
+```
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/+layout.js
new file mode 100644
index 000000000..9c3bab4f6
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/+layout.js
@@ -0,0 +1,7 @@
+export async function load({ depends }) {
+ depends('data:now');
+
+ return {
+ now: Date.now()
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte
new file mode 100644
index 000000000..7fcdc2471
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/04-custom-dependencies/app-b/src/routes/[...timezone]/+page.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {new Intl.DateTimeFormat([], {
+ timeStyle: 'full',
+ timeZone: data.timezone
+ }).format(new Date(data.now))}
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/README.md b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/README.md
new file mode 100644
index 000000000..afd34b194
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/README.md
@@ -0,0 +1,42 @@
+---
+title: invalidateAll
+---
+
+Finally, there's the nuclear option — `invalidateAll()`. This will indiscriminately re-run all `load` functions for the current page, regardless of what they depend on.
+
+Update `src/routes/[...timezone]/+page.svelte` from the previous exercise:
+
+```svelte
+/// file: src/routes/[...timezone]/+page.svelte
+
+```
+
+The `depends` call in `src/routes/+layout.js` is no longer necessary:
+
+```js
+/// file: src/routes/+layout.js
+export async function load(---{ depends }---) {
+ ---depends('data:now');---
+
+ return {
+ now: Date.now()
+ };
+}
+```
+
+> `invalidate(() => true)` and `invalidateAll` are _not_ the same. `invalidateAll` also re-runs `load` functions without any `url` dependencies, which `invalidate(() => true)` does not.
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/+layout.js b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/+layout.js
new file mode 100644
index 000000000..6638f2246
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/+layout.js
@@ -0,0 +1,5 @@
+export async function load() {
+ return {
+ now: Date.now()
+ };
+}
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte
new file mode 100644
index 000000000..4276591f6
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/05-invalidate-all/app-b/src/routes/[...timezone]/+page.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {new Intl.DateTimeFormat([], {
+ timeStyle: 'full',
+ timeZone: data.timezone
+ }).format(new Date(data.now))}
+
diff --git a/content/tutorial/04-advanced-sveltekit/04-advanced-loading/meta.json b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/meta.json
new file mode 100644
index 000000000..3c359db66
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/04-advanced-loading/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Advanced loading"
+}
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/README.md b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/README.md
new file mode 100644
index 000000000..be3a2abd7
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/README.md
@@ -0,0 +1,91 @@
+---
+title: $env/static/private
+---
+
+Environment variables — like API keys and database credentials — can be added to a `.env` file, and they will be made available to your application.
+
+> You can also use `.env.local` or `.env.[mode]` files — see the [Vite documentation](https://vitejs.dev/guide/env-and-mode.html#env-files) for more information). Make sure you add any files containing sensitive information to your `.gitignore` file!
+
+In this exercise, we want to allow the user to enter the website if they know the correct passphrase, using an environment variable.
+
+First, in `.env`, add a new environment variable:
+
+```env
+/// file: .env
+PASSPHRASE=+++"open sesame"+++
+```
+
+Open `src/routes/+page.server.js`. Import `PASSPHRASE` from `$env/static/private` and use it inside the [form action](/tutorial/the-form-element):
+
+```js
+/// file: src/routes/+page.server.js
+import { redirect, fail } from '@sveltejs/kit';
++++import { PASSPHRASE } from '$env/static/private';+++
+
+export function load({ cookies }) {
+ if (cookies.get('allowed')) {
+ throw redirect(307, '/welcome');
+ }
+}
+
+export const actions = {
+ default: async ({ request, cookies }) => {
+ const data = await request.formData();
+
+ if (data.get('passphrase') === +++PASSPHRASE+++) {
+ cookies.set('allowed', 'true', {
+ path: '/'
+ });
+
+ throw redirect(303, '/welcome');
+ }
+
+ return fail(403, {
+ incorrect: true
+ });
+ }
+};
+```
+
+The website is now accessible to anyone who knows the correct passphrase.
+
+> Environment variables in `process.env` are also available via `$env/static/private`.
+
+## Keeping secrets
+
+It's important that sensitive data doesn't accidentally end up being sent to the browser, where it could easily be stolen by hackers and scoundrels.
+
+SvelteKit makes it easy to prevent this from happening. Notice what happens if we try to import `PASSPHRASE` into `src/routes/+page.svelte`:
+
+```svelte
+/// file: src/routes/+page.svelte
+
+```
+
+An error overlay pops up, telling us that `$env/static/private` cannot be imported into client-side code. It can only be imported into server modules:
+
+- `+page.server.js`
+- `+layout.server.js`
+- `+server.js`
+- any modules ending with `.server.js`
+- any modules inside `src/lib/server`
+
+In turn, these modules can only be imported by _other_ server modules.
+
+## Static vs dynamic
+
+The `static` in `$env/static/private` indicates that these values are known at build time, and can be _statically replaced_. This enables useful optimisations:
+
+```js
+import { FEATURE_FLAG_X } from '$env/static/private';
+
+if (FEATURE_FLAG_X === 'enabled') {
+ // code in here will be removed from the build output
+ // if FEATURE_FLAG_X is not enabled
+}
+```
+
+In some cases you might need to refer to environment variables that are _dynamic_ — in other words, not known until we run the app. We'll cover this case in the next exercise.
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/.env b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/.env
new file mode 100644
index 000000000..33ea5138a
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/.env
@@ -0,0 +1 @@
+PASSPHRASE=
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.server.js
new file mode 100644
index 000000000..ebd2be099
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.server.js
@@ -0,0 +1,25 @@
+import { redirect, fail } from '@sveltejs/kit';
+
+export function load({ cookies }) {
+ if (cookies.get('allowed')) {
+ throw redirect(307, '/welcome');
+ }
+}
+
+export const actions = {
+ default: async ({ request, cookies }) => {
+ const data = await request.formData();
+
+ if (data.get('passphrase') === 'TODO') {
+ cookies.set('allowed', 'true', {
+ path: '/'
+ });
+
+ throw redirect(303, '/welcome');
+ }
+
+ return fail(403, {
+ incorrect: true
+ });
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..a848d87bb
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/+page.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+{#if form?.incorrect}
+ wrong passphrase!
+{/if}
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.server.js
new file mode 100644
index 000000000..87b01cea1
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.server.js
@@ -0,0 +1,15 @@
+import { redirect } from '@sveltejs/kit';
+import { error } from '@sveltejs/kit';
+
+export function load({ cookies }) {
+ if (!cookies.get('allowed')) {
+ throw error(403, 'Forbidden');
+ }
+}
+
+export const actions = {
+ default: ({ cookies }) => {
+ cookies.delete('allowed', { path: '/' });
+ throw redirect(303, '/');
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.svelte
new file mode 100644
index 000000000..3a1970178
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-a/src/routes/welcome/+page.svelte
@@ -0,0 +1,5 @@
+welcome!
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/.env b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/.env
new file mode 100644
index 000000000..f090472cc
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/.env
@@ -0,0 +1 @@
+PASSPHRASE="open sesame"
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/src/routes/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/src/routes/+page.server.js
new file mode 100644
index 000000000..761edc1d0
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/01-env-static-private/app-b/src/routes/+page.server.js
@@ -0,0 +1,26 @@
+import { redirect, fail } from '@sveltejs/kit';
+import { PASSPHRASE } from '$env/static/private';
+
+export function load({ cookies }) {
+ if (cookies.get('allowed')) {
+ throw redirect(307, '/welcome');
+ }
+}
+
+export const actions = {
+ default: async ({ request, cookies }) => {
+ const data = await request.formData();
+
+ if (data.get('passphrase') === PASSPHRASE) {
+ cookies.set('allowed', 'true', {
+ path: '/'
+ });
+
+ throw redirect(303, '/welcome');
+ }
+
+ return fail(403, {
+ incorrect: true
+ });
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/README.md b/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/README.md
new file mode 100644
index 000000000..4f7051798
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/README.md
@@ -0,0 +1,36 @@
+---
+title: $env/dynamic/private
+---
+
+If you need to read the values of environment variables when the app runs, as opposed to when the app is built, you can use `$env/dynamic/private` instead of `$env/static/private`:
+
+```js
+/// file: src/routes/+page.server.js
+import { redirect, fail } from '@sveltejs/kit';
+import { +++env+++ } from '$env/+++dynamic+++/private';
+
+export function load({ cookies }) {
+ if (cookies.get('allowed')) {
+ throw redirect(307, '/welcome');
+ }
+}
+
+export const actions = {
+ default: async ({ request, cookies }) => {
+ const data = await request.formData();
+
+ if (data.get('passphrase') === +++env.+++PASSPHRASE) {
+ cookies.set('allowed', 'true', {
+ path: '/'
+ });
+
+ throw redirect(303, '/welcome');
+ }
+
+ return fail(403, {
+ incorrect: true
+ });
+ }
+};
+
+```
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/app-b/src/routes/+page.server.js b/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/app-b/src/routes/+page.server.js
new file mode 100644
index 000000000..3339bff13
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/02-env-dynamic-private/app-b/src/routes/+page.server.js
@@ -0,0 +1,26 @@
+import { redirect, fail } from '@sveltejs/kit';
+import { env } from '$env/dynamic/private';
+
+export function load({ cookies }) {
+ if (cookies.get('allowed')) {
+ throw redirect(307, '/welcome');
+ }
+}
+
+export const actions = {
+ default: async ({ request, cookies }) => {
+ const data = await request.formData();
+
+ if (data.get('passphrase') === env.PASSPHRASE) {
+ cookies.set('allowed', 'true', {
+ path: '/'
+ });
+
+ throw redirect(303, '/welcome');
+ }
+
+ return fail(403, {
+ incorrect: true
+ });
+ }
+};
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/README.md b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/README.md
new file mode 100644
index 000000000..2f4e10d22
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/README.md
@@ -0,0 +1,26 @@
+---
+title: $env/static/public
+---
+
+Some environment variables _can_ be safely exposed to the browser. These are distinguished from private environment variables with a `PUBLIC_` prefix.
+
+Add values to the two public environment variables in `.env`:
+
+```env
+PUBLIC_THEME_BACKGROUND=+++"steelblue"+++
+PUBLIC_THEME_FOREGROUND=+++"bisque"+++
+```
+
+Then, import them into `src/routes/+page.svelte`:
+
+```svelte
+/// file: src/routes/+page.svelte
+
+```
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/.env b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/.env
new file mode 100644
index 000000000..598d2ba2c
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/.env
@@ -0,0 +1,2 @@
+PUBLIC_THEME_BACKGROUND=
+PUBLIC_THEME_FOREGROUND=
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/src/routes/+page.svelte
new file mode 100644
index 000000000..846ee5734
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-a/src/routes/+page.svelte
@@ -0,0 +1,25 @@
+
+
+
+ {PUBLIC_THEME_FOREGROUND} on {PUBLIC_THEME_BACKGROUND}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/.env b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/.env
new file mode 100644
index 000000000..b5880e0f0
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/.env
@@ -0,0 +1,2 @@
+PUBLIC_THEME_BACKGROUND="steelblue"
+PUBLIC_THEME_FOREGROUND="bisque"
\ No newline at end of file
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/src/routes/+page.svelte
new file mode 100644
index 000000000..1b1eff3cb
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/03-env-static-public/app-b/src/routes/+page.svelte
@@ -0,0 +1,27 @@
+
+
+
+ {PUBLIC_THEME_FOREGROUND} on {PUBLIC_THEME_BACKGROUND}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/README.md b/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/README.md
new file mode 100644
index 000000000..8f0bb8ee9
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/README.md
@@ -0,0 +1,18 @@
+---
+title: $env/static/public
+---
+
+As with [private environment variables](/tutorial/env-static-private), it's preferable to use static values if possible, but if necessary we can use dynamic values instead:
+
+```svelte
+
+
+
+ {+++env.+++PUBLIC_THEME_FOREGROUND} on {+++env.+++PUBLIC_THEME_BACKGROUND}
+
+```
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/app-b/src/routes/+page.svelte b/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/app-b/src/routes/+page.svelte
new file mode 100644
index 000000000..f305b3b4d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/04-env-dynamic-public/app-b/src/routes/+page.svelte
@@ -0,0 +1,24 @@
+
+
+
+ {env.PUBLIC_THEME_FOREGROUND} on {env.PUBLIC_THEME_BACKGROUND}
+
+
+
diff --git a/content/tutorial/04-advanced-sveltekit/05-environment-variables/meta.json b/content/tutorial/04-advanced-sveltekit/05-environment-variables/meta.json
new file mode 100644
index 000000000..6f066bc4d
--- /dev/null
+++ b/content/tutorial/04-advanced-sveltekit/05-environment-variables/meta.json
@@ -0,0 +1,3 @@
+{
+ "title": "Environment variables"
+}
diff --git a/content/tutorial/common/package-lock.json b/content/tutorial/common/package-lock.json
new file mode 100644
index 000000000..b5bcfb4da
--- /dev/null
+++ b/content/tutorial/common/package-lock.json
@@ -0,0 +1,1440 @@
+{
+ "name": "~TODO~",
+ "version": "0.0.1",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "~TODO~",
+ "version": "0.0.1",
+ "devDependencies": {
+ "@sveltejs/kit": "next",
+ "esbuild-wasm": "^0.16.4",
+ "svelte": "^3.54.0",
+ "vite": "^4.0.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.4.tgz",
+ "integrity": "sha512-rZzb7r22m20S1S7ufIc6DC6W659yxoOrl7sKP1nCYhuvUlnCFHVSbATG4keGUtV8rDz11sRRDbWkvQZpzPaHiw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.4.tgz",
+ "integrity": "sha512-VPuTzXFm/m2fcGfN6CiwZTlLzxrKsWbPkG7ArRFpuxyaHUm/XFHQPD4xNwZT6uUmpIHhnSjcaCmcla8COzmZ5Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.4.tgz",
+ "integrity": "sha512-MW+B2O++BkcOfMWmuHXB15/l1i7wXhJFqbJhp82IBOais8RBEQv2vQz/jHrDEHaY2X0QY7Wfw86SBL2PbVOr0g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.4.tgz",
+ "integrity": "sha512-a28X1O//aOfxwJVZVs7ZfM8Tyih2Za4nKJrBwW5Wm4yKsnwBy9aiS/xwpxiiTRttw3EaTg4Srerhcm6z0bu9Wg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.4.tgz",
+ "integrity": "sha512-e3doCr6Ecfwd7VzlaQqEPrnbvvPjE9uoTpxG5pyLzr2rI2NMjDHmvY1E5EO81O/e9TUOLLkXA5m6T8lfjK9yAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.4.tgz",
+ "integrity": "sha512-Oup3G/QxBgvvqnXWrBed7xxkFNwAwJVHZcklWyQt7YCAL5bfUkaa6FVWnR78rNQiM8MqqLiT6ZTZSdUFuVIg1w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.4.tgz",
+ "integrity": "sha512-vAP+eYOxlN/Bpo/TZmzEQapNS8W1njECrqkTpNgvXskkkJC2AwOXwZWai/Kc2vEFZUXQttx6UJbj9grqjD/+9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.4.tgz",
+ "integrity": "sha512-A47ZmtpIPyERxkSvIv+zLd6kNIOtJH03XA0Hy7jaceRDdQaQVGSDt4mZqpWqJYgDk9rg96aglbF6kCRvPGDSUA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.4.tgz",
+ "integrity": "sha512-2zXoBhv4r5pZiyjBKrOdFP4CXOChxXiYD50LRUU+65DkdS5niPFHbboKZd/c81l0ezpw7AQnHeoCy5hFrzzs4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.4.tgz",
+ "integrity": "sha512-uxdSrpe9wFhz4yBwt2kl2TxS/NWEINYBUFIxQtaEVtglm1eECvsj1vEKI0KX2k2wCe17zDdQ3v+jVxfwVfvvjw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.4.tgz",
+ "integrity": "sha512-peDrrUuxbZ9Jw+DwLCh/9xmZAk0p0K1iY5d2IcwmnN+B87xw7kujOkig6ZRcZqgrXgeRGurRHn0ENMAjjD5DEg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.4.tgz",
+ "integrity": "sha512-sD9EEUoGtVhFjjsauWjflZklTNr57KdQ6xfloO4yH1u7vNQlOfAlhEzbyBKfgbJlW7rwXYBdl5/NcZ+Mg2XhQA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.4.tgz",
+ "integrity": "sha512-X1HSqHUX9D+d0l6/nIh4ZZJ94eQky8d8z6yxAptpZE3FxCWYWvTDd9X9ST84MGZEJx04VYUD/AGgciddwO0b8g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.4.tgz",
+ "integrity": "sha512-97ANpzyNp0GTXCt6SRdIx1ngwncpkV/z453ZuxbnBROCJ5p/55UjhbaG23UdHj88fGWLKPFtMoU4CBacz4j9FA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.4.tgz",
+ "integrity": "sha512-pUvPQLPmbEeJRPjP0DYTC1vjHyhrnCklQmCGYbipkep+oyfTn7GTBJXoPodR7ZS5upmEyc8lzAkn2o29wD786A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.4.tgz",
+ "integrity": "sha512-N55Q0mJs3Sl8+utPRPBrL6NLYZKBCLLx0bme/+RbjvMforTGGzFvsRl4xLTZMUBFC1poDzBEPTEu5nxizQ9Nlw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.4.tgz",
+ "integrity": "sha512-LHSJLit8jCObEQNYkgsDYBh2JrJT53oJO2HVdkSYLa6+zuLJh0lAr06brXIkljrlI+N7NNW1IAXGn/6IZPi3YQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.4.tgz",
+ "integrity": "sha512-nLgdc6tWEhcCFg/WVFaUxHcPK3AP/bh+KEwKtl69Ay5IBqUwKDaq/6Xk0E+fh/FGjnLwqFSsarsbPHeKM8t8Sw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.4.tgz",
+ "integrity": "sha512-08SluG24GjPO3tXKk95/85n9kpyZtXCVwURR2i4myhrOfi3jspClV0xQQ0W0PYWHioJj+LejFMt41q+PG3mlAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.4.tgz",
+ "integrity": "sha512-yYiRDQcqLYQSvNQcBKN7XogbrSvBE45FEQdH8fuXPl7cngzkCvpsG2H9Uey39IjQ6gqqc+Q4VXYHsQcKW0OMjQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.4.tgz",
+ "integrity": "sha512-5rabnGIqexekYkh9zXG5waotq8mrdlRoBqAktjx2W3kb0zsI83mdCwrcAeKYirnUaTGztR5TxXcXmQrEzny83w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.4.tgz",
+ "integrity": "sha512-sN/I8FMPtmtT2Yw+Dly8Ur5vQ5a/RmC8hW7jO9PtPSQUPkowxWpcUZnqOggU7VwyT3Xkj6vcXWd3V/qTXwultQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.21",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
+ "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
+ "dev": true
+ },
+ "node_modules/@sveltejs/kit": {
+ "version": "1.0.0-next.584",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.584.tgz",
+ "integrity": "sha512-iBfrrwkza1szR1GVMorTjj1Yw3SXhDVB5MMdDzCMKqKcCwxCehQ3K6QnlmyXHtHg2qX5rfvz0cpkp0uGGmcxQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@sveltejs/vite-plugin-svelte": "^2.0.0",
+ "@types/cookie": "^0.5.1",
+ "cookie": "^0.5.0",
+ "devalue": "^4.2.0",
+ "esm-env": "^1.0.0",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.27.0",
+ "mime": "^3.0.0",
+ "sade": "^1.8.1",
+ "set-cookie-parser": "^2.5.1",
+ "sirv": "^2.0.2",
+ "tiny-glob": "^0.2.9",
+ "undici": "5.14.0"
+ },
+ "bin": {
+ "svelte-kit": "svelte-kit.js"
+ },
+ "engines": {
+ "node": ">=16.14"
+ },
+ "peerDependencies": {
+ "svelte": "^3.54.0",
+ "vite": "^4.0.0"
+ }
+ },
+ "node_modules/@sveltejs/vite-plugin-svelte": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.0.2.tgz",
+ "integrity": "sha512-xCEan0/NNpQuL0l5aS42FjwQ6wwskdxC3pW1OeFtEKNZwRg7Evro9lac9HesGP6TdFsTv2xMes5ASQVKbCacxg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "deepmerge": "^4.2.2",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.27.0",
+ "svelte-hmr": "^0.15.1",
+ "vitefu": "^0.2.3"
+ },
+ "engines": {
+ "node": "^14.18.0 || >= 16"
+ },
+ "peerDependencies": {
+ "svelte": "^3.54.0",
+ "vite": "^4.0.0"
+ }
+ },
+ "node_modules/@types/cookie": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz",
+ "integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==",
+ "dev": true
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dev": true,
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.2.0.tgz",
+ "integrity": "sha512-mbjoAaCL2qogBKgeFxFPOXAUsZchircF+B/79LD4sHH0+NHfYm8gZpQrskKDn5gENGt35+5OI1GUF7hLVnkPDw==",
+ "dev": true
+ },
+ "node_modules/esbuild": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.4.tgz",
+ "integrity": "sha512-qQrPMQpPTWf8jHugLWHoGqZjApyx3OEm76dlTXobHwh/EBbavbRdjXdYi/GWr43GyN0sfpap14GPkb05NH3ROA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.16.4",
+ "@esbuild/android-arm64": "0.16.4",
+ "@esbuild/android-x64": "0.16.4",
+ "@esbuild/darwin-arm64": "0.16.4",
+ "@esbuild/darwin-x64": "0.16.4",
+ "@esbuild/freebsd-arm64": "0.16.4",
+ "@esbuild/freebsd-x64": "0.16.4",
+ "@esbuild/linux-arm": "0.16.4",
+ "@esbuild/linux-arm64": "0.16.4",
+ "@esbuild/linux-ia32": "0.16.4",
+ "@esbuild/linux-loong64": "0.16.4",
+ "@esbuild/linux-mips64el": "0.16.4",
+ "@esbuild/linux-ppc64": "0.16.4",
+ "@esbuild/linux-riscv64": "0.16.4",
+ "@esbuild/linux-s390x": "0.16.4",
+ "@esbuild/linux-x64": "0.16.4",
+ "@esbuild/netbsd-x64": "0.16.4",
+ "@esbuild/openbsd-x64": "0.16.4",
+ "@esbuild/sunos-x64": "0.16.4",
+ "@esbuild/win32-arm64": "0.16.4",
+ "@esbuild/win32-ia32": "0.16.4",
+ "@esbuild/win32-x64": "0.16.4"
+ }
+ },
+ "node_modules/esbuild-wasm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.16.4.tgz",
+ "integrity": "sha512-Nh7aa9uazooaEIGubc8s0nQZFhnf035pJMTpMPBonzDchN6RPsQES5bojQo3zT2xSAuC9nEMg8Nxzc1iwigETw==",
+ "dev": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esm-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
+ "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/globalyzer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
+ "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
+ "dev": true
+ },
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
+ "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.13"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
+ "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/postcss": {
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.3.tgz",
+ "integrity": "sha512-7e68MQbAWCX6mI4/0lG1WHd+NdNAlVamg0Zkd+8LZ/oXojligdGnCNyHlzXqXCZObyjs5FRc3AH0b17iJESGIQ==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "dependencies": {
+ "mri": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz",
+ "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==",
+ "dev": true
+ },
+ "node_modules/sirv": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz",
+ "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==",
+ "dev": true,
+ "dependencies": {
+ "@polka/url": "^1.0.0-next.20",
+ "mrmime": "^1.0.0",
+ "totalist": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/svelte": {
+ "version": "3.54.0",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.54.0.tgz",
+ "integrity": "sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/svelte-hmr": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz",
+ "integrity": "sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20 || ^14.13.1 || >= 16"
+ },
+ "peerDependencies": {
+ "svelte": ">=3.19.0"
+ }
+ },
+ "node_modules/tiny-glob": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
+ "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
+ "dev": true,
+ "dependencies": {
+ "globalyzer": "0.1.0",
+ "globrex": "^0.1.2"
+ }
+ },
+ "node_modules/totalist": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
+ "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/undici": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz",
+ "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==",
+ "dev": true,
+ "dependencies": {
+ "busboy": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=12.18"
+ }
+ },
+ "node_modules/vite": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.0.tgz",
+ "integrity": "sha512-ynad+4kYs8Jcnn8J7SacS9vAbk7eMy0xWg6E7bAhS1s79TK+D7tVFGXVZ55S7RNLRROU1rxoKlvZ/qjaB41DGA==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.16.3",
+ "postcss": "^8.4.19",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.3.tgz",
+ "integrity": "sha512-75l7TTuU8isAhz1QFtNKjDkqjxvndfMC1AfIMjJ0ZQ59ZD0Ow9QOIsJJX16Wv9PS8f+zMzp6fHy5cCbKG/yVUQ==",
+ "dev": true,
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "@esbuild/android-arm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.4.tgz",
+ "integrity": "sha512-rZzb7r22m20S1S7ufIc6DC6W659yxoOrl7sKP1nCYhuvUlnCFHVSbATG4keGUtV8rDz11sRRDbWkvQZpzPaHiw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.4.tgz",
+ "integrity": "sha512-VPuTzXFm/m2fcGfN6CiwZTlLzxrKsWbPkG7ArRFpuxyaHUm/XFHQPD4xNwZT6uUmpIHhnSjcaCmcla8COzmZ5Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.4.tgz",
+ "integrity": "sha512-MW+B2O++BkcOfMWmuHXB15/l1i7wXhJFqbJhp82IBOais8RBEQv2vQz/jHrDEHaY2X0QY7Wfw86SBL2PbVOr0g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.4.tgz",
+ "integrity": "sha512-a28X1O//aOfxwJVZVs7ZfM8Tyih2Za4nKJrBwW5Wm4yKsnwBy9aiS/xwpxiiTRttw3EaTg4Srerhcm6z0bu9Wg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.4.tgz",
+ "integrity": "sha512-e3doCr6Ecfwd7VzlaQqEPrnbvvPjE9uoTpxG5pyLzr2rI2NMjDHmvY1E5EO81O/e9TUOLLkXA5m6T8lfjK9yAA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.4.tgz",
+ "integrity": "sha512-Oup3G/QxBgvvqnXWrBed7xxkFNwAwJVHZcklWyQt7YCAL5bfUkaa6FVWnR78rNQiM8MqqLiT6ZTZSdUFuVIg1w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.4.tgz",
+ "integrity": "sha512-vAP+eYOxlN/Bpo/TZmzEQapNS8W1njECrqkTpNgvXskkkJC2AwOXwZWai/Kc2vEFZUXQttx6UJbj9grqjD/+9Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.4.tgz",
+ "integrity": "sha512-A47ZmtpIPyERxkSvIv+zLd6kNIOtJH03XA0Hy7jaceRDdQaQVGSDt4mZqpWqJYgDk9rg96aglbF6kCRvPGDSUA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.4.tgz",
+ "integrity": "sha512-2zXoBhv4r5pZiyjBKrOdFP4CXOChxXiYD50LRUU+65DkdS5niPFHbboKZd/c81l0ezpw7AQnHeoCy5hFrzzs4g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ia32": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.4.tgz",
+ "integrity": "sha512-uxdSrpe9wFhz4yBwt2kl2TxS/NWEINYBUFIxQtaEVtglm1eECvsj1vEKI0KX2k2wCe17zDdQ3v+jVxfwVfvvjw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.4.tgz",
+ "integrity": "sha512-peDrrUuxbZ9Jw+DwLCh/9xmZAk0p0K1iY5d2IcwmnN+B87xw7kujOkig6ZRcZqgrXgeRGurRHn0ENMAjjD5DEg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-mips64el": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.4.tgz",
+ "integrity": "sha512-sD9EEUoGtVhFjjsauWjflZklTNr57KdQ6xfloO4yH1u7vNQlOfAlhEzbyBKfgbJlW7rwXYBdl5/NcZ+Mg2XhQA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ppc64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.4.tgz",
+ "integrity": "sha512-X1HSqHUX9D+d0l6/nIh4ZZJ94eQky8d8z6yxAptpZE3FxCWYWvTDd9X9ST84MGZEJx04VYUD/AGgciddwO0b8g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-riscv64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.4.tgz",
+ "integrity": "sha512-97ANpzyNp0GTXCt6SRdIx1ngwncpkV/z453ZuxbnBROCJ5p/55UjhbaG23UdHj88fGWLKPFtMoU4CBacz4j9FA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-s390x": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.4.tgz",
+ "integrity": "sha512-pUvPQLPmbEeJRPjP0DYTC1vjHyhrnCklQmCGYbipkep+oyfTn7GTBJXoPodR7ZS5upmEyc8lzAkn2o29wD786A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.4.tgz",
+ "integrity": "sha512-N55Q0mJs3Sl8+utPRPBrL6NLYZKBCLLx0bme/+RbjvMforTGGzFvsRl4xLTZMUBFC1poDzBEPTEu5nxizQ9Nlw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/netbsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.4.tgz",
+ "integrity": "sha512-LHSJLit8jCObEQNYkgsDYBh2JrJT53oJO2HVdkSYLa6+zuLJh0lAr06brXIkljrlI+N7NNW1IAXGn/6IZPi3YQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/openbsd-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.4.tgz",
+ "integrity": "sha512-nLgdc6tWEhcCFg/WVFaUxHcPK3AP/bh+KEwKtl69Ay5IBqUwKDaq/6Xk0E+fh/FGjnLwqFSsarsbPHeKM8t8Sw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/sunos-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.4.tgz",
+ "integrity": "sha512-08SluG24GjPO3tXKk95/85n9kpyZtXCVwURR2i4myhrOfi3jspClV0xQQ0W0PYWHioJj+LejFMt41q+PG3mlAQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-arm64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.4.tgz",
+ "integrity": "sha512-yYiRDQcqLYQSvNQcBKN7XogbrSvBE45FEQdH8fuXPl7cngzkCvpsG2H9Uey39IjQ6gqqc+Q4VXYHsQcKW0OMjQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-ia32": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.4.tgz",
+ "integrity": "sha512-5rabnGIqexekYkh9zXG5waotq8mrdlRoBqAktjx2W3kb0zsI83mdCwrcAeKYirnUaTGztR5TxXcXmQrEzny83w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.4.tgz",
+ "integrity": "sha512-sN/I8FMPtmtT2Yw+Dly8Ur5vQ5a/RmC8hW7jO9PtPSQUPkowxWpcUZnqOggU7VwyT3Xkj6vcXWd3V/qTXwultQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "@polka/url": {
+ "version": "1.0.0-next.21",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
+ "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
+ "dev": true
+ },
+ "@sveltejs/kit": {
+ "version": "1.0.0-next.584",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.584.tgz",
+ "integrity": "sha512-iBfrrwkza1szR1GVMorTjj1Yw3SXhDVB5MMdDzCMKqKcCwxCehQ3K6QnlmyXHtHg2qX5rfvz0cpkp0uGGmcxQw==",
+ "dev": true,
+ "requires": {
+ "@sveltejs/vite-plugin-svelte": "^2.0.0",
+ "@types/cookie": "^0.5.1",
+ "cookie": "^0.5.0",
+ "devalue": "^4.2.0",
+ "esm-env": "^1.0.0",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.27.0",
+ "mime": "^3.0.0",
+ "sade": "^1.8.1",
+ "set-cookie-parser": "^2.5.1",
+ "sirv": "^2.0.2",
+ "tiny-glob": "^0.2.9",
+ "undici": "5.14.0"
+ }
+ },
+ "@sveltejs/vite-plugin-svelte": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.0.2.tgz",
+ "integrity": "sha512-xCEan0/NNpQuL0l5aS42FjwQ6wwskdxC3pW1OeFtEKNZwRg7Evro9lac9HesGP6TdFsTv2xMes5ASQVKbCacxg==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "deepmerge": "^4.2.2",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.27.0",
+ "svelte-hmr": "^0.15.1",
+ "vitefu": "^0.2.3"
+ }
+ },
+ "@types/cookie": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz",
+ "integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==",
+ "dev": true
+ },
+ "busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dev": true,
+ "requires": {
+ "streamsearch": "^1.1.0"
+ }
+ },
+ "cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true
+ },
+ "devalue": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.2.0.tgz",
+ "integrity": "sha512-mbjoAaCL2qogBKgeFxFPOXAUsZchircF+B/79LD4sHH0+NHfYm8gZpQrskKDn5gENGt35+5OI1GUF7hLVnkPDw==",
+ "dev": true
+ },
+ "esbuild": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.4.tgz",
+ "integrity": "sha512-qQrPMQpPTWf8jHugLWHoGqZjApyx3OEm76dlTXobHwh/EBbavbRdjXdYi/GWr43GyN0sfpap14GPkb05NH3ROA==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.16.4",
+ "@esbuild/android-arm64": "0.16.4",
+ "@esbuild/android-x64": "0.16.4",
+ "@esbuild/darwin-arm64": "0.16.4",
+ "@esbuild/darwin-x64": "0.16.4",
+ "@esbuild/freebsd-arm64": "0.16.4",
+ "@esbuild/freebsd-x64": "0.16.4",
+ "@esbuild/linux-arm": "0.16.4",
+ "@esbuild/linux-arm64": "0.16.4",
+ "@esbuild/linux-ia32": "0.16.4",
+ "@esbuild/linux-loong64": "0.16.4",
+ "@esbuild/linux-mips64el": "0.16.4",
+ "@esbuild/linux-ppc64": "0.16.4",
+ "@esbuild/linux-riscv64": "0.16.4",
+ "@esbuild/linux-s390x": "0.16.4",
+ "@esbuild/linux-x64": "0.16.4",
+ "@esbuild/netbsd-x64": "0.16.4",
+ "@esbuild/openbsd-x64": "0.16.4",
+ "@esbuild/sunos-x64": "0.16.4",
+ "@esbuild/win32-arm64": "0.16.4",
+ "@esbuild/win32-ia32": "0.16.4",
+ "@esbuild/win32-x64": "0.16.4"
+ }
+ },
+ "esbuild-wasm": {
+ "version": "0.16.4",
+ "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.16.4.tgz",
+ "integrity": "sha512-Nh7aa9uazooaEIGubc8s0nQZFhnf035pJMTpMPBonzDchN6RPsQES5bojQo3zT2xSAuC9nEMg8Nxzc1iwigETw==",
+ "dev": true
+ },
+ "esm-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
+ "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "globalyzer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
+ "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
+ "dev": true
+ },
+ "globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true
+ },
+ "magic-string": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
+ "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/sourcemap-codec": "^1.4.13"
+ }
+ },
+ "mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "dev": true
+ },
+ "mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true
+ },
+ "mrmime": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
+ "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "rollup": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.3.tgz",
+ "integrity": "sha512-7e68MQbAWCX6mI4/0lG1WHd+NdNAlVamg0Zkd+8LZ/oXojligdGnCNyHlzXqXCZObyjs5FRc3AH0b17iJESGIQ==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "requires": {
+ "mri": "^1.1.0"
+ }
+ },
+ "set-cookie-parser": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz",
+ "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==",
+ "dev": true
+ },
+ "sirv": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz",
+ "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==",
+ "dev": true,
+ "requires": {
+ "@polka/url": "^1.0.0-next.20",
+ "mrmime": "^1.0.0",
+ "totalist": "^3.0.0"
+ }
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true
+ },
+ "streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "dev": true
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "svelte": {
+ "version": "3.54.0",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.54.0.tgz",
+ "integrity": "sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==",
+ "dev": true
+ },
+ "svelte-hmr": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz",
+ "integrity": "sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==",
+ "dev": true,
+ "requires": {}
+ },
+ "tiny-glob": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
+ "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
+ "dev": true,
+ "requires": {
+ "globalyzer": "0.1.0",
+ "globrex": "^0.1.2"
+ }
+ },
+ "totalist": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
+ "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==",
+ "dev": true
+ },
+ "undici": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz",
+ "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==",
+ "dev": true,
+ "requires": {
+ "busboy": "^1.6.0"
+ }
+ },
+ "vite": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.0.tgz",
+ "integrity": "sha512-ynad+4kYs8Jcnn8J7SacS9vAbk7eMy0xWg6E7bAhS1s79TK+D7tVFGXVZ55S7RNLRROU1rxoKlvZ/qjaB41DGA==",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.16.3",
+ "fsevents": "~2.3.2",
+ "postcss": "^8.4.19",
+ "resolve": "^1.22.1",
+ "rollup": "^3.7.0"
+ }
+ },
+ "vitefu": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.3.tgz",
+ "integrity": "sha512-75l7TTuU8isAhz1QFtNKjDkqjxvndfMC1AfIMjJ0ZQ59ZD0Ow9QOIsJJX16Wv9PS8f+zMzp6fHy5cCbKG/yVUQ==",
+ "dev": true,
+ "requires": {}
+ }
+ }
+}
diff --git a/content/tutorial/common/package.json b/content/tutorial/common/package.json
index 01bd06954..7243df8c4 100644
--- a/content/tutorial/common/package.json
+++ b/content/tutorial/common/package.json
@@ -8,9 +8,9 @@
},
"devDependencies": {
"@sveltejs/kit": "next",
- "esbuild-wasm": "^0.14.43",
- "svelte": "^3.53.1",
- "vite": "^3.2.5"
+ "esbuild-wasm": "^0.16.4",
+ "svelte": "^3.54.0",
+ "vite": "^4.0.0"
},
"type": "module"
}
diff --git a/content/tutorial/common/src/__client.js b/content/tutorial/common/src/__client.js
index 1dc7420e9..7bb766697 100644
--- a/content/tutorial/common/src/__client.js
+++ b/content/tutorial/common/src/__client.js
@@ -15,7 +15,10 @@ window.addEventListener('message', async (e) => {
const css_files = [];
for (const { name, code } of transformed) {
- if (name.endsWith('.svelte') && code.includes('svelte&type=style&lang.css')) {
+ if (
+ name.endsWith('.svelte') &&
+ code.includes('svelte&type=style&lang.css')
+ ) {
css_files.push(name + '?svelte&type=style&lang.css');
}
}
@@ -56,7 +59,7 @@ function ping() {
);
}
-setInterval(ping, 200);
+setInterval(ping, 50);
ping();
if (import.meta.hot) {
diff --git a/content/tutorial/common/src/app.html b/content/tutorial/common/src/app.html
index 2f8367462..a81dfbad1 100644
--- a/content/tutorial/common/src/app.html
+++ b/content/tutorial/common/src/app.html
@@ -5,8 +5,56 @@
%sveltekit.head%
+
+
- %sveltekit.body%
+ %sveltekit.body%