Repository navigation
Upgrade to SvelteKit 3 - #2661
Conversation
|
/preview |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Preview deployed
|
Query parameter schemas accept list types (`'string[]'`, `'number[]'`, `'<a,b>[]'`) encoded as repeated keys. Lists drop invalid and duplicate items, compare item by item, and are frozen so an in-place mutation cannot change state without updating the URL. An emptied list with a non-empty default writes an empty marker so a reload keeps it empty. Each instance now writes only its own keys onto the live URL, so several instances on one page no longer overwrite each other, and a new instance reads the visible URL rather than `page.url`, which shallow history writes do not update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the SvelteKit configuration into the Vite plugin, extend `$app/tsconfig`, declare param matchers with `defineParams`, and declare public environment variables in `src/env.ts`. They stay dynamic, so the container entrypoint can still rewrite `_app/env.js` at startup. localStorage overrides now live in an app-owned module because `$app/env/public` exports immutable bindings. Shallow routing uses `goto` with `shallow: true`. A shallow `goto` starts a navigation that aborts one already in progress, and SvelteKit 3 writes it asynchronously, so all shallow writes go through one queue that waits for navigations, derives each write when it runs, and persists page state across reloads. Query parameters, detail sheets, and saved views read their entry markers from `page.state` instead of SvelteKit's internal history format. SvelteKit applies a traversed entry's page state before component popstate listeners run, so Back and Forward are counted from the client `init` hook. Navigation hooks ignore shallow navigations. Also: `goto` options and `data-sveltekit-reset` replace the removed `noScroll`/`keepFocus` options and attributes; same-origin redirects that are not app routes load as full pages because `goto` now rejects them; route IDs follow SvelteKit 3's `RouteId`; the client `handleError` hook uses the new `kind` input; and the organization query finishes after its observer unmounts, like other cacheable reads, now that render errors show the error page. Storybook 10 gets the payload define and public environment mock that Storybook 11 adds for SvelteKit 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d5e0670 to
1dd4630
Compare
|
/preview |
1dd4630 to
adeea59
Compare
SvelteKit 3 no longer generates `$lib` and deprecates `config.alias`. Declare `#comp`, `#features`, `#generated`, `#lib`, and `#shared` as `package.json` subpath imports, which Vite and TypeScript resolve natively, and drop the `alias` option. Each specifier names the file on disk: `.ts` and `.svelte.ts` for modules, `/index.ts` for barrels, and `.svelte` for components, which `allowImportingTsExtensions` from `$app/tsconfig` permits. The rewrite resolved all 2,285 specifiers to files on disk, and the few relative `.js` specifiers now name their `.ts` files too; ESLint regrouped the imports. `components.json` and the frontend guidance use the new aliases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SvelteKit 3 renders the full-page error page for the saved view's render-time 404, which SvelteKit 2 left uncaught. Replacing the app shell cancels whatever requests it has in flight, so the deletion step asserts the not-found page, and the no-cancelled-requests assertion covers the home view navigation it was written for. This replaces the narrower organization query change, which only covered one of those requests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adeea59 to
8507049
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 85070494ef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Brings in the strict CSP for the Svelte frontend (#2363) and the .NET 10.0.13 and Foundatio 13.0.5 updates (#2663). `svelte.config.js` is gone on this branch, so its new `csp` block moves into the `sveltekit()` options in `vite.config.ts`. That file is type-checked, and SvelteKit's CSP types reject `'*'`, so `connect-src` lists `http:`, `https:`, and `ws:`, which allow the same origins on an HTTP(S) page. The Zod `jitless` setup runs after the `#` imports in `hooks.client.ts`. Kit 3's fallback page keeps the contract `update-config.sh` and the backend rely on: one inline bootstrap that imports `/_app/env.js`, hashed in the CSP meta tag. Running the script on a kit 3 build versions the import and refreshes the hash to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Most of this follows the SvelteKit 3 migration guide. The configuration, environment, matcher, and navigation changes have concrete migration purposes. I found one confirmed regression to fix before merging: [P2] Preserve premium-page state during shallow Back/Forward. In the layout callback, Scope recommendation: list query-parameter support has no application callers at this revision and is independent of the upgrade. Consider splitting it into a separate PR. Validation: 1,039 unit tests, type checking, production build, Storybook build, and 48 old/new matcher comparisons passed locally. Full-app browser checks passed in CI. One unchanged runtime-config test failed locally because the script requires GNU Reproduction and migration audit detailsReviewed commit
|
Brings in the KaTeX font allowance for the frontend CSP and the webhook delivery logging changes (#2628). `svelte.config.js` is gone on this branch, so the `data:` font source moves into the `csp` options in `vite.config.ts`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SvelteKit 3 runs the navigation hooks with `shallow: true` and `type: 'popstate'` when Back or Forward reaches a shallow entry, such as a query parameter update, and SvelteKit 2 ran none. The layout reset the premium page state on those traversals while the page stayed mounted, so the Sessions upgrade notice disappeared, and telemetry recorded another page view. Both now skip shallow navigations that stay on the same route. A Back that crosses into another route's shallow entry still resets the state and records the view. The test fake runs the hooks for these traversals as SvelteKit does, and a browser test covers the Sessions notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SvelteKit 3 migration guide requires Svelte's async mode for an async client `handleError`, and this app leaves it off. The hook now returns at once and submits in the background, so telemetry never delays the error page. The returned `errorId` is set as the submitted event's reference id; before, it was the last session's reference id or an unrelated guid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Blake. Addressed in aed83b7 and 56d8d0b.
Codex's note on the async |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 56d8d0b0b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| void updateShallowHistory({ | ||
| state: withHistoryEntry(historyValue) | ||
| }); |
There was a problem hiding this comment.
Defer ownership until the shallow entry exists
When the user closes the sheet before this asynchronous write completes—especially while updateShallowHistory is queued behind another write or navigation—the component has already set ownsHistoryEntry, so consumeOwnedHistoryEntry() calls history.back() even though no sheet entry has been pushed yet. This can unexpectedly leave the current page, after which the queued write is discarded because its originating page changed. Mark the entry as owned only after the write completes, or handle a close while the push is pending without traversing history.
Useful? React with 👍 / 👎.
Upgrades
@sveltejs/kit2.70.3 → 3.0.1 and@sveltejs/adapter-static3 → 4, following the official migration guide and thesv migrate sveltekit-3conventions, and adds list query parameters. The first three commits each build and pass the unit tests on their own: query parameters (still on kit 2), the kit 3 upgrade, and a mechanical rewrite of$aliases to#subpath imports. Merges frommainand review fixes follow. Unlikesv migrate, which writes.js, each specifier names the file on disk (.ts,.svelte.ts,/index.ts,.svelte), whichallowImportingTsExtensionsfrom$app/tsconfigpermits.Behavior changes:
error(404)intended. Under kit 2 that render-time error was uncaught and the page rendered nothing. Replacing the app shell cancels its in-flight requests, so the saved-view deletion test asserts the 404 page instead of no cancelled requests.data-sveltekit-noscroll;data-sveltekit-reset={false}is its replacement.Validation:
npm run validate, 1,048 unit tests, production build, Storybook build, and the hosted browser shards; locally, all 119 browser tests against the Aspire app before the merge frommain. Compared against a kit 2 build ofmainon the same API, both with scripted journeys and by running on kit 2 the four browser tests that first failed on kit 3 (all four now pass on kit 3).build/update-config.shfrommainversions theenv.jsimport and refreshes the bootstrap's CSP hash on the kit 3 build, and the preview loads under the strict CSP with no violations.SvelteKit 3 migration notes
sveltekit()invite.config.ts;tsconfig.jsonextends$app/tsconfig; param matchers are insrc/params.tswithdefineParams;$app/environment→$app/env.src/env.tsdeclares the public variables as dynamic, so_app/env.jsis still loaded at runtime and the container entrypoint can rewrite it. Values stay plain strings because the browser does not re-validate them. The localStorage overrides moved to#shared/environment.tsbecause$app/env/publicexports immutable bindings.goto(url, { shallow: true })throughupdateShallowHistory. In kit 3 a shallowgotois asynchronous and aborts any navigation in progress, so writes are queued until navigations finish, derived when they run, and persist page state across reloads. Query parameters, detail sheets, and saved views read their markers frompage.state; kit 2'ssveltekit:statesandsveltekit:historyhistory keys no longer exist.popstatelistener, and browsers flush effects between listeners, so Back and Forward are counted from the clientinithook, before the router starts.gotoand for Back or Forward to a shallow entry (type: 'popstate',shallow: true); kit 2 ran neither. The canonical-URL guard, detail sheet, saved views, and query parameters skip shallowgotos and handle traversals themselves. The premium reset and telemetry page views skip any shallow navigation that stays on the same route, so a Back into another route's entry still counts as a page change.gotonow rejects URLs that are not app routes, so post-login and status-page redirects usegotoRedirect, which checks$app/pathsmatchand otherwise loads the page in full.handleErrortakes{ kind, error, event }. Kit 3 keeps the oldstatus/messageonly in development, so production would have reported every error without a status. The guide requires Svelte's async mode for an async hook, and the app keeps it off (as onmain), so the hook returns at once, submits in the background, and returns anerrorIdthat is the submitted event's reference id.sveltekit()options.connect-srclistshttp:,https:, andws:because kit's CSP types reject'*'; on an HTTP(S) page they allow the same origins.RouteIdno longer includes layout-only routes: home links useresolve('/(app)')and base-path checks useresolve('')..storybook/main.tsbackports Storybook 11's payload define and mocks$app/env/public; remove both when upgrading to Storybook 11.runeddeclares kit ^2 as a peer, so it gets an override (the app does not importruned/kit). Thecookieoverride is gone because kit 3 shipscookie@2.devalueis a dev dependency for an e2e helper that reads kit 3's serialized page state.Query parameters
'string[]','number[]','<a,b>[]') use repeated keys, drop invalid and duplicate items, and are frozen. An emptied list with a non-empty default writeskey=so a reload keeps it empty.page.urlpremium gate did not reproduce: the API's 426 response shows the notice either way. Saved views keeppage.url, which means "the URL that was navigated to" there.Follow-ups
src/routes/(app)/+error.sveltewould keep the app shell (sidebar and queries) for errors inside the app. It needs an in-shell version of the error page design.system/actionshand-rolls itsqparameter instead of usingcreateQueryParameters.#aliases but writes.jsspecifiers;AGENTS.mdsays to rename them to the.tsfiles after adding a component.🤖 Generated with Claude Code