feat: Migrate to SvelteKit 3 - #244
Merged
Merged
Conversation
Ran `sv migrate sveltekit-3` and worked through the manual tasks it collected.
Config:
- `experimental.tracing` -> top-level `tracing.server`, and
`experimental.instrumentation` is gone (instrumentation.server.ts is picked
up automatically now)
- `vitePlugin.inspector` moves to the top level of the sveltekit() options
- `KitConfig` is no longer exported from `@sveltejs/kit`; take `Config` from
`@sveltejs/kit/vite` instead
- tsconfig extends `$app/tsconfig`, mirrors the new `#lib` subpath imports in
`paths` (svelte-check resolves .svelte imports itself and only understands
tsconfig paths, not package.json imports) and keeps type-checking the
config, plugin and e2e sources
Paths:
- `Path` no longer carries a leading slash, so pathname literals, breadcrumb
and sidebar entries drop it
- `prefixBase()` still takes a union-typed pathname, which `resolve()` cannot
(it is generic over a single literal path), and derives the base path from
PUBLIC_SITE_URL the same way vite.config.ts does — `resolve()` returns a
path relative to the page being rendered, which cannot be compared against
page.url.pathname nor back the absolute URLs in the sitemap and canonical
tags
Environment, hooks and navigation:
- `$env/static|dynamic/*` -> `$app/env/*` through the generated src/env.ts;
the previously dynamic variables keep an empty-string fallback, which every
consumer treats exactly like the old `undefined`
- `handleError` discriminates on `kind`, so expected app and framework errors
(404s and friends, which SvelteKit 3 also routes through the hook) log at
warn instead of drowning real defects in telemetry
- `replaceState()` -> shallow `goto()`, `keepFocus`/`noScroll` -> `reset`
- parameter matchers consolidated into src/params.ts
Also fixes three bugs the type checker surfaced on the way:
- the logo asset is `logo.svg`, not `Logo.svg`, so the social preview image
and the welcome screen preload were 404ing
- public-routes.ts cast its computed paths to `Path`, which hid the
leading-slash change from the compiler — sitemap.xml and llms.txt would
have emitted `https://home/`-style URLs
- redirectLegacyHashRoute() was handed `resolve('')`, yielding the
protocol-relative `//home`
`pnpm run check` passes `--tsgo`, which svelte-check only honours when TypeScript 7 is installed under the `@typescript/native` npm alias — otherwise it aborts with "requires TypeScript 7 to be installed in the workspace". It was resolving only because pnpm hoists the alias out of the packages/svelte-core workspace package, so any lockfile change that dropped it there silently broke type-checking here. Declare it locally, matching the version svelte-core pins. TypeScript itself stays on 6: @sveltejs/kit 3, svelte-check and typescript-eslint all cap their `typescript` peer below 7.
The (app) auth gate sent the interrupted destination to /login as `next`, but nothing ever read that parameter: the login flow and the (auth) layout both go through gotoQueryRedirectOrFallback(), which reads REDIRECT_QUERY_PARAM. Signing back in after a session expired therefore always landed on /home. Use the constant on both sides so the two halves cannot drift again.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🔵 In progress View logs |
openshock-app-dev | 1ed3158 | Oct 02 2026, 09:15 AM |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
All seven conflicts were the same kind: develop reached the same result in SvelteKit 2 spelling while this branch had already migrated it. - `asset()`/`resolve()` arguments keep this branch's slashless form; the substance of develop's `Logo.svg` -> `logo.svg` casing fix is already here. - `#lib/...js` imports keep this branch's subpath form over `$lib`. - develop's redirect-after-reauth fix is the same change as f609688. - pnpm-lock.yaml follows package.json in dropping formsnap and sveltekit-superforms from the root importer; packages/svelte-core keeps both.
package.json keeps this branch's prerelease pins for `@sveltejs/kit` and both adapters, plus its `#lib` imports map, and takes develop's other bumps — vite-plugin-svelte, svelte, svelte-check, svelte-sonner and pnpm 11.22.0. pnpm-lock.yaml is regenerated from this branch's copy so the SvelteKit 3 prereleases stay pinned. Regenerating left a stale svelte 5.56.8 beside 5.56.9, which is the duplicate that makes every snippet fail to type-check against a `Snippet` prop; `pnpm dedupe` collapses it, and the `dedupe --check` step this merge brings in from develop guards it going forward. The submodule points at svelte-core's own feature/svelte-kit-3 rather than its master, and .gitmodules now records that branch, so `git submodule update --remote` tracks the migration branch here instead of pulling master back in.
Conflicts came from develop's online-hubs rewrite landing on top of this branch's SvelteKit 3 migration. Resolutions: - package.json: keep the SvelteKit 3 pins (kit 3.0.0-next.23, adapter-cloudflare 8.0.0-next.6, adapter-node 6.0.0-next.10) and the `#lib` imports map, take develop's other bumps, and move packageManager to pnpm@12.5.1 so it matches the Dockerfile ARG that came with develop's toolchain update (ci-lint.yml checks the two agree). - pnpm-lock.yaml: rebuilt from develop's copy so only the kit 2 -> 3 resolutions differ. - packages/svelte-core: merged master into the package's own feature/svelte-kit-3 branch and repointed the submodule at the result. - online-hubs: took develop's rewrite wholesale, restated its imports in this branch's `#lib/...js` style, and kept the branch's leading-slash-free `resolve()` paths. develop's removal of the placeholder Edit and Delete actions stands. pnpm check, lint, format:check and test:unit pass in both repos. E2E is unverified: `vite preview` needs a local.openshock.app hosts entry and port 443 rights this machine does not have.
@sveltejs/kit 3.0.0-next.23 -> 3.0.0-next.30, adapter-node 6.0.0-next.10 -> 6.0.0-next.15, adapter-cloudflare 8.0.0-next.6 -> 8.0.0-next.7 — all three now at their `next` tip. `pnpm outdated` never flagged these: it compares against the `latest` dist-tag, which still points at the stable 2.x/5.x/7.x line, so an exact prerelease pin always looks current. adapter-node next.15 drops the `Reading config.kit inside adapters is deprecated` warning the build used to emit. svelte-core picks up the restored sidebar/slider customizations and its own dependency bumps. Because it declares `"@sveltejs/kit": "next"`, its resolution had run ahead of the frontend's pin and the workspace was installing two SvelteKit copies; matching the pin collapses that, along with a duplicate bits-ui, for a net -9 packages. typescript stays on ~6.0.3 — 7.x comes in separately via the @typescript/native alias for tsgo. Verified: check, lint, format:check, test:unit and dedupe --check pass, and both the node and Cloudflare (WORKERS_CI=1) adapter builds succeed.
Moves off the SvelteKit 3 prereleases now that stable is out: @sveltejs/kit 3.0.0-next.30 -> 3.0.0, adapter-cloudflare 8.0.0-next.7 -> 8.0.0, adapter-node 6.0.0-next.15 -> 6.0.0. Also bumps typescript-eslint and wrangler. The three stable pins are added to minimumReleaseAgeExclude so the 3-day quarantine does not block them. Bumps packages/svelte-core to a17e5e0, which removes the unused shadcn ui/form component set along with its formsnap and sveltekit-superforms peers. Nothing in this app imported ui/form, so no source changes are needed here. superforms declared a required peer on @sveltejs/kit 1.x || 2.x and was the last genuine SvelteKit 3 peer conflict in the tree; dropping it removes 45 packages from the install. Verified with svelte-check (459 files, 0 errors), a production build, eslint and prettier.
src/env.ts had the structural migration to defineEnvVars but used none of what the new API offers: every variable was an untyped string, and the only schema present was a `?? ''` shim preserving the old $env/dynamic/* behaviour. Each variable now declares: - a `description`, carried over from the comments in .env, which surfaces as inline documentation on hover at every import site - a `schema` that validates on build (static) or startup (dynamic), so a misconfigured deployment fails immediately with a named error instead of throwing at the first request that happens to touch the value - a transformation, so consumers receive the type they actually want Flags are coerced to real booleans, which lets every call site drop isTruthy() and `=== 'true'`. Text values are trimmed in the schema, removing the .trim() calls in metadata.ts and llms.txt. URLs are parsed and rejected unless absolute http(s); PUBLIC_BACKEND_API_URL additionally requires HTTPS with no query or fragment, mirroring the checks getApiUrl() performs. Those checks stay in url.ts as well, since url.test.ts mocks $app/env/public and never runs these schemas. URLs stay strings rather than becoming URL instances, so static values remain inlinable and dynamic public ones stay devalue-serializable. The flag helper reimplements isTruthy instead of importing it: SvelteKit evaluates src/env.ts in a plain Node context to resolve static values, and the @openshock/svelte-core/utils barrel reaches clipboard.svelte.ts -> svelte-sonner -> a .svelte file, which Node cannot load. The module is kept free of app and package imports. static/dynamic split is unchanged, so no deployment switch changes meaning. Verified that booleans inline as real literals, that dynamic flags validate at startup, and that bad values fail the build: PUBLIC_DISCORD_INVITE_URL is not a valid absolute URL: nonsense PUBLIC_BACKEND_API_URL must be an HTTPS URL PUBLIC_SITE_NAME must be set to a non-empty value svelte-check 459 files 0 errors, 338 unit tests passing, production build, eslint and prettier all clean.
src/env.ts had its own reimplementation of isTruthy plus a `flag` wrapper around it. Both are gone: the schema for every boolean variable is now isTruthy itself, imported from the submodule source. The reason the copy existed was that `@openshock/svelte-core/utils` is a barrel that re-exports clipboard.svelte.ts, which imports svelte-sonner and so reaches a real .svelte file. SvelteKit evaluates src/env.ts in a plain Node context to resolve `static` values, where that fails with `Unknown file extension ".svelte"`. The barrel was the problem, not the package, so importing the file directly sidesteps it and leaves one definition of isTruthy in the tree. Exporting isTruthy from src/env.ts and importing it into app code was tried first and rejected: onboarding-state.ts runs on the client, so pulling src/env.ts into its module graph shipped the entire `variables` object to the browser. The client bundle then contained every description and validator message, including the name and the "INSECURE" description of PRIVATE_BACKEND_TLS_INSECURE. Confirmed against a build at the previous commit, where those strings are absent, and confirmed absent again here. App code keeps importing isTruthy from @openshock/svelte-core/utils; only env.ts needs the barrel-free path. No behaviour change. svelte-check 459 files 0 errors, 338 unit tests, production build, eslint and prettier clean; static flags still inline as real boolean literals and dynamic ones still validate at startup.
hhvrc
marked this pull request as ready for review
October 2, 2026 09:12
svelte-core's feature/svelte-kit-3 branch was squash-merged into master as
c058e94 ("feat: Migrate to SvelteKit 3 (#18)") and the branch was deleted,
so the previous pointer a17e5e0 is no longer reachable from any remote
branch. Repoints the submodule at c058e94 and retargets the tracked branch
in .gitmodules from the deleted feature/svelte-kit-3 to master, so
`git submodule update --remote` keeps working.
The only content difference between a17e5e0 and c058e94 is a refactor of
isTruthy in src/lib/utils/parse.ts. It accepts the same set of values
(1 / true / yes / y / on, case-insensitive), so the env flags in src/env.ts
that use it as their schema are unaffected. package.json is identical, so
the lockfile does not move.
svelte-check 459 files 0 errors, 338 unit tests, production build, eslint
and prettier clean; static flags still inline as real boolean literals.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.