Repository: sveltejs/kit
Pull request #6099 (2022-08-19 19:38:07)

Revert "[feat] Suggest props destructuring if possible"
Reverts sveltejs/kit#6069. Unfortunately this creates buggy code, because the destructured values aren't first assigned until after the `<script>` contents execute.

People need to manually migrate this stuff. Offering a half measure with gotchas is worse than doing nothing IMHO.

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: dda9004ac14c6e1e5cb79c927e7ae48fcc03f45d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/sveltejs/kit/new/revert-6069-migration-props-conversion?filename=.changeset/forty-llamas-lick.md&value=---%0A%22svelte-migrate%22%3A%20patch%0A---%0A%0ARevert%20%22%5Bfeat%5D%20Suggest%20props%20destructuring%20if%20possible%22%0A)


Rich-Harris: I'm not sure what the proper protocol around changesets is when reverting. Should the deleted changeset stay deleted, and should we add a new changeset?
dummdidumm: The old changeset stays (no deletion) and you add a new one.
Btw I didn't know if this behavior previously, guess I never ran into it 😅 

Patch:
diff --git a/.changeset/beige-drinks-melt.md b/.changeset/beige-drinks-melt.md
new file mode 100644
index 000000000..15672c753
--- /dev/null
+++ b/.changeset/beige-drinks-melt.md
@@ -0,0 +1,5 @@
+---
+'svelte-migrate': patch
+---
+
+Revert change to suggest props destructuring
diff --git a/.changeset/gentle-years-leave.md b/.changeset/gentle-years-leave.md
new file mode 100644
index 000000000..9b512b8dc
--- /dev/null
+++ b/.changeset/gentle-years-leave.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Allow `$app/stores` to be used from anywhere on the browser
diff --git a/.changeset/hot-lions-cough.md b/.changeset/hot-lions-cough.md
new file mode 100644
index 000000000..65b0719b9
--- /dev/null
+++ b/.changeset/hot-lions-cough.md
@@ -0,0 +1,5 @@
+---
+'create-svelte': patch
+---
+
+Add notes about includes/excludes and path aliases
diff --git a/.changeset/kind-tools-shop.md b/.changeset/kind-tools-shop.md
new file mode 100644
index 000000000..6e6c04ccf
--- /dev/null
+++ b/.changeset/kind-tools-shop.md
@@ -0,0 +1,5 @@
+---
+'create-svelte': patch
+---
+
+setup prettier plugin-search-dirs to enable use with pnpm
diff --git a/.changeset/ninety-walls-heal.md b/.changeset/ninety-walls-heal.md
new file mode 100644
index 000000000..3c270bbb0
--- /dev/null
+++ b/.changeset/ninety-walls-heal.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+use `enumerable: false` on "[x] no longer exists" getters so that they are not triggered by spreading
diff --git a/.changeset/olive-ducks-talk.md b/.changeset/olive-ducks-talk.md
new file mode 100644
index 000000000..e5787dec3
--- /dev/null
+++ b/.changeset/olive-ducks-talk.md
@@ -0,0 +1,5 @@
+---
+'svelte-migrate': patch
+---
+
+Handle Error without message, handle status 200, handle missing body
diff --git a/.changeset/pre.json b/.changeset/pre.json
index e51464608..9f2c94c67 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -332,6 +332,7 @@
     "gentle-dogs-heal",
     "gentle-news-shout",
     "gentle-rules-camp",
+    "gentle-years-leave",
     "giant-ants-hang",
     "giant-ghosts-give",
     "giant-rice-notice",
@@ -424,6 +425,7 @@
     "hot-dogs-fry",
     "hot-keys-walk",
     "hot-kings-confess",
+    "hot-lions-cough",
     "hot-planes-shout",
     "hot-taxis-jam",
     "hungry-coats-sort",
@@ -449,6 +451,7 @@
     "khaki-wolves-shout",
     "kind-ducks-relate",
     "kind-steaks-bake",
+    "kind-tools-shop",
     "kind-wolves-yawn",
     "large-berries-exercise",
     "large-carrots-visit",
@@ -633,6 +636,7 @@
     "ninety-snakes-melt",
     "ninety-suns-relax",
     "ninety-vans-talk",
+    "ninety-walls-heal",
     "odd-bottles-drop",
     "odd-coats-shake",
     "odd-coins-lie",
@@ -652,6 +656,7 @@
     "old-ears-wait",
     "old-files-jump",
     "old-years-march",
+    "olive-ducks-talk",
     "olive-frogs-add",
     "olive-frogs-drive",
     "olive-lies-train",
@@ -776,6 +781,7 @@
     "rich-pumpkins-applaud",
     "rich-seahorses-walk",
     "rich-singers-taste",
+    "rich-walls-doubt",
     "rotten-cats-pump",
     "rotten-gorillas-sort",
     "rotten-rocks-mate",
@@ -1049,6 +1055,7 @@
     "three-windows-push",
     "tidy-boats-listen",
     "tidy-books-reply",
+    "tidy-mice-kick",
     "tidy-pigs-peel",
     "tidy-turkeys-rule",
     "tidy-wasps-shave",
@@ -1080,6 +1087,7 @@
     "tricky-beers-unite",
     "tricky-bees-yell",
     "tricky-buses-punch",
+    "tricky-cheetahs-warn",
     "tricky-maps-know",
     "tricky-moose-sip",
     "tricky-news-smash",
@@ -1138,12 +1146,14 @@
     "warm-jars-move",
     "warm-knives-swim",
     "warm-news-stare",
+    "warm-pots-melt",
     "weak-ladybugs-greet",
     "weak-parents-compare",
     "weak-parents-guess",
     "weak-swans-lie",
     "wet-beds-thank",
     "wet-bees-exist",
