From 3720bdf5c1c88ee54f04ab118687dac3c822cb86 Mon Sep 17 00:00:00 2001 From: Manuel Serret Date: Sat, 8 Aug 2026 11:13:17 +0200 Subject: [PATCH 1/3] feat(migrate): `prepare-ai-migration` for `sk3` --- .../migrate/migrations/sveltekit-3/index.ts | 2 + .../sveltekit-3/tasks/package-json.ts | 10 +- .../sveltekit-3/tasks/prepare-ai-migration.ts | 169 ++++++++++++++++++ .../MIGRATION_TASKS.snapshot.md | 67 +++++++ .../nested/svelte.config.ts | 4 + .../src/routes/+page.svelte | 5 + .../prepare-ai-migration/svelte.config.js | 11 ++ .../tests/prepare-ai-migration/vite.config.ts | 6 + 8 files changed, 269 insertions(+), 5 deletions(-) create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/index.ts b/packages/sv/src/migrate/migrations/sveltekit-3/index.ts index 47fde3c8b..322a6dffd 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/index.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/index.ts @@ -6,6 +6,7 @@ import externalRedirects from './tasks/external-redirects.ts'; import packageJson from './tasks/package-json.ts'; import params from './tasks/params.ts'; import paths from './tasks/paths.ts'; +import prepareAiMigration from './tasks/prepare-ai-migration.ts'; import shallowRouting from './tasks/shallow-routing.ts'; import svelteConfig from './tasks/svelte-config.ts'; import tsconfig from './tasks/tsconfig.ts'; @@ -38,5 +39,6 @@ export default defineMigration({ tasks.add(params, { prerequisite: false }); tasks.add(tsconfig, { prerequisite: true }); tasks.add(appState, { prerequisite: false }); + tasks.add(prepareAiMigration, { prerequisite: false }); } }); diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts index a5cfbb827..13e1c69e4 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts @@ -7,10 +7,10 @@ export default defineMigrationTask({ run: (args) => { // instead of duplicating the logic of the experimental addon, lets just call it. // migrates kit to it's 'next' version. - experimentalAddon.run({ - ...args, - options: { versions: ['kit-3'], features: [] }, - cancel: () => {} - }); + // experimentalAddon.run({ + // ...args, + // options: { versions: ['kit-3'], features: [] }, + // cancel: () => {} + // }); } }); diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts new file mode 100644 index 000000000..509036b93 --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts @@ -0,0 +1,169 @@ +import { defineMigrationTask } from '../../../index.ts'; + +const REPORT_PATH = 'MIGRATION_TASKS.md'; +export const GENERATED_MARKER = ''; + +type MigrationTask = { + title: string; + checks: Array<{ + include: string | string[]; + patterns: Array; + }>; + summary: string; + instructions: string; + links: Array<{ label: string; url: string }>; +}; + +const migrationTasks: MigrationTask[] = [ + { + title: 'Remove `experimental.handleRenderingErrors`', + checks: [ + { + include: '**/{svelte,vite}.config.{js,ts,mjs,mts,cjs,cts}', + patterns: ['handleRenderingErrors'] + } + ], + summary: + 'SvelteKit 3 removes the `experimental.handleRenderingErrors` feature flag because rendering errors are now handled this way by default.', + instructions: + 'Remove the `handleRenderingErrors` property from the SvelteKit configuration. If that leaves an empty `experimental` object, remove that object as well. No replacement option is needed — SvelteKit 3 always wraps route components in error boundaries so rendering errors reach the nearest `+error.svelte` page.', + links: [ + { + label: 'SvelteKit PR #16265', + url: 'https://github.com/sveltejs/kit/pull/16265' + } + ] + }, + { + // Temporary: this is already handled by the automatic Kit 3 migration. It exercises a + // migration task with multiple detection rules and can be removed after this task is proven. + title: 'Replace the `$lib` alias with `#lib` and remove `files.lib`', + checks: [ + { + include: '**/*.{js,ts,svelte,mjs,mts,cjs,cts}', + patterns: ['$lib'] + }, + { + include: '**/{svelte,vite}.config.{js,ts,mjs,mts,cjs,cts}', + patterns: [/\bfiles\s*:\s*\{[\s\S]*?\blib\s*:/] + } + ], + summary: + 'SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field.', + instructions: + 'Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports.', + links: [ + { + label: 'SvelteKit PR #16360', + url: 'https://github.com/sveltejs/kit/pull/16360' + }, + { + label: 'Node.js package imports', + url: 'https://nodejs.org/api/packages.html#subpath-imports' + } + ] + } +]; + +type Finding = { task: MigrationTask; files: string[] }; + +export default defineMigrationTask({ + id: 'prepare-ai-migration', + description: 'Prepare instructions for AI-assisted migration tasks', + run: ({ sv }) => { + const findings: Finding[] = []; + + for (const task of migrationTasks) { + const files = new Set(); + for (const check of task.checks) { + sv.files( + { + include: check.include, + exclude: [REPORT_PATH], + where: (content) => check.patterns.some((pattern) => matches(content, pattern)) + }, + (_content, file) => { + files.add(file); + return false; + } + ); + } + + if (files.size > 0) findings.push({ task, files: [...files].sort() }); + } + + if (findings.length === 0) return; + + sv.file(REPORT_PATH, (content) => { + if (content && !content.includes(GENERATED_MARKER)) { + throw new Error( + `'${REPORT_PATH}' already exists and was not generated by this migration. Move or rename it before rerunning the task.` + ); + } + + return renderReport(findings); + }); + } +}); + +function matches(content: string, pattern: string | RegExp): boolean { + return typeof pattern === 'string' ? content.includes(pattern) : pattern.test(content); +} + +export function renderReport(findings: Finding[]): string { + const sections = findings.map(({ task, files }) => { + const links = task.links.map(({ label, url }) => `- [${label}](${url})`).join('\n'); + const locations = files.map((file) => `- [ ] \`${file}\``).join('\n'); + + return `### ${task.title} + +${task.summary} + +#### What to do + +${task.instructions} + +#### References + +${links} + +#### Files to review + +${locations}`; + }); + + return `${GENERATED_MARKER} +# SvelteKit 3 migration tasks + +## For humans + +Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. Modern AI assistants can handle many of these cases effectively when they are given focused context. This file uses that current technology to bridge the gap while keeping the automatic migrations reliable and maintainable. + +The findings are intentionally broad and may include files that do not require changes. Review the AI's work before accepting it. + +## For AI assistants + +Work through the migration tasks below one at a time: + +1. Read the linked documentation or pull request before changing code. +2. Inspect every listed file and its surrounding context. +3. Ignore a finding when the file is not actually affected. +4. Make the smallest necessary change. Do not perform unrelated refactors or introduce unnecessary abstractions. +5. Ask the user when application intent cannot be inferred. +6. Run the project's appropriate checks after editing. + +Also search the project for \`@migration-task\` comments. They may describe additional manual migration work that must be resolved. + +## Migration tasks + +${sections.join('\n\n')} + +## Final verification + +- [ ] Review every migration task and ignore any irrelevant findings. +- [ ] Resolve remaining \`@migration-task\` comments. +- [ ] Run the project's type checker and tests. +- [ ] Build the project successfully. +- [ ] Delete this file when all migration work is complete. +`; +} diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md new file mode 100644 index 000000000..fb78556a2 --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md @@ -0,0 +1,67 @@ + +# SvelteKit 3 migration tasks + +## For humans + +Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. Modern AI assistants can handle many of these cases effectively when they are given focused context. This file uses that current technology to bridge the gap while keeping the automatic migrations reliable and maintainable. + +The findings are intentionally broad and may include files that do not require changes. Review the AI's work before accepting it. + +## For AI assistants + +Work through the migration tasks below one at a time: + +1. Read the linked documentation or pull request before changing code. +2. Inspect every listed file and its surrounding context. +3. Ignore a finding when the file is not actually affected. +4. Make the smallest necessary change. Do not perform unrelated refactors or introduce unnecessary abstractions. +5. Ask the user when application intent cannot be inferred. +6. Run the project's appropriate checks after editing. + +Also search the project for `@migration-task` comments. They may describe additional manual migration work that must be resolved. + +## Migration tasks + +### Remove `experimental.handleRenderingErrors` + +SvelteKit 3 removes the `experimental.handleRenderingErrors` feature flag because rendering errors are now handled this way by default. + +#### What to do + +Remove the `handleRenderingErrors` property from the SvelteKit configuration. If that leaves an empty `experimental` object, remove that object as well. No replacement option is needed — SvelteKit 3 always wraps route components in error boundaries so rendering errors reach the nearest `+error.svelte` page. + +#### References + +- [SvelteKit PR #16265](https://github.com/sveltejs/kit/pull/16265) + +#### Files to review + +- [ ] `nested/svelte.config.ts` +- [ ] `svelte.config.js` +- [ ] `vite.config.ts` + +### Replace the `$lib` alias with `#lib` and remove `files.lib` + +SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field. + +#### What to do + +Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports. + +#### References + +- [SvelteKit PR #16360](https://github.com/sveltejs/kit/pull/16360) +- [Node.js package imports](https://nodejs.org/api/packages.html#subpath-imports) + +#### Files to review + +- [ ] `src/routes/+page.svelte` +- [ ] `svelte.config.js` + +## Final verification + +- [ ] Review every migration task and ignore any irrelevant findings. +- [ ] Resolve remaining `@migration-task` comments. +- [ ] Run the project's type checker and tests. +- [ ] Build the project successfully. +- [ ] Delete this file when all migration work is complete. diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts new file mode 100644 index 000000000..3a509c3ad --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts @@ -0,0 +1,4 @@ +// This intentionally broad textual match may be irrelevant and should still be reported. +const removedOption = 'handleRenderingErrors'; + +export default { removedOption }; diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte new file mode 100644 index 000000000..490d4276a --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js new file mode 100644 index 000000000..1fdb05057 --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js @@ -0,0 +1,11 @@ +export default { + kit: { + // This directory was previously available through $lib. + files: { + lib: 'src/shared' + }, + experimental: { + handleRenderingErrors: true + } + } +}; diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts new file mode 100644 index 000000000..aaefc96f0 --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts @@ -0,0 +1,6 @@ +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [sveltekit({ experimental: { handleRenderingErrors: true } })] +}); From a39ac5deb4861755b13f6f212af0f32a6bcb38e6 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 10 Aug 2026 14:34:33 +0200 Subject: [PATCH 2/3] more --- .../sveltekit-3/tasks/package-json.ts | 2 +- .../sveltekit-3/tasks/prepare-ai-migration.ts | 359 +++++++++++++++++- .../tests/package-json/package.snapshot.json | 4 +- .../MIGRATION_TASKS.snapshot.md | 22 +- .../src/routes/+page.svelte | 3 + 5 files changed, 356 insertions(+), 34 deletions(-) diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts index 5c873653d..7801d36f1 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/package-json.ts @@ -4,7 +4,7 @@ import { defineMigrationTask } from '../../../index.ts'; const KIT3_PEERS = { vite: '^8.0.12', '@sveltejs/vite-plugin-svelte': '^7.0.0', - svelte: '^5.48.0', + svelte: '^5.56.4', typescript: '^6.0.0' }; diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts index 509036b93..c6df37d88 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts @@ -1,6 +1,9 @@ import { defineMigrationTask } from '../../../index.ts'; const REPORT_PATH = 'MIGRATION_TASKS.md'; +const GUIDE_URL = + 'https://github.com/sveltejs/kit/blob/24a438d23baa049fcd1d6b4b558634f7054de052/documentation/docs/60-appendix/35-migrating-to-sveltekit-3.md'; +const CODE_FILES = '**/*.{js,ts,svelte,mjs,mts,cjs,cts}'; export const GENERATED_MARKER = ''; type MigrationTask = { @@ -14,26 +17,11 @@ type MigrationTask = { links: Array<{ label: string; url: string }>; }; +function guideLink(anchor: string): MigrationTask['links'] { + return [{ label: 'Migrating to SvelteKit v3', url: `${GUIDE_URL}#${anchor}` }]; +} + const migrationTasks: MigrationTask[] = [ - { - title: 'Remove `experimental.handleRenderingErrors`', - checks: [ - { - include: '**/{svelte,vite}.config.{js,ts,mjs,mts,cjs,cts}', - patterns: ['handleRenderingErrors'] - } - ], - summary: - 'SvelteKit 3 removes the `experimental.handleRenderingErrors` feature flag because rendering errors are now handled this way by default.', - instructions: - 'Remove the `handleRenderingErrors` property from the SvelteKit configuration. If that leaves an empty `experimental` object, remove that object as well. No replacement option is needed — SvelteKit 3 always wraps route components in error boundaries so rendering errors reach the nearest `+error.svelte` page.', - links: [ - { - label: 'SvelteKit PR #16265', - url: 'https://github.com/sveltejs/kit/pull/16265' - } - ] - }, { // Temporary: this is already handled by the automatic Kit 3 migration. It exercises a // migration task with multiple detection rules and can be removed after this task is proven. @@ -62,6 +50,339 @@ const migrationTasks: MigrationTask[] = [ url: 'https://nodejs.org/api/packages.html#subpath-imports' } ] + }, + { + title: 'Migrate remaining `$app/stores` usages', + checks: [ + { + include: CODE_FILES, + patterns: ['$app/stores'] + } + ], + summary: + 'The automatic migration can leave `$app/stores` references when their store semantics require application context.', + instructions: + 'Replace each remaining `$app/stores` reference with `$app/state`. Remove auto-subscription prefixes, read `page` and `navigating` directly, and use `updated.current`. Rewrite `getStores()`, `get(store)`, subscriptions, re-exports, and dynamic imports according to how the value is used rather than only changing the module name.', + links: guideLink('appstores-removed') + }, + { + title: 'Migrate the removed `$service-worker` module', + checks: [ + { + include: CODE_FILES, + patterns: ['$service-worker'] + } + ], + summary: + 'SvelteKit 3 removes `$service-worker` and replaces its exports with several new modules.', + instructions: + 'Import `version` from `$app/env`, application asset metadata from `$app/manifest`, and path helpers from `$app/paths`. Account for the new manifest value shapes rather than blindly renaming `build` or `files` imports.', + links: guideLink('service-worker-removed') + }, + { + title: 'Create a TypeScript project for the service worker', + checks: [ + { + include: ['src/service-worker.ts', 'src/service-worker/**/*.ts'], + patterns: [/\S/] + } + ], + summary: + 'TypeScript service workers now need a separate project with service-worker-specific types.', + instructions: + 'Exclude the service worker from the root tsconfig and ensure `src/service-worker/tsconfig.json` extends `$app/tsconfig/service-worker`. Move a flat `src/service-worker.ts` entry to `src/service-worker/index.ts` if necessary, preserving any tooling references.', + links: guideLink('apptsconfigservice-worker') + }, + { + title: 'Make the service worker module-compatible', + checks: [ + { + include: ['src/service-worker.{js,ts}', 'src/service-worker/**/*.{js,ts}'], + patterns: [/\bimportScripts\s*\(/] + } + ], + summary: + 'SvelteKit 3 registers service workers as modules, where classic worker APIs may not work.', + instructions: + 'Replace `importScripts(...)` and any other classic-worker-only assumptions with module imports or module-compatible equivalents.', + links: guideLink('service-worker-registrations-use-type-module') + }, + { + title: 'Copy `page.url` before mutating it', + checks: [ + { + include: CODE_FILES, + patterns: [ + /\bpage\s*\.\s*url\s*\.\s*searchParams\s*\.\s*(?:append|delete|set|sort)\s*\(/, + /\bpage\s*\.\s*url\s*\.\s*(?:hash|host|hostname|href|password|pathname|port|protocol|search|username)\s*(?:=|\+\+|--)/ + ] + } + ], + summary: '`page.url` and its search parameters are readonly in SvelteKit 3.', + instructions: + 'Create a mutable copy with `new URL(page.url.href)`, mutate that copy, and use it for navigation or serialization. Leave readonly accesses unchanged.', + links: guideLink('pageurl-is-now-readonly') + }, + { + title: 'Review `goto` destinations', + checks: [ + { + include: CODE_FILES, + patterns: [/(?=[\s\S]*['"]\$app\/navigation['"])(?=[\s\S]*\bgoto\s*\()/] + } + ], + summary: '`goto(...)` now rejects destinations that do not resolve to an application route.', + instructions: + 'Confirm each destination is an internal route. Use `window.location.href` for external browser navigation, and handle rejected dynamic destinations where they can fail to resolve.', + links: guideLink('goto-rejects-for-urls-that-dont-resolve-to-a-route') + }, + { + title: 'Guard navigation `delta` access', + checks: [ + { + include: CODE_FILES, + patterns: [ + /(?=[\s\S]*['"]\$app\/navigation['"])(?=[\s\S]*(?:\.\s*delta\b|\{[^}]*\bdelta\b))/ + ] + } + ], + summary: 'Navigation `delta` is now only defined for `popstate` navigations.', + instructions: + 'Check the navigation type or handle `undefined` before using `delta`. Do not treat an absent delta as zero unless that has the intended application meaning.', + links: guideLink('delta-only-exists-for-popstate-navigations') + }, + { + title: 'Handle `preloadData` errors', + checks: [ + { + include: CODE_FILES, + patterns: [/(?=[\s\S]*['"]\$app\/navigation['"])(?=[\s\S]*\bpreloadData\s*\()/] + } + ], + summary: + '`preloadData(...)` can now return an error result, and redirects report their real status.', + instructions: + 'Inspect the complete result flow and add handling for `{ type: "error", status, error }` where absent. Do not assume every non-redirect result is loaded or has status 200.', + links: guideLink('preloaddata-can-return-an-error-result') + }, + { + title: 'Review enhanced forms with explicit actions', + checks: [ + { + include: '**/*.svelte', + patterns: [/(?=[\s\S]*\buse:enhance\b)(?=[\s\S]*]*\baction\s*=)/] + } + ], + summary: 'Enhanced forms that submit to another page now navigate to that page.', + instructions: + 'Determine whether each action resolves to another page and confirm navigation is intended. If the form must remain on the current page, implement that behavior explicitly in the enhancement callback.', + links: guideLink('appforms') + }, + { + title: 'Migrate `handleValidationError`', + checks: [ + { + include: '**/hooks*.{js,ts,mjs,mts}', + patterns: ['handleValidationError'] + } + ], + summary: '`handleValidationError` is removed in SvelteKit 3.', + instructions: + 'Move validation-error handling into `handleError` and branch on `kind === "validation"`. Merge it carefully with any existing `handleError` logic.', + links: guideLink('handlevalidationerror-is-removed') + }, + { + title: 'Review `handleError` behavior', + checks: [ + { + include: '**/hooks*.{js,ts,mjs,mts}', + patterns: ['handleError'] + } + ], + summary: 'SvelteKit 3 sends expected, validation, and rendering errors through `handleError`.', + instructions: + 'Review filtering, logging, reporting, returned error properties, and status handling for the broader set of errors. If `hooks.client` has an async hook, enable `compilerOptions.experimental.async` in `sveltekit(...)`.', + links: guideLink('handleerror-receives-all-errors') + }, + { + title: 'Remove the Node polyfills import', + checks: [ + { + include: CODE_FILES, + patterns: ['@sveltejs/kit/node/polyfills'] + } + ], + summary: '`@sveltejs/kit/node/polyfills` is removed because SvelteKit 3 requires modern Node.', + instructions: + 'Remove the obsolete side-effect import and verify that the custom server or adapter runs on Node 22.17 or newer.', + links: guideLink('sveltejskitnodepolyfills-removed') + }, + { + title: 'Remove `await` from synchronous Node helpers', + checks: [ + { + include: CODE_FILES, + patterns: [ + /(?=[\s\S]*['"]@sveltejs\/kit\/node['"])(?=[\s\S]*\bawait\s+(?:\w+\.)?(?:getRequest|setResponse)\s*\()/ + ] + } + ], + summary: '`getRequest` and `setResponse` from `@sveltejs/kit/node` are now synchronous.', + instructions: + 'Remove `await` only from calls bound to those SvelteKit helpers, then review surrounding promise composition and return types.', + links: guideLink('sveltejskitnode') + }, + { + title: 'Rename cookie option types', + checks: [ + { + include: CODE_FILES, + patterns: ['CookieSerializeOptions', 'CookieParseOptions'] + } + ], + summary: 'Cookie v2 renames its serialization and parsing option types.', + instructions: + 'Rename `CookieSerializeOptions` to `SerializeOptions` and `CookieParseOptions` to `ParseOptions`, changing only types imported from the `cookie` package.', + links: guideLink('updated-to-cookie-v2') + }, + { + title: 'Replace non-ASCII cookie names', + checks: [ + { + include: CODE_FILES, + patterns: [ + /\bcookies\s*\.\s*(?:get|getAll|set|delete|serialize)\s*\(\s*['"][^'"]*[^\x00-\x7f][^'"]*['"]/ + ] + } + ], + summary: 'Cookie v2 rejects cookie names containing non-ASCII characters.', + instructions: + 'Choose a stable ASCII replacement and consider compatibility or cleanup for cookies already issued under the old name.', + links: guideLink('updated-to-cookie-v2') + }, + { + title: 'Rename Cloudflare `platform.context`', + checks: [ + { + include: CODE_FILES, + patterns: [/\bplatform\s*(?:\?\.|\.)\s*context\b/] + } + ], + summary: 'The Cloudflare adapter replaces `platform.context` with `platform.ctx`.', + instructions: + 'Confirm the value is the Cloudflare platform execution context, then rename it to `platform.ctx` and update related platform typings.', + links: guideLink('adapter-cloudflare') + }, + { + title: 'Move adapter-node `ORIGIN` to `paths.origin`', + checks: [ + { + include: ['Dockerfile*', '**/Dockerfile*', '**/*.{js,ts,mjs,mts,json,jsonc,yml,yaml,toml}'], + patterns: [ + /\bprocess\.env\.ORIGIN\b/, + /\benv\s*\[\s*['"]ORIGIN['"]\s*\]/, + /^\s*(?:ENV|ARG)\s+ORIGIN\b/m, + /^\s*ORIGIN\s*[:=]/m + ] + } + ], + summary: 'The adapter-node `ORIGIN` environment variable is removed.', + instructions: + 'If this value configures adapter-node, move the public-facing origin to `paths.origin` in `sveltekit(...)`. Remove the environment variable only after confirming it has no unrelated use.', + links: guideLink('adapter-node') + }, + { + title: 'Replace the Vercel edge runtime', + checks: [ + { + include: '**/*.{js,ts,mjs,mts,json,jsonc}', + patterns: [/\bruntime\s*:\s*['"]edge['"]/] + } + ], + summary: 'The Vercel adapter no longer supports the edge runtime.', + instructions: + 'Select a supported Vercel runtime and review runtime-specific APIs, dependencies, and deployment behavior before changing the configuration.', + links: guideLink('adapter-vercel') + }, + { + title: 'Replace `builder.createEntries` in custom adapters', + checks: [ + { + include: CODE_FILES, + patterns: [/\bbuilder\s*\.\s*createEntries\s*\(/] + } + ], + summary: 'The adapter API removes `builder.createEntries`.', + instructions: + 'Replace it with the appropriate `builder.writeClient`, `builder.writeServer`, and `builder.writePrerendered` flow for the adapter output model.', + links: guideLink('adapter-api-changes') + }, + { + title: 'Remove request route data from remote queries', + checks: [ + { + include: ['**/*.remote.{js,ts}', '**/*.remote.*.{js,ts}', '**/remote.{js,ts}'], + patterns: [/\bevent\s*\.\s*(?:url|params|route)\b/] + } + ], + summary: 'Remote queries can no longer access `event.url`, `event.params`, or `event.route`.', + instructions: + 'Pass the required values explicitly as validated query arguments and remove the request-specific event access.', + links: guideLink('eventurl-eventparams-and-eventroute-cannot-be-accessed-inside-queries') + }, + { + title: 'Use remote form field attributes', + checks: [ + { + include: '**/*.svelte', + patterns: [ + /(?=[\s\S]*(?:from\s*['"][^'"]+\.remote(?:\.[^'"]+)?['"]|import\(\s*['"][^'"]+\.remote))(?=[\s\S]*\bname\s*=)/ + ] + } + ], + summary: 'Remote form controls must use attributes from the current form field.', + instructions: + 'Replace manually specified control names with attributes from the corresponding field `.as(...)` method, verifying that the field belongs to the submitted form.', + links: guideLink('form-submissions-require-fieldas') + }, + { + title: 'Review consumers of 204 responses', + checks: [ + { + include: ['src/routes/**/+server.{js,ts}', '**/*.{test,spec}.{js,ts,mjs,mts}'], + patterns: [/\bstatus\s*:\s*204\b/] + } + ], + summary: 'SvelteKit 3 returns no body for 204 and other empty 2xx responses.', + instructions: + 'Find callers and tests for the matched endpoint and ensure they do not parse JSON or text from its empty response. Keep the endpoint response unchanged if it is already spec-compliant.', + links: guideLink('204-responses-return-no-content') + }, + { + title: 'Replace remaining `csrf.checkOrigin` configuration', + checks: [ + { + include: '**/{svelte,vite}.config.{js,ts,mjs,mts,cjs,cts}', + patterns: ['checkOrigin'] + } + ], + summary: '`csrf.checkOrigin` is removed and CSRF protection is always enabled.', + instructions: + 'Remove `checkOrigin`. If cross-origin submissions are intentional, configure the narrowest possible `csrf.trustedOrigins` allowlist instead of disabling protection.', + links: guideLink('csrfcheckorigin-replaced-by-csrftrustedorigins') + }, + { + title: 'Review cross-origin form submissions', + checks: [ + { + include: '**/*.svelte', + patterns: [/]*\baction\s*=\s*['"](?:https?:)?\/\//] + } + ], + summary: 'Cross-origin mutative requests without a `Content-Type` header are rejected as CSRF.', + instructions: + 'Ensure the submission sends an appropriate `Content-Type` header or add the destination to the narrowest possible `csrf.trustedOrigins` allowlist.', + links: guideLink('cross-origin-form-submissions-require-a-content-type-header') } ]; diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/package-json/package.snapshot.json b/packages/sv/src/migrate/migrations/sveltekit-3/tests/package-json/package.snapshot.json index 89b77e597..39096a3db 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tests/package-json/package.snapshot.json +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/package-json/package.snapshot.json @@ -3,8 +3,8 @@ "@sveltejs/adapter-auto": "next", "@sveltejs/kit": "next", "@sveltejs/vite-plugin-svelte": "^7.0.0", - "svelte": "^5.48.0", + "svelte": "^5.56.4", "typescript": "^6.0.0", - "vite": "^8.0.0" + "vite": "^8.0.12" } } diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md index fb78556a2..a993c2916 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md @@ -22,41 +22,39 @@ Also search the project for `@migration-task` comments. They may describe additi ## Migration tasks -### Remove `experimental.handleRenderingErrors` +### Replace the `$lib` alias with `#lib` and remove `files.lib` -SvelteKit 3 removes the `experimental.handleRenderingErrors` feature flag because rendering errors are now handled this way by default. +SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field. #### What to do -Remove the `handleRenderingErrors` property from the SvelteKit configuration. If that leaves an empty `experimental` object, remove that object as well. No replacement option is needed — SvelteKit 3 always wraps route components in error boundaries so rendering errors reach the nearest `+error.svelte` page. +Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports. #### References -- [SvelteKit PR #16265](https://github.com/sveltejs/kit/pull/16265) +- [SvelteKit PR #16360](https://github.com/sveltejs/kit/pull/16360) +- [Node.js package imports](https://nodejs.org/api/packages.html#subpath-imports) #### Files to review -- [ ] `nested/svelte.config.ts` +- [ ] `src/routes/+page.svelte` - [ ] `svelte.config.js` -- [ ] `vite.config.ts` -### Replace the `$lib` alias with `#lib` and remove `files.lib` +### Copy `page.url` before mutating it -SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field. +`page.url` and its search parameters are readonly in SvelteKit 3. #### What to do -Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports. +Create a mutable copy with `new URL(page.url.href)`, mutate that copy, and use it for navigation or serialization. Leave readonly accesses unchanged. #### References -- [SvelteKit PR #16360](https://github.com/sveltejs/kit/pull/16360) -- [Node.js package imports](https://nodejs.org/api/packages.html#subpath-imports) +- [Migrating to SvelteKit v3](https://github.com/sveltejs/kit/blob/24a438d23baa049fcd1d6b4b558634f7054de052/documentation/docs/60-appendix/35-migrating-to-sveltekit-3.md#pageurl-is-now-readonly) #### Files to review - [ ] `src/routes/+page.svelte` -- [ ] `svelte.config.js` ## Final verification diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte index 490d4276a..bad2b0906 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte @@ -1,5 +1,8 @@ From fe1a9f1717227e76f3f9f423485a602f5af9c0fd Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 10 Aug 2026 14:44:14 +0200 Subject: [PATCH 3/3] rename --- .../migrate/migrations/sveltekit-3/index.ts | 4 +- ...n.ts => collect-migration-instructions.ts} | 46 ++----------- .../MIGRATION_TASKS.snapshot.md | 43 ++++++++++++ .../nested/svelte.config.ts | 0 .../src/routes/+page.svelte | 0 .../svelte.config.js | 0 .../vite.config.ts | 0 .../MIGRATION_TASKS.snapshot.md | 65 ------------------- 8 files changed, 52 insertions(+), 106 deletions(-) rename packages/sv/src/migrate/migrations/sveltekit-3/tasks/{prepare-ai-migration.ts => collect-migration-instructions.ts} (88%) create mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/MIGRATION_TASKS.snapshot.md rename packages/sv/src/migrate/migrations/sveltekit-3/tests/{prepare-ai-migration => collect-migration-instructions}/nested/svelte.config.ts (100%) rename packages/sv/src/migrate/migrations/sveltekit-3/tests/{prepare-ai-migration => collect-migration-instructions}/src/routes/+page.svelte (100%) rename packages/sv/src/migrate/migrations/sveltekit-3/tests/{prepare-ai-migration => collect-migration-instructions}/svelte.config.js (100%) rename packages/sv/src/migrate/migrations/sveltekit-3/tests/{prepare-ai-migration => collect-migration-instructions}/vite.config.ts (100%) delete mode 100644 packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/index.ts b/packages/sv/src/migrate/migrations/sveltekit-3/index.ts index dabb14d1c..bf1502184 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/index.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/index.ts @@ -1,13 +1,13 @@ import { coerceVersion, color } from '@sveltejs/sv-utils'; import { defineMigration } from '../../index.ts'; import appState from '../app-state/tasks/app-state.ts'; +import collectMigrationInstructions from './tasks/collect-migration-instructions.ts'; import environment from './tasks/environment.ts'; import externalRedirects from './tasks/external-redirects.ts'; import libAlias from './tasks/lib-alias.ts'; import packageJson from './tasks/package-json.ts'; import params from './tasks/params.ts'; import paths from './tasks/paths.ts'; -import prepareAiMigration from './tasks/prepare-ai-migration.ts'; import shallowRouting from './tasks/shallow-routing.ts'; import svelteConfig from './tasks/svelte-config.ts'; import tsconfig from './tasks/tsconfig.ts'; @@ -44,6 +44,6 @@ export default defineMigration({ tasks.add(params, { prerequisite: false }); tasks.add(libAlias, { prerequisite: false }); tasks.add(appState, { prerequisite: false }); - tasks.add(prepareAiMigration, { prerequisite: false }); + tasks.add(collectMigrationInstructions, { prerequisite: false }); } }); diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/collect-migration-instructions.ts similarity index 88% rename from packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts rename to packages/sv/src/migrate/migrations/sveltekit-3/tasks/collect-migration-instructions.ts index c6df37d88..33a7f9ed9 100644 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tasks/prepare-ai-migration.ts +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tasks/collect-migration-instructions.ts @@ -4,7 +4,8 @@ const REPORT_PATH = 'MIGRATION_TASKS.md'; const GUIDE_URL = 'https://github.com/sveltejs/kit/blob/24a438d23baa049fcd1d6b4b558634f7054de052/documentation/docs/60-appendix/35-migrating-to-sveltekit-3.md'; const CODE_FILES = '**/*.{js,ts,svelte,mjs,mts,cjs,cts}'; -export const GENERATED_MARKER = ''; +export const GENERATED_MARKER = + ''; type MigrationTask = { title: string; @@ -22,35 +23,6 @@ function guideLink(anchor: string): MigrationTask['links'] { } const migrationTasks: MigrationTask[] = [ - { - // Temporary: this is already handled by the automatic Kit 3 migration. It exercises a - // migration task with multiple detection rules and can be removed after this task is proven. - title: 'Replace the `$lib` alias with `#lib` and remove `files.lib`', - checks: [ - { - include: '**/*.{js,ts,svelte,mjs,mts,cjs,cts}', - patterns: ['$lib'] - }, - { - include: '**/{svelte,vite}.config.{js,ts,mjs,mts,cjs,cts}', - patterns: [/\bfiles\s*:\s*\{[\s\S]*?\blib\s*:/] - } - ], - summary: - 'SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field.', - instructions: - 'Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports.', - links: [ - { - label: 'SvelteKit PR #16360', - url: 'https://github.com/sveltejs/kit/pull/16360' - }, - { - label: 'Node.js package imports', - url: 'https://nodejs.org/api/packages.html#subpath-imports' - } - ] - }, { title: 'Migrate remaining `$app/stores` usages', checks: [ @@ -389,8 +361,8 @@ const migrationTasks: MigrationTask[] = [ type Finding = { task: MigrationTask; files: string[] }; export default defineMigrationTask({ - id: 'prepare-ai-migration', - description: 'Prepare instructions for AI-assisted migration tasks', + id: 'collect-migration-instructions', + description: 'Collect instructions for non-automated migration tasks', run: ({ sv }) => { const findings: Finding[] = []; @@ -456,15 +428,11 @@ ${locations}`; return `${GENERATED_MARKER} # SvelteKit 3 migration tasks -## For humans - -Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. Modern AI assistants can handle many of these cases effectively when they are given focused context. This file uses that current technology to bridge the gap while keeping the automatic migrations reliable and maintainable. - -The findings are intentionally broad and may include files that do not require changes. Review the AI's work before accepting it. +Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. This document lists them. -## For AI assistants +The findings are intentionally broad and may include files that do not require changes. -Work through the migration tasks below one at a time: +AI agents can work through the migration tasks below one at a time: 1. Read the linked documentation or pull request before changing code. 2. Inspect every listed file and its surrounding context. diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/MIGRATION_TASKS.snapshot.md b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/MIGRATION_TASKS.snapshot.md new file mode 100644 index 000000000..37e0361e1 --- /dev/null +++ b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/MIGRATION_TASKS.snapshot.md @@ -0,0 +1,43 @@ + +# SvelteKit 3 migration tasks + +Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. This document lists them. + +The findings are intentionally broad and may include files that do not require changes. + +AI agents can work through the migration tasks below one at a time: + +1. Read the linked documentation or pull request before changing code. +2. Inspect every listed file and its surrounding context. +3. Ignore a finding when the file is not actually affected. +4. Make the smallest necessary change. Do not perform unrelated refactors or introduce unnecessary abstractions. +5. Ask the user when application intent cannot be inferred. +6. Run the project's appropriate checks after editing. + +Also search the project for `@migration-task` comments. They may describe additional manual migration work that must be resolved. + +## Migration tasks + +### Copy `page.url` before mutating it + +`page.url` and its search parameters are readonly in SvelteKit 3. + +#### What to do + +Create a mutable copy with `new URL(page.url.href)`, mutate that copy, and use it for navigation or serialization. Leave readonly accesses unchanged. + +#### References + +- [Migrating to SvelteKit v3](https://github.com/sveltejs/kit/blob/24a438d23baa049fcd1d6b4b558634f7054de052/documentation/docs/60-appendix/35-migrating-to-sveltekit-3.md#pageurl-is-now-readonly) + +#### Files to review + +- [ ] `src/routes/+page.svelte` + +## Final verification + +- [ ] Review every migration task and ignore any irrelevant findings. +- [ ] Resolve remaining `@migration-task` comments. +- [ ] Run the project's type checker and tests. +- [ ] Build the project successfully. +- [ ] Delete this file when all migration work is complete. diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/nested/svelte.config.ts similarity index 100% rename from packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/nested/svelte.config.ts rename to packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/nested/svelte.config.ts diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/src/routes/+page.svelte similarity index 100% rename from packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/src/routes/+page.svelte rename to packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/src/routes/+page.svelte diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/svelte.config.js similarity index 100% rename from packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/svelte.config.js rename to packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/svelte.config.js diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts b/packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/vite.config.ts similarity index 100% rename from packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/vite.config.ts rename to packages/sv/src/migrate/migrations/sveltekit-3/tests/collect-migration-instructions/vite.config.ts diff --git a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md b/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md deleted file mode 100644 index a993c2916..000000000 --- a/packages/sv/src/migrate/migrations/sveltekit-3/tests/prepare-ai-migration/MIGRATION_TASKS.snapshot.md +++ /dev/null @@ -1,65 +0,0 @@ - -# SvelteKit 3 migration tasks - -## For humans - -Some migrations are uncommon, context-dependent, or disproportionately difficult to automate safely. Modern AI assistants can handle many of these cases effectively when they are given focused context. This file uses that current technology to bridge the gap while keeping the automatic migrations reliable and maintainable. - -The findings are intentionally broad and may include files that do not require changes. Review the AI's work before accepting it. - -## For AI assistants - -Work through the migration tasks below one at a time: - -1. Read the linked documentation or pull request before changing code. -2. Inspect every listed file and its surrounding context. -3. Ignore a finding when the file is not actually affected. -4. Make the smallest necessary change. Do not perform unrelated refactors or introduce unnecessary abstractions. -5. Ask the user when application intent cannot be inferred. -6. Run the project's appropriate checks after editing. - -Also search the project for `@migration-task` comments. They may describe additional manual migration work that must be resolved. - -## Migration tasks - -### Replace the `$lib` alias with `#lib` and remove `files.lib` - -SvelteKit 3 removes the built-in `$lib` alias and the `kit.files.lib` configuration. The replacement is a Node subpath import named `#lib`, configured through the package.json `imports` field. - -#### What to do - -Replace remaining `$lib` module references with `#lib`. Add `"#lib": "./src/lib/index.js"` and `"#lib/*": "./src/lib/*"` to package.json `imports`, adjusting `src/lib` if the project used a custom library directory. Remove `files.lib` from the SvelteKit configuration. Check imports, re-exports, dynamic imports, ambient module declarations, tests, and configuration strings rather than assuming every textual match is executable code. If the project intentionally needs to preserve `$lib`, configure it explicitly through SvelteKit `alias` instead of adding the `#lib` imports. - -#### References - -- [SvelteKit PR #16360](https://github.com/sveltejs/kit/pull/16360) -- [Node.js package imports](https://nodejs.org/api/packages.html#subpath-imports) - -#### Files to review - -- [ ] `src/routes/+page.svelte` -- [ ] `svelte.config.js` - -### Copy `page.url` before mutating it - -`page.url` and its search parameters are readonly in SvelteKit 3. - -#### What to do - -Create a mutable copy with `new URL(page.url.href)`, mutate that copy, and use it for navigation or serialization. Leave readonly accesses unchanged. - -#### References - -- [Migrating to SvelteKit v3](https://github.com/sveltejs/kit/blob/24a438d23baa049fcd1d6b4b558634f7054de052/documentation/docs/60-appendix/35-migrating-to-sveltekit-3.md#pageurl-is-now-readonly) - -#### Files to review - -- [ ] `src/routes/+page.svelte` - -## Final verification - -- [ ] Review every migration task and ignore any irrelevant findings. -- [ ] Resolve remaining `@migration-task` comments. -- [ ] Run the project's type checker and tests. -- [ ] Build the project successfully. -- [ ] Delete this file when all migration work is complete.