The Svelte team moved SvelteKit 3 to Release Candidate in early September 2026, days after Svelte 5.57 shipped. The major version of the meta-framework reorganises its Vite integration, adopts Node subpath imports in place of the $lib alias, and hands migration to a new command-line tool. Nothing is frozen in stone yet, but the upgrade path is now legible.
A Release Candidate, not yet a stable release
SvelteKit 3 matured through successive prereleases, from 3.0.0-next.17 to 3.0.0-next.25 by the time the Release Candidate was announced. That status signals a frozen API surface: the team is mainly waiting for real-world feedback before the final release and should introduce no further breaking change. Production projects are therefore better off testing the switch on a dedicated branch rather than upgrading in a hurry.
The Vite plugin at the heart of the rework
The structural change in this version is the rewrite of the Vite plugin architecture. SvelteKit aligns with Vite’s recent evolution and clarifies the boundary between framework and bundler, with reworked form actions and several routing refinements as a result. This shift toward more modern foundations continues a broader trend in front-end tooling.
From $lib to #lib: internal imports adopt a Node convention
In a project created with the new tooling, internal imports no longer go through the in-house $lib alias but through #lib, which relies on the imports field of package.json, that is, Node’s standard subpath imports.
{
"imports": {
"#lib/*": "./src/lib/*.js"
}
}
In practice, an import changes prefix without changing target:
- import { formatDate } from '$lib/utils';
+ import { formatDate } from '#lib/utils';
The benefit is to rely on a convention understood natively by Node, editors, and test tooling, with no framework-specific mechanism to configure on either side.
Svelte 5.57 ships alongside
Released in the same window, Svelte 5.57 adds several long-awaited primitives without breaking existing code.
| Addition | What it brings |
|---|---|
SvelteMap.getOrInsert and getOrInsertComputed | Read a key or initialise it in a single operation on a reactive Map |
Third has value from createContext() | Check whether a context has been set before trying to read it |
<select defaultValue> | Restores the chosen value on a form reset |
Types exported by svelte/server | RenderOutput, SyncRenderOutput, Csp and Sha256Source, useful for server rendering and CSP policies |
Migration handed to the sv command
The sv tool reaches version 1.0.0-next.0 and adopts a task-based migration model. A dedicated command applies the transformations specific to SvelteKit 3, including replacing $lib with #lib in new projects.
npx sv migrate sveltekit-3
This task-based approach mirrors how command-line tooling works in general: targeted, repeatable operations whose result can be reviewed in a diff before being accepted.
Worth watching: a Release Candidate is not a production release. It remains wise to pin the exact prerelease in the lockfile, re-run the test suite after migration, and keep an eye on third-party Vite plugins, some of which still assume the old architecture.
By freezing its API and standardising its imports on Node, SvelteKit 3 bets on predictability rather than spectacular novelty.
What to take away
The Release Candidate marks SvelteKit 3’s entry into its final stretch. The two changes to prepare for are the Vite plugin rework and the move from $lib to #lib. The sv command automates most of the upgrade, while Svelte 5.57 adds welcome API primitives in parallel. Until the final release ships, testing on a dedicated branch remains the way to go.
The move from $lib to #lib looks cosmetic and turns out, in practice, to be very handy: an import understood natively by Node is one edge case fewer to handle across editor, bundler, and tests. On my side, migrating through sv proved reliable on recent projects, provided it is run on a clean repository and the diff is reviewed before accepting. — Simon Janvier
Source: What’s new in Svelte: September 2026, on the project’s official blog.