+    "wet-crews-smoke",
     "wet-dingos-perform",
     "wet-hairs-wink",
     "wet-lemons-cheat",
diff --git a/.changeset/rich-walls-doubt.md b/.changeset/rich-walls-doubt.md
new file mode 100644
index 000000000..c56fd899f
--- /dev/null
+++ b/.changeset/rich-walls-doubt.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Fix pattern matching for routes starting with an encoded `@` symbol
diff --git a/.changeset/tidy-mice-kick.md b/.changeset/tidy-mice-kick.md
new file mode 100644
index 000000000..bf30dfd9c
--- /dev/null
+++ b/.changeset/tidy-mice-kick.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Fix typos in generating `LayoutServerLoad.{name}` type
diff --git a/.changeset/tricky-cheetahs-warn.md b/.changeset/tricky-cheetahs-warn.md
new file mode 100644
index 000000000..f201e5659
--- /dev/null
+++ b/.changeset/tricky-cheetahs-warn.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Fix sorting of files into +layout, +error, everything else.
diff --git a/.changeset/warm-pots-melt.md b/.changeset/warm-pots-melt.md
new file mode 100644
index 000000000..e38ea295c
--- /dev/null
+++ b/.changeset/warm-pots-melt.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Add test folder to generated tsconfig
diff --git a/.changeset/wet-crews-smoke.md b/.changeset/wet-crews-smoke.md
new file mode 100644
index 000000000..b6d9f4417
--- /dev/null
+++ b/.changeset/wet-crews-smoke.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/adapter-vercel': patch
+---
+
+Use `platform: 'browser'` for esbuild in Vercel Edge Functions.
diff --git a/documentation/docs/15-configuration.md b/documentation/docs/15-configuration.md
index 2f99bd282..e94002412 100644
--- a/documentation/docs/15-configuration.md
+++ b/documentation/docs/15-configuration.md
@@ -120,6 +120,8 @@ const config = {
 
 > The built-in `$lib` alias is controlled by `config.kit.files.lib` as it is used for packaging.
 
+> You will need to run `npm run dev` to have SvelteKit automatically generate the required alias configuration in `jsconfig.json` or `tsconfig.json`.
+
 ### appDir
 
 The directory relative to `paths.assets` where the built JS and CSS (and imported assets) are served from. (The filenames therein contain content-based hashes, meaning they can be cached indefinitely). Must not start or end with `/`.
diff --git a/documentation/faq/50-aliases.md b/documentation/faq/50-aliases.md
deleted file mode 100644
index fccd8d641..000000000
--- a/documentation/faq/50-aliases.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: How do I setup a path alias?
----
-
-Aliases can be set in `svelte.config.js` as described in the [`configuration`](/docs/configuration#alias) docs.
-
-Then run `npm run prepare` or `npm run dev` (both will execute a sync command). SvelteKit will automatically generate the required alias configuration in `jsconfig.json` or `tsconfig.json`.
diff --git a/packages/adapter-auto/CHANGELOG.md b/packages/adapter-auto/CHANGELOG.md
index 565ba704b..7acdcc1ef 100644
--- a/packages/adapter-auto/CHANGELOG.md
+++ b/packages/adapter-auto/CHANGELOG.md
@@ -1,5 +1,13 @@
 # @sveltejs/adapter-auto
 
+## 1.0.0-next.65
+
+### Patch Changes
+
+- Updated dependencies [[`4bd84b32`](https://github.com/sveltejs/kit/commit/4bd84b326889f71c2ebaacfc7f0f1b3a19017a4c)]:
+  - @sveltejs/adapter-vercel@1.0.0-next.67
+  - @sveltejs/adapter-netlify@1.0.0-next.71
+
 ## 1.0.0-next.64
 
 ### Patch Changes
diff --git a/packages/adapter-auto/package.json b/packages/adapter-auto/package.json
index b4df41868..7550d5350 100644
--- a/packages/adapter-auto/package.json
+++ b/packages/adapter-auto/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/adapter-auto",
-	"version": "1.0.0-next.64",
+	"version": "1.0.0-next.65",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/adapter-vercel/CHANGELOG.md b/packages/adapter-vercel/CHANGELOG.md
index d556400fe..e2bafae16 100644
--- a/packages/adapter-vercel/CHANGELOG.md
+++ b/packages/adapter-vercel/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/adapter-vercel
 
+## 1.0.0-next.67
+
+### Patch Changes
+
+- Use `platform: 'browser'` for esbuild in Vercel Edge Functions. ([#6109](https://github.com/sveltejs/kit/pull/6109))
+
 ## 1.0.0-next.66
 
 ### Patch Changes
diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js
index fc55c079f..532d3534e 100644
--- a/packages/adapter-vercel/index.js
+++ b/packages/adapter-vercel/index.js
@@ -186,7 +186,7 @@ export default function ({ external = [], edge, split } = {}) {
 					outfile: `${dirs.functions}/${name}.func/index.js`,
 					target: 'es2020', // TODO verify what the edge runtime supports
 					bundle: true,
-					platform: 'node',
+					platform: 'browser',
 					format: 'esm',
 					external,
 					sourcemap: 'linked'
diff --git a/packages/adapter-vercel/package.json b/packages/adapter-vercel/package.json
index 99649ff2c..4bba54b8e 100644
--- a/packages/adapter-vercel/package.json
+++ b/packages/adapter-vercel/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/adapter-vercel",
-	"version": "1.0.0-next.66",
+	"version": "1.0.0-next.67",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/create-svelte/CHANGELOG.md b/packages/create-svelte/CHANGELOG.md
index 1fb0f81c6..f6f559472 100644
--- a/packages/create-svelte/CHANGELOG.md
+++ b/packages/create-svelte/CHANGELOG.md
@@ -1,5 +1,13 @@
 # create-svelte
 
+## 2.0.0-next.158
+
+### Patch Changes
+
+- Add notes about includes/excludes and path aliases ([#6085](https://github.com/sveltejs/kit/pull/6085))
+
+* setup prettier plugin-search-dirs to enable use with pnpm ([#6101](https://github.com/sveltejs/kit/pull/6101))
+
 ## 2.0.0-next.157
 
 ### Patch Changes
diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json
index 2eaa19005..a3027d35b 100644
--- a/packages/create-svelte/package.json
+++ b/packages/create-svelte/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "create-svelte",
-	"version": "2.0.0-next.157",
+	"version": "2.0.0-next.158",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/create-svelte/shared/+checkjs/jsconfig.json b/packages/create-svelte/shared/+checkjs/jsconfig.json
index 0f47472f7..fe45e13fd 100644
--- a/packages/create-svelte/shared/+checkjs/jsconfig.json
+++ b/packages/create-svelte/shared/+checkjs/jsconfig.json
@@ -10,4 +10,8 @@
 		"sourceMap": true,
 		"strict": true
 	}
+	// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files
+	//
+	// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+	// from the referenced tsconfig.json - TypeScript does not merge them in
 }
diff --git a/packages/create-svelte/shared/+eslint+prettier/package.json b/packages/create-svelte/shared/+eslint+prettier/package.json
index b66bc9c09..a8b937b25 100644
--- a/packages/create-svelte/shared/+eslint+prettier/package.json
+++ b/packages/create-svelte/shared/+eslint+prettier/package.json
@@ -3,7 +3,7 @@
 		"eslint-config-prettier": "^8.3.0"
 	},
 	"scripts": {
-		"lint": "prettier --check --plugin-search-dir=. . && eslint .",
-		"format": "prettier --write --plugin-search-dir=. ."
+		"lint": "prettier --check . && eslint .",
+		"format": "prettier --write ."
 	}
 }
diff --git a/packages/create-svelte/shared/+prettier/.prettierrc b/packages/create-svelte/shared/+prettier/.prettierrc
index ff2677efd..d177cd62d 100644
--- a/packages/create-svelte/shared/+prettier/.prettierrc
+++ b/packages/create-svelte/shared/+prettier/.prettierrc
@@ -2,5 +2,7 @@
 	"useTabs": true,
 	"singleQuote": true,
 	"trailingComma": "none",
-	"printWidth": 100
+	"printWidth": 100,
+	"pluginSearchDirs": ["."],
+	"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
 }
diff --git a/packages/create-svelte/shared/+typescript/tsconfig.json b/packages/create-svelte/shared/+typescript/tsconfig.json
index 0f47472f7..6ae0c8c44 100644
--- a/packages/create-svelte/shared/+typescript/tsconfig.json
+++ b/packages/create-svelte/shared/+typescript/tsconfig.json
@@ -10,4 +10,8 @@
 		"sourceMap": true,
 		"strict": true
 	}
+	// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
+	//
+	// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+	// from the referenced tsconfig.json - TypeScript does not merge them in
 }
diff --git a/packages/create-svelte/shared/-eslint+prettier/package.json b/packages/create-svelte/shared/-eslint+prettier/package.json
index e9103a7e2..bcdff7cf9 100644
--- a/packages/create-svelte/shared/-eslint+prettier/package.json
+++ b/packages/create-svelte/shared/-eslint+prettier/package.json
@@ -1,6 +1,6 @@
 {
 	"scripts": {
-		"lint": "prettier --check --plugin-search-dir=. .",
-		"format": "prettier --write --plugin-search-dir=. ."
+		"lint": "prettier --check .",
+		"format": "prettier --write ."
 	}
 }
diff --git a/packages/create-svelte/templates/skeleton/package.json b/packages/create-svelte/templates/skeleton/package.json
index b5e925884..587569066 100644
--- a/packages/create-svelte/templates/skeleton/package.json
+++ b/packages/create-svelte/templates/skeleton/package.json
@@ -2,7 +2,7 @@
 	"name": "skeleton-template",
 	"version": "0.0.1-next.0",
 	"devDependencies": {
-		"@sveltejs/adapter-auto": "workspace:1.0.0-next.64"
+		"@sveltejs/adapter-auto": "workspace:*"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index fb56b9e8a..168c4cb76 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,21 @@
 # @sveltejs/kit
 
+## 1.0.0-next.428
+
+### Patch Changes
+
+- Allow `$app/stores` to be used from anywhere on the browser ([#6100](https://github.com/sveltejs/kit/pull/6100))
+
+* use `enumerable: false` on "[x] no longer exists" getters so that they are not triggered by spreading ([#6105](https://github.com/sveltejs/kit/pull/6105))
+
+- Fix pattern matching for routes starting with an encoded `@` symbol ([#6110](https://github.com/sveltejs/kit/pull/6110))
+
+* Fix typos in generating `LayoutServerLoad.{name}` type ([#6123](https://github.com/sveltejs/kit/pull/6123))
+
+- Fix sorting of files into +layout, +error, everything else. ([#6108](https://github.com/sveltejs/kit/pull/6108))
+
+* Add test folder to generated tsconfig ([#6085](https://github.com/sveltejs/kit/pull/6085))
+
 ## 1.0.0-next.427
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index dd64163cb..d9e94c817 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.0.0-next.427",
+	"version": "1.0.0-next.428",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/kit/src/core/sync/create_manifest_data/index.js b/packages/kit/src/core/sync/create_manifest_data/index.js
index 32de6c264..ce8944511 100644
--- a/packages/kit/src/core/sync/create_manifest_data/index.js
+++ b/packages/kit/src/core/sync/create_manifest_data/index.js
@@ -478,9 +478,9 @@ function list_files(dir, path = '', files = []) {
 			// sort each directory in (+layout, +error, everything else) order
 			// so that we can trace layouts/errors immediately
 
-			if (a.startsWith('+layout')) {
-				if (!b.startsWith('+layout')) return -1;
-			} else if (b.startsWith('+layout')) {
+			if (a.startsWith('+layout') || a.startsWith('+error')) {
+				if (!b.startsWith('+layout') && !b.startsWith('+error')) return -1;
+			} else if (b.startsWith('+layout') || b.startsWith('+error')) {
 				return 1;
 			} else if (a.startsWith('__')) {
 				if (!b.startsWith('__')) return -1;
diff --git a/packages/kit/src/core/sync/write_root.js b/packages/kit/src/core/sync/write_root.js
index c71e30f5b..0dd8536bd 100644
--- a/packages/kit/src/core/sync/write_root.js
+++ b/packages/kit/src/core/sync/write_root.js
@@ -43,6 +43,7 @@ export function write_root(manifest_data, output) {
 			<!-- This file is generated by @sveltejs/kit — do not edit it! -->
 			<script>
 				import { setContext, afterUpdate, onMount } from 'svelte';
+				import { browser } from '$app/env';
 
 				// stores
 				export let stores;
@@ -52,7 +53,9 @@ export function write_root(manifest_data, output) {
 				${levels.map((l) => `export let data_${l} = null;`).join('\n\t\t\t\t')}
 				export let errors;
 
-				setContext('__svelte__', stores);
+				if (!browser) {
+					setContext('__svelte__', stores);
+				}
 
 				$: stores.page.set(page);
 				afterUpdate(stores.page.notify);
diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js
index 4bee748dd..95d787c34 100644
--- a/packages/kit/src/core/sync/write_tsconfig.js
+++ b/packages/kit/src/core/sync/write_tsconfig.js
@@ -53,6 +53,12 @@ export function write_tsconfig(config, cwd = process.cwd()) {
 		include.push(config_relative(`${relative}/**/*.ts`));
 		include.push(config_relative(`${relative}/**/*.svelte`));
 	}
+	// Test folder is a special case - we advocate putting tests in a top-level test folder
+	// and it's not configurable (should we make it?)
+	const test_folder = project_relative('tests');
+	include.push(config_relative(`${test_folder}/**/*.js`));
+	include.push(config_relative(`${test_folder}/**/*.ts`));
+	include.push(config_relative(`${test_folder}/**/*.svelte`));
 
 	write_if_changed(
 		out,
diff --git a/packages/kit/src/core/sync/write_types.js b/packages/kit/src/core/sync/write_types.js
index 814e732c5..624223027 100644
--- a/packages/kit/src/core/sync/write_types.js
+++ b/packages/kit/src/core/sync/write_types.js
@@ -363,7 +363,7 @@ function write_types_for_dir(config, manifest_data, routes_dir, dir, groups, ts)
 				}
 				if (server_load) {
 					server_load_exports.push(
-						`export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${load};`
+						`export type ${name}<OutputData extends Record<string, any> | void = Record<string, any> | void> = ${server_load};`
 					);
 					server_load_event_exports.push(
 						`export type ${name} = Parameters<LayoutServerLoad.${name}>[0];`
diff --git a/packages/kit/src/runtime/app/stores.js b/packages/kit/src/runtime/app/stores.js
index d98e71715..8f1e21984 100644
--- a/packages/kit/src/runtime/app/stores.js
+++ b/packages/kit/src/runtime/app/stores.js
@@ -1,5 +1,6 @@
 import { getContext } from 'svelte';
 import { browser } from './env.js';
+import { stores as browser_stores } from '../client/singletons.js';
 
 // TODO remove this (for 1.0? after 1.0?)
 let warned = false;
@@ -15,29 +16,39 @@ export function stores() {
  * @type {import('$app/stores').getStores}
  */
 export const getStores = () => {
-	const stores = getContext('__svelte__');
+	const stores = browser ? browser_stores : getContext('__svelte__');
 
-	return {
+	const readonly_stores = {
 		page: {
 			subscribe: stores.page.subscribe
 		},
 		navigating: {
 			subscribe: stores.navigating.subscribe
 		},
-		// TODO remove this (for 1.0? after 1.0?)
-		// @ts-expect-error - deprecated, not part of type definitions, but still callable
-		get preloading() {
-			console.error('stores.preloading is deprecated; use stores.navigating instead');
-			return {
-				subscribe: stores.navigating.subscribe
-			};
-		},
-		get session() {
-			removed_session();
-			return {};
-		},
 		updated: stores.updated
 	};
+
+	// TODO remove this for 1.0
+	Object.defineProperties(readonly_stores, {
+		preloading: {
+			get() {
+				console.error('stores.preloading is deprecated; use stores.navigating instead');
+				return {
+					subscribe: stores.navigating.subscribe
+				};
+			},
+			enumerable: false
+		},
+		session: {
+			get() {
+				removed_session();
+				return {};
+			},
+			enumerable: false
+		}
+	});
+
+	return readonly_stores;
 };
 
 /** @type {typeof import('$app/stores').page} */
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index 806214c2f..214d8843c 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -1,15 +1,7 @@
 import { onMount, tick } from 'svelte';
-import { writable } from 'svelte/store';
 import { normalize_error } from '../../utils/error.js';
 import { LoadURL, decode_params, normalize_path } from '../../utils/url.js';
-import {
-	create_updated_store,
-	find_anchor,
-	get_base_uri,
-	get_href,
-	notifiable_store,
-	scroll_state
-} from './utils.js';
+import { find_anchor, get_base_uri, get_href, scroll_state } from './utils.js';
 import { lock_fetch, unlock_fetch, initial_fetch, native_fetch } from './fetcher.js';
 import { parse } from './parse.js';
 import { error } from '../../index/index.js';
@@ -17,6 +9,7 @@ import { error } from '../../index/index.js';
 import Root from '__GENERATED__/root.svelte';
 import { nodes, dictionary, matchers } from '__GENERATED__/client-manifest.js';
 import { HttpError, Redirect } from '../../index/private.js';
+import { stores } from './singletons.js';
 
 const SCROLL_KEY = 'sveltekit:scroll';
 const INDEX_KEY = 'sveltekit:index';
@@ -59,13 +52,6 @@ export function create_client({ target, base, trailing_slash }) {
 	/** @type {Array<((href: string) => boolean)>} */
 	const invalidated = [];
 
-	const stores = {
-		url: notifiable_store({}),
-		page: notifiable_store({}),
-		navigating: writable(/** @type {import('types').Navigation | null} */ (null)),
-		updated: create_updated_store()
-	};
-
 	/** @type {{id: string | null, promise: Promise<import('./types').NavigationResult | undefined> | null}} */
 	const load_cache = {
 		id: null,
@@ -583,25 +569,36 @@ export function create_client({ target, base, trailing_slash }) {
 					// does await parent() inside an if branch which wasn't executed yet.
 					uses.parent = true;
 					return parent;
+				}
+			};
+
+			// TODO remove this for 1.0
+			Object.defineProperties(load_input, {
+				props: {
+					get() {
+						throw new Error(
+							'@migration task: Replace `props` with `data` stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693'
+						);
+					},
+					enumerable: false
 				},
-				// @ts-expect-error
-				get props() {
-					throw new Error(
-						'@migration task: Replace `props` with `data` stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693'
-					);
-				},
-				get session() {
-					// TODO remove this for 1.0
-					throw new Error(
-						'session is no longer available. See https://github.com/sveltejs/kit/discussions/5883'
-					);
+				session: {
+					get() {
+						throw new Error(
+							'session is no longer available. See https://github.com/sveltejs/kit/discussions/5883'
+						);
+					},
+					enumerable: false
 				},
-				get stuff() {
-					throw new Error(
-						'@migration task: Remove stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693'
-					);
+				stuff: {
+					get() {
+						throw new Error(
+							'@migration task: Remove stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693'
+						);
+					},
+					enumerable: false
 				}
-			};
+			});
 
 			if (import.meta.env.DEV) {
 				try {
diff --git a/packages/kit/src/runtime/client/singletons.js b/packages/kit/src/runtime/client/singletons.js
index 6cf3e8417..f1ab3986c 100644
--- a/packages/kit/src/runtime/client/singletons.js
+++ b/packages/kit/src/runtime/client/singletons.js
@@ -1,3 +1,6 @@
+import { writable } from 'svelte/store';
+import { create_updated_store, notifiable_store } from './utils.js';
+
 /** @type {import('./types').Client} */
 export let client;
 
@@ -9,3 +12,10 @@ export let client;
 export function init(opts) {
 	client = opts.client;
 }
+
+export const stores = {
+	url: notifiable_store({}),
+	page: notifiable_store({}),
+	navigating: writable(/** @type {import('types').Navigation | null} */ (null)),
+	updated: create_updated_store()
+};
diff --git a/packages/kit/src/runtime/server/page/load_data.js b/packages/kit/src/runtime/server/page/load_data.js
index 2562356fd..03422217c 100644
--- a/packages/kit/src/runtime/server/page/load_data.js
+++ b/packages/kit/src/runtime/server/page/load_data.js
@@ -55,23 +55,31 @@ export async function load_data({ event, fetcher, node, parent, server_data_prom
 		return server_data;
 	}
 
-	const data = await node.shared.load.call(null, {
+	const load_input = {
 		url: state.prerendering ? new PrerenderingURL(event.url) : new LoadURL(event.url),
 		params: event.params,
 		data: server_data,
 		routeId: event.routeId,
-		get session() {
-			// TODO remove for 1.0
-			throw new Error(
-				'session is no longer available. See https://github.com/sveltejs/kit/discussions/5883'
-			);
-		},
 		fetch: fetcher,
 		setHeaders: event.setHeaders,
 		depends: () => {},
 		parent
+	};
+
+	// TODO remove this for 1.0
+	Object.defineProperties(load_input, {
+		session: {
+			get() {
+				throw new Error(
+					'session is no longer available. See https://github.com/sveltejs/kit/discussions/5883'
+				);
+			},
+			enumerable: false
+		}
 	});
 
+	const data = await node.shared.load.call(null, load_input);
+
 	return data ? unwrap_promises(data) : null;
 }
 
diff --git a/packages/kit/src/utils/routing.js b/packages/kit/src/utils/routing.js
index fb6d219ad..826c75a4d 100644
--- a/packages/kit/src/utils/routing.js
+++ b/packages/kit/src/utils/routing.js
@@ -16,11 +16,12 @@ export function parse_route_id(id) {
 		id === ''
 			? /^\/$/
 			: new RegExp(
-					`^${decodeURIComponent(id)
+					`^${id
 						.split(/(?:@[a-zA-Z0-9_-]+)?(?:\/|$)/)
 						.map((segment, i, segments) => {
+							const decoded_segment = decodeURIComponent(segment);
 							// special case — /[...rest]/ could contain zero segments
-							const match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment);
+							const match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(decoded_segment);
 							if (match) {
 								names.push(match[1]);
 								types.push(match[2]);
@@ -30,9 +31,9 @@ export function parse_route_id(id) {
 							const is_last = i === segments.length - 1;
 
 							return (
-								segment &&
+								decoded_segment &&
 								'/' +
-									segment
+									decoded_segment
 										.split(/\[(.+?)\]/)
 										.map((content, i) => {
 											if (i % 2) {
diff --git a/packages/kit/src/utils/routing.spec.js b/packages/kit/src/utils/routing.spec.js
index dd14241c0..3c14ce927 100644
--- a/packages/kit/src/utils/routing.spec.js
+++ b/packages/kit/src/utils/routing.spec.js
@@ -42,6 +42,16 @@ const tests = {
 		pattern: /^\/matched\/([^/]+?)\/?$/,
 		names: ['id'],
 		types: ['uuid']
+	},
+	'%23hash-encoded': {
+		pattern: /^\/%23hash-encoded\/?$/,
+		names: [],
+		types: []
+	},
+	'%40at-encoded/[id]': {
+		pattern: /^\/@at-encoded\/([^/]+?)\/?$/,
+		names: ['id'],
+		types: [undefined]
 	}
 };
 
diff --git a/packages/kit/types/ambient.d.ts b/packages/kit/types/ambient.d.ts
index 25981f86b..678de3ebe 100644
--- a/packages/kit/types/ambient.d.ts
+++ b/packages/kit/types/ambient.d.ts
@@ -216,24 +216,16 @@ declare module '$app/paths' {
  * import { getStores, navigating, page, updated } from '$app/stores';
  * ```
  *
- * Stores are _contextual_ — they are added to the [context](https://svelte.dev/tutorial/context-api) of your root component. This means that `page` is unique to each request on the server, rather than shared between multiple requests handled by the same server simultaneously.
+ * Stores on the server are _contextual_ — they are added to the [context](https://svelte.dev/tutorial/context-api) of your root component. This means that `page` is unique to each request, rather than shared between multiple requests handled by the same server simultaneously.
  *
  * Because of that, you must subscribe to the stores during component initialization (which happens automatically if you reference the store value, e.g. as `$page`, in a component) before you can use them.
+ *
+ * In the browser, we don't need to worry about this, and stores can be accessed from anywhere. Code that will only ever run on the browser can refer to (or subscribe to) any of these stores at any time.
  */
 declare module '$app/stores' {
 	import { Readable } from 'svelte/store';
 	import { Navigation, Page } from '@sveltejs/kit';
 
-	/**
-	 * A convenience function around `getContext`. Must be called during component initialization.
-	 * Only use this if you need to defer store subscription until after the component has mounted, for some reason.
-	 */
-	export function getStores(): {
-		navigating: typeof navigating;
-		page: typeof page;
-		updated: typeof updated;
-	};
-
 	/**
 	 * A readable store whose value contains page data.
 	 */
@@ -248,6 +240,16 @@ declare module '$app/stores' {
 	 *  A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
 	 */
 	export const updated: Readable<boolean> & { check: () => boolean };
+
+	/**
+	 * A function that returns all of the contextual stores. On the server, this must be called during component initialization.
+	 * Only use this if you need to defer store subscription until after the component has mounted, for some reason.
+	 */
+	export function getStores(): {
+		navigating: typeof navigating;
+		page: typeof page;
+		updated: typeof updated;
+	};
 }
 
 /**
diff --git a/packages/migrate/CHANGELOG.md b/packages/migrate/CHANGELOG.md
index d19ade957..73e0d88e5 100644
--- a/packages/migrate/CHANGELOG.md
+++ b/packages/migrate/CHANGELOG.md
@@ -1,5 +1,11 @@
 # svelte-migrate
 
+## 1.0.0-next.9
+
+### Patch Changes
+
+- Handle Error without message, handle status 200, handle missing body ([#6096](https://github.com/sveltejs/kit/pull/6096))
+
 ## 1.0.0-next.8
 
 ### Patch Changes
diff --git a/packages/migrate/migrations/routes/index.js b/packages/migrate/migrations/routes/index.js
index 0597f00c3..14b55a393 100644
--- a/packages/migrate/migrations/routes/index.js
+++ b/packages/migrate/migrations/routes/index.js
@@ -148,12 +148,7 @@ export async function migrate() {
 
 			renamed += svelte_ext;
 
-			const { module, main, ext } = migrate_scripts(
-				content,
-				bare,
-				is_error_page,
-				move_to_directory
-			);
+			const { module, main, ext } = migrate_scripts(content, is_error_page, move_to_directory);
 
 			if (move_to_directory) {
 				const dir = path.dirname(renamed);
diff --git a/packages/migrate/migrations/routes/migrate_page_js/index.js b/packages/migrate/migrations/routes/migrate_page_js/index.js
index 308a9b9d0..a4947f475 100644
--- a/packages/migrate/migrations/routes/migrate_page_js/index.js
+++ b/packages/migrate/migrations/routes/migrate_page_js/index.js
@@ -61,8 +61,12 @@ export function migrate_page(content, filename) {
 						return; // nothing to do
 					}
 
-					if (keys === 'props') {
-						automigration(value, file.code, dedent(nodes.props.getText()));
+					if (
+						keys === 'props' ||
+						((keys === 'status' || keys === 'props status') &&
+							Number(nodes.status.getText()) === 200)
+					) {
+						automigration(value, file.code, dedent(nodes.props?.getText() || ''));
 						return;
 					}
 
@@ -85,10 +89,16 @@ export function migrate_page(content, filename) {
 						if (nodes.error) {
 							const message = is_string_like(nodes.error)
 								? nodes.error.getText()
-								: is_new(nodes.error, 'Error') && nodes.error.arguments[0].getText();
-
-							if (message) {
-								automigration(node, file.code, `throw error(${status || 500}, ${message});`);
+								: is_new(nodes.error, 'Error')
+								? /** @type {string | undefined} */ (nodes.error.arguments[0]?.getText())
+								: false;
+
+							if (message !== false) {
+								automigration(
+									node,
+									file.code,
+									`throw error(${status || 500}${message ? `, ${message}` : ''});`
+								);
 								imports.add('error');
 								return;
 							}
diff --git a/packages/migrate/migrations/routes/migrate_page_js/samples.md b/packages/migrate/migrations/routes/migrate_page_js/samples.md
index 3f72c848a..c38874cb2 100644
--- a/packages/migrate/migrations/routes/migrate_page_js/samples.md
+++ b/packages/migrate/migrations/routes/migrate_page_js/samples.md
@@ -157,6 +157,29 @@ export function load({ session }) {
 }
 ```
 
+## Error constructor with no arguments
+
+```js before
+export function load({ session }) {
+	if (!session.user?.admin) {
+		return {
+			status: 403,
+			error: new Error()
+		};
+	}
+}
+```
+
+```js after
+import { error } from '@sveltejs/kit';
+
+export function load({ session }) {
+	if (!session.user?.admin) {
+		throw error(403);
+	}
+}
+```
+
 ## Error status with no error
 
 ```js before
@@ -322,3 +345,36 @@ export function load() {
 	return;
 }
 ```
+
+## A load function that returns props and status 200
+
+```js before
+export function load() {
+	return {
+		status: 200,
+		props: {}
+	};
+}
+```
+
+```js after
+export function load() {
+	return {};
+}
+```
+
+## A load function that returns status 200
+
+```js before
+export function load() {
+	return {
+		status: 200 
+	};
+}
+```
+
+```js after
+export function load() {
+	return ;
+}
+```
diff --git a/packages/migrate/migrations/routes/migrate_page_server/index.js b/packages/migrate/migrations/routes/migrate_page_server/index.js
index 15f550728..f33c40002 100644
--- a/packages/migrate/migrations/routes/migrate_page_server/index.js
+++ b/packages/migrate/migrations/routes/migrate_page_server/index.js
@@ -58,7 +58,7 @@ export function migrate_page_server(content, filename) {
 							return;
 						}
 
-						automigration(value, file.code, dedent(nodes.body.getText()));
+						automigration(value, file.code, dedent(nodes.body?.getText() || ''));
 					});
 				}
 
diff --git a/packages/migrate/migrations/routes/migrate_page_server/samples.md b/packages/migrate/migrations/routes/migrate_page_server/samples.md
index 3d717164d..4d61b46d9 100644
--- a/packages/migrate/migrations/routes/migrate_page_server/samples.md
+++ b/packages/migrate/migrations/routes/migrate_page_server/samples.md
@@ -137,3 +137,19 @@ export function load() {
 	return;
 }
 ```
+
+## A function that wrongfully has no body
+
+```js before
+export function GET() {
+	return {
+		status: 200
+	};
+}
+```
+
+```js after
+export function load() {
+	return ;
+}
+```
diff --git a/packages/migrate/migrations/routes/migrate_scripts/index.js b/packages/migrate/migrations/routes/migrate_scripts/index.js
index 043257c56..3b1ac905c 100644
--- a/packages/migrate/migrations/routes/migrate_scripts/index.js
+++ b/packages/migrate/migrations/routes/migrate_scripts/index.js
@@ -9,21 +9,16 @@ import {
 	except_str
 } from '../utils.js';
 import * as TASKS from '../tasks.js';
-import MagicString from 'magic-string';
 
 /**
  * @param {string} content
- * @param {string} filename
  * @param {boolean} is_error
  * @param {boolean} moved
  */
-export function migrate_scripts(content, filename, is_error, moved) {
+export function migrate_scripts(content, is_error, moved) {
 	/** @type {string | null} */
 	let module = null;
 
-	const match = /__layout(?:-([^.@]+))?/.exec(filename);
-	const data_name = match?.[1] ? `LayoutData.${match[1]}` : match ? `LayoutData` : 'PageData';
-
 	let ext = '.js';
 
 	// instance script
@@ -36,10 +31,6 @@ export function migrate_scripts(content, filename, is_error, moved) {
 				contents = adjust_imports(contents);
 			}
 
-			if (/lang(?:uage)?=(['"])(ts|typescript)\1/.test(attrs)) {
-				ext = '.ts';
-			}
-
 			if (/context=(['"])module\1/.test(attrs)) {
 				// special case — load is no longer supported in error
 				if (is_error) {
@@ -51,6 +42,10 @@ export function migrate_scripts(content, filename, is_error, moved) {
 					return `<script${attrs}>${body}</script>${whitespace}`;
 				}
 
+				if (/lang(?:uage)?=(['"])(ts|typescript)\1/.test(attrs)) {
+					ext = '.ts';
+				}
+
 				module = dedent(contents.replace(/^\n/, ''));
 
 				const declared = find_declarations(contents);
@@ -93,22 +88,8 @@ export function migrate_scripts(content, filename, is_error, moved) {
 			}
 
 			if (!is_error && /export/.test(contents)) {
-				let prefix = `\n${indent}${error('Add data prop', TASKS.PAGE_DATA_PROP)}`;
-				const props = get_props(contents);
-				if (props) {
-					prefix += `\n${comment(
-						`${indent}Suggestion (check code before using, and possibly convert to data.X access later):\n` +
-							`${indent}${
-								ext === '.ts'
-									? `import type { ${data_name} } from './$types';`
-									: `/** @type {import('./$types').${data_name}} */`
-							}\n` +
-							`${indent}export let data${ext === '.ts' ? `: ${data_name}` : ''};\n` +
-							`${indent}$: ({ ${props.join(', ')} } = data);`,
-						indent
-					)}`;
-				}
-				contents = `${prefix}\n${contents}`;
+				contents = `\n${indent}${error('Add data prop', TASKS.PAGE_DATA_PROP)}\n${contents}`;
+				// Possible TODO: migrate props to data.prop, or suggest $: ({propX, propY, ...} = data);
 			}
 
 			return `<script${attrs}>${contents}</script>${whitespace}`;
@@ -174,74 +155,3 @@ function find_declarations(content) {
 
 	return declared;
 }
-
-/**
- * @param {string} content
- */
-function get_props(content) {
-	try {
-		const ast = ts.createSourceFile(
-			'filename.ts',
-			content,
-			ts.ScriptTarget.Latest,
-			true,
-			ts.ScriptKind.TS
-		);
-
-		const code = new MagicString(content);
-		let give_up = false;
-		/** @type {string[] } */
-		let exports = [];
-
-		/** @param {ts.Node} node */
-		function walk(node) {
-			if (
-				ts.isExportDeclaration(node) ||
-				((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) && hasExportKeyword(node))
-			) {
-				give_up = true;
-				return;
-			}
-
-			if (ts.isVariableStatement(node)) {
-				if (hasExportKeyword(node)) {
-					const isLet = node.declarationList.flags === ts.NodeFlags.Let;
-					if (isLet) {
-						ts.forEachChild(node.declarationList, (node) => {
-							if (ts.isVariableDeclaration(node)) {
-								if (ts.isIdentifier(node.name)) {
-									const name = node.name.getText();
-									if (name === 'data') {
-										give_up = true;
-										return;
-									} else {
-										exports.push(name);
-									}
-								} else {
-									give_up = true;
-									return;
-								}
-							}
-						});
-					} else {
-						give_up = true;
-						return;
-					}
-				}
-			}
-		}
-
-		ts.forEachChild(ast, walk);
-		if (give_up) return;
-		return exports;
-	} catch (e) {
-		return;
-	}
-}
-
-/**
- * @param {ts.Node} node
- */
-export function hasExportKeyword(node) {
-	return node.modifiers?.find((x) => x.kind == ts.SyntaxKind.ExportKeyword);
-}
diff --git a/packages/migrate/migrations/routes/migrate_scripts/index.spec.js b/packages/migrate/migrations/routes/migrate_scripts/index.spec.js
index 5c51d1ec8..f26c1f1cd 100644
--- a/packages/migrate/migrations/routes/migrate_scripts/index.spec.js
+++ b/packages/migrate/migrations/routes/migrate_scripts/index.spec.js
@@ -7,7 +7,6 @@ for (const sample of read_samples(import.meta.url)) {
 	test(sample.description, () => {
 		const actual = migrate_scripts(
 			sample.before,
-			sample.filename ?? 'some-page.svelte',
 			sample.description.includes('error'),
 			sample.description.includes('moved')
 		);
diff --git a/packages/migrate/migrations/routes/migrate_scripts/samples.md b/packages/migrate/migrations/routes/migrate_scripts/samples.md
index 986c44326..6f57fb1f4 100644
--- a/packages/migrate/migrations/routes/migrate_scripts/samples.md
+++ b/packages/migrate/migrations/routes/migrate_scripts/samples.md
@@ -77,10 +77,6 @@
 ```svelte after
 <script>
 	throw new Error("@migration task: Add data prop (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292707)");
-	// Suggestion (check code before using, and possibly convert to data.X access later):
-	// /** @type {import('./$types').PageData} */
-	// export let data;
-	// $: ({ a } = data);
 
 	export let a;
 </script>
@@ -88,8 +84,6 @@
 
 ## Module context with moved imports
 
-> file: __layout.svelte
-
 ```svelte before
 <script context="module">
 	import Foo from './Foo.svelte';
@@ -102,7 +96,7 @@
 	}
 </script>
 
-<script lang="ts">
+<script>
 	export let sry;
 </script>
 
@@ -123,12 +117,8 @@
 	// }
 </script>
 
-<script lang="ts">
+<script>
 	throw new Error("@migration task: Add data prop (https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292707)");
-	// Suggestion (check code before using, and possibly convert to data.X access later):
-	// import type { LayoutData } from './$types';
-	// export let data: LayoutData;
-	// $: ({ sry } = data);
 
 	export let sry;
 </script>
diff --git a/packages/migrate/package.json b/packages/migrate/package.json
index 3b03821ab..c5ac8be47 100644
--- a/packages/migrate/package.json
+++ b/packages/migrate/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "svelte-migrate",
-	"version": "1.0.0-next.8",
+	"version": "1.0.0-next.9",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 141b10e1d..0670c9c92 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -262,7 +262,7 @@ importers:
 
   packages/create-svelte/templates/skeleton:
     specifiers:
-      '@sveltejs/adapter-auto': workspace:1.0.0-next.64
+      '@sveltejs/adapter-auto': workspace:*
     devDependencies:
       '@sveltejs/adapter-auto': link:../../../adapter-auto
 


Test patch:
diff --git a/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte
new file mode 100644
index 000000000..d6fb29263
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte
@@ -0,0 +1,13 @@
+<script>
+	import { getStores } from '$app/stores';
+
+	let pathname;
+</script>
+
+<h1>{pathname}</h1>
+
+<button
+	on:click={() => {
+		getStores().page.subscribe(($page) => pathname = $page.url.pathname)();
+	}}>click</button
+>
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index 05be5cf42..f95a9568d 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -585,3 +585,10 @@ test('Can use browser-only global on client-only page', async ({ page, read_erro
 	await expect(page.locator('p')).toHaveText('Works');
 	expect(read_errors('/no-ssr/browser-only-global')).toBe(undefined);
 });
+
+test('can use $app/stores from anywhere on client', async ({ page }) => {
+	await page.goto('/store/client-access');
+	await expect(page.locator('h1')).toHaveText('undefined');
+	await page.click('button');
+	await expect(page.locator('h1')).toHaveText('/store/client-access');
+});