Repository navigation
fix: serve pages in SPA mode when the route also has an API handler (1.x) - #2355
Merged
Merged
Conversation
`matchAPIRoute` only counted a route as a page when it had a page component. SPA builds leave page components out of the server routes, so a route file exporting both a page and `GET` was treated as API-only. When its `GET` returned nothing, the handler stopped there and the request got a 404. A catch-all like `[...404].tsx` with a `GET` turned every page into a 404. Use `route.page` alone. SSR routes with a page always have the component, so nothing changes there. The new spec needs `vinxi/routes`, which vinxi only serves inside an app build, so vitest aliases it to a stub the spec mocks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 44809c0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
brenelz
approved these changes
Oct 14, 2026
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.
The 1.x version of #2354.
Problem
With
ssr: false, a route file that exports both a page and an API handler, such as a[...404].tsxwith aGET, makes every URL it matches return 404 instead of the SPA shell.Cause
matchAPIRouteinrouter/routes.tscounted a route as a page only when it had a page component (route.page === true && route.$component !== undefined). SPA builds leave page components out of the server routes, soisPagewas always false there. When theGETreturnedundefined, the handler hitif (!match.isPage) return;and the request got a 404.Fix
Use
route.pagealone. With SSR, a route with a page always has its component, so SSR doesn't change.The new spec needs
vinxi/routes, which vinxi only serves inside an app build.vitest.config.tsaliases it totest/vinxi-routes.stub.ts, and the spec mocks that. The stub is outsidesrc, so it isn't compiled intodist.Verification
basicfixture withexport const GET = () => undefinedadded to[...404].tsx, production builds://about/nopessr: false, beforessr: false, afterrouter/routes.spec.ts. The SPA case fails without the fix.packages/start: 98 tests, typecheck and build pass.apps/tests: the unit test passes. Cypress: 18 of 19 pass.server-function.cy.ts› "should reject the promise when the response is a 5xx without an X-Error header". It fails the same way on clean1.x.Not part of this PR: with SSR,
/nopeon that fixture returns 200 instead of 404, and nitro logsunhandledRejection: TypeError: Cannot read properties of undefined (reading 'file'). Clean1.xdoes the same.🤖 Generated with Claude Code