Repository: sveltejs/kit (js)

Issue:
Typescript warns that a .svelte file import into a test file doesn't exist.
### Describe the bug

I'm getting typescript warnings that a `.svelte` file that I'm importing in a test file doesn't exist. But `vitest` runs fine. It seems to work if I add an includes in the project `tsconfig.json` to 

```
"include": [
    "./.svelte-kit/ambient.d.ts",
    "src/**/*.js",
    "src/**/*.ts",
    "src/**/*.svelte",
    "src/**/*.js",
    "src/**/*.ts",
    "src/**/*.svelte",
    "test/**/*.ts",
    "test/**/*.js",
    "test/**/*.svelte"
  ],
```

and relaunch VS Code. But I'm wondering why test directory wasn't included in .`svelte-kit/tsconfig.json` in the first place.

![Screenshot 2022-08-05 at 14 59 39](https://user-images.githubusercontent.com/1709986/183082642-33821a9d-f135-443b-b6e3-86e0cf8daa12.png)


### Reproduction

https://github.com/manuganji/sjsf/tree/17b0742b3d25347a6c4be2186a7bd8f568ea32ae

### Logs

_No response_

### System Info

```shell
System:
    OS: macOS 12.1
    CPU: (8) x64 Apple M1
    Memory: 30.89 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 1.22.17 - /opt/homebrew/bin/yarn
    npm: 8.10.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
  Browsers:
    Chrome: 104.0.5112.79
    Firefox: 100.0.2
    Safari: 15.2
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.63 
    @sveltejs/kit: next => 1.0.0-next.403 
    svelte: ^3.44.0 => 3.49.0 
    vite: ^3.0.0 => 3.0.3
```


### Severity

annoyance

### Additional Information

_No response_

Pull request description:
[fix] add test folder to includes
Also add some notes to tsconfig/jsonfig
Fixes #5833

I briefly thought about making this configurable through `kit.files`, but didn't do so because only the tsconfig includes generation would benefit from it - you'd still need to update the package.json scripts yourself.

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
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 ac7739a12..e51464608 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -1010,6 +1010,7 @@
     "tasty-zebras-guess",
     "ten-apricots-admire",
     "ten-berries-develop",
+    "ten-gorillas-itch",
     "ten-hairs-perform",
     "ten-mice-kneel",
     "ten-plants-sleep",
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/ten-gorillas-itch.md b/.changeset/ten-gorillas-itch.md
new file mode 100644
index 000000000..15790d6cb
--- /dev/null
+++ b/.changeset/ten-gorillas-itch.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Throw error if browser.hydrate is false and browser.router is true
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-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/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 379188f4a..fb56b9e8a 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/kit
 
+## 1.0.0-next.427
+
+### Patch Changes
+
+- Throw error if browser.hydrate is false and browser.router is true ([#6086](https://github.com/sveltejs/kit/pull/6086))
+
 ## 1.0.0-next.426
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index b8fb164a6..dd64163cb 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.0.0-next.426",
+	"version": "1.0.0-next.427",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js
index 3cd626d49..e9d6e0e66 100644
--- a/packages/kit/src/core/config/index.spec.js
+++ b/packages/kit/src/core/config/index.spec.js
@@ -246,6 +246,19 @@ test('fails if kit.appDir ends with slash', () => {
 	}, /^config\.kit\.appDir cannot start or end with '\/'. See https:\/\/kit\.svelte\.dev\/docs\/configuration$/);
 });
 
+test('fails if browser.hydrate is false and browser.router is true', () => {
+	assert.throws(() => {
+		validate_config({
+			kit: {
+				browser: {
+					hydrate: false,
+					router: true
+				}
+			}
+		});
+	}, /^config\.kit\.browser\.router cannot be true if config\.kit\.browser\.hydrate is false$/);
+});
+
 test('fails if paths.base is not root-relative', () => {
 	assert.throws(() => {
 		validate_config({
diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js
index 9d89fd4ee..c82f008d8 100644
--- a/packages/kit/src/core/config/options.js
+++ b/packages/kit/src/core/config/options.js
@@ -107,9 +107,14 @@ const options = object(
 				return input;
 			}),
 
-			browser: object({
-				hydrate: boolean(true),
-				router: boolean(true)
+			browser: validate({ hydrate: true, router: true }, (input, keypath) => {
+				const value = object({ hydrate: boolean(true), router: boolean(true) })(input, keypath);
+				if (!value.hydrate && value.router) {
+					throw new Error(
+						'config.kit.browser.router cannot be true if config.kit.browser.hydrate is false'
+					);
+				}
+				return value;
 			}),
 
 			csp: object({
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/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/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/create-svelte/test/check.js b/packages/create-svelte/test/check.js
index 2fa477952..5e74a81da 100644
--- a/packages/create-svelte/test/check.js
+++ b/packages/create-svelte/test/check.js
@@ -2,6 +2,7 @@ import fs from 'fs';
 import { execSync } from 'child_process';
 import path from 'path';
 import { test } from 'uvu';
+import { Writable } from 'stream';
 import * as assert from 'uvu/assert';
 import { create } from '../index.js';
 import { fileURLToPath } from 'url';
@@ -43,7 +44,8 @@ test.before(() => {
 		fs.writeFileSync(path.join(test_workspace_dir, 'pnpm-workspace.yaml'), 'packages:\n  - ./*\n');
 
 		// force creation of pnpm-lock.yaml in test workspace
-		execSync('pnpm install --no-frozen-lockfile', { dir: test_workspace_dir, stdio: 'inherit' });
+		console.log(`running pnpm install in .test-tmp/create-svelte`);
+		execSync('pnpm install --no-frozen-lockfile', { dir: test_workspace_dir, stdio: 'ignore' });
 	} catch (e) {
 		console.error('failed to setup create-svelte test workspace', e);
 		throw e;
@@ -84,7 +86,8 @@ for (const template of fs.readdirSync('templates')) {
 			fs.writeFileSync(path.join(cwd, 'package.json'), JSON.stringify(pkg, null, '\t') + '\n');
 
 			// this pnpm install works in the test workspace, which redirects to our local packages again
-			execSync('pnpm install --no-frozen-lockfile', { cwd, stdio: 'inherit' });
+			console.log(`running pnpm install in ${cwd}`);
+			execSync('pnpm install --no-frozen-lockfile', { cwd, stdio: 'ignore' });
 
 			// run provided scripts that are non-blocking. All of them should exit with 0
 			const scripts_to_test = ['prepare', 'check', 'lint', 'build', 'sync'];
@@ -95,17 +98,20 @@ for (const template of fs.readdirSync('templates')) {
 			}
 
 			// not all templates have all scripts
+			console.group(`${template}-${types}`);
 			for (const script of Object.keys(pkg.scripts).filter((s) => scripts_to_test.includes(s))) {
-				const command = `pnpm run ${script}`;
 				try {
-					console.log(`executing ${command} in ${cwd}`);
-					execSync(command, { cwd, stdio: 'inherit' });
+					execSync(`pnpm run ${script}`, { cwd, stdio: 'pipe' });
+					console.log(`✅ ${script}`);
 				} catch (e) {
-					const msg = `${command} failed in ${cwd}`;
-					console.error(msg, e);
-					assert.unreachable(msg);
+					console.error(`❌ ${script}`);
+					console.error(`---\nstdout:\n${e.stdout}`);
+					console.error(`---\nstderr:\n${e.stderr}`);
+					console.groupEnd();
+					assert.unreachable(e.message);
 				}
 			}
+			console.groupEnd();
 		});
 	}
 }
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');
+});