-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix: not all pages are pre-rendered #5475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds automatic static-route discovery via a new generator plugin and global, extends prerender config with autoStaticPathsDiscovery, maxRedirects, and failOnError, enhances prerender engine to follow internal redirects and track prerendered pages, exposes inferFullPath, and updates docs, e2e tests, and scripts for a prerender mode. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Generator as prerenderRoutesPlugin
participant Global as globalThis
participant Core as prerender engine
participant App as Local SSR server
participant FS as File System
Generator->>Generator: compute prerenderable paths (non-dynamic, has component)
Generator->>Global: set TSS_PRERENDABLE_PATHS
Core->>Core: init pages ("/" if none)
alt autoStaticPathsDiscovery = true
Core->>Global: read TSS_PRERENDABLE_PATHS
Core->>Core: merge into pages set (dedupe)
end
loop for each page
Core->>App: localFetch(page, maxRedirects)
alt internal 3xx (<= maxRedirects)
App-->>Core: 3xx Location: /target
Core->>App: follow redirect
App-->>Core: 200 OK
else external 3xx or redirects exhausted
Core-->>Core: warn and skip
end
Core->>FS: write HTML
Core->>Core: mark page prerendered
end
Core-->>Developer: return prerendered paths
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
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 |
|
Command | Status | Duration | Result |
---|---|---|---|
nx affected --targets=test:eslint,test:unit,tes... |
❌ Failed | 27m 36s | View ↗ |
nx run-many --target=build --exclude=examples/*... |
✅ Succeeded | 14s | View ↗ |
☁️ Nx Cloud last updated this comment at 2025-10-18 20:57:41
UTC
More templates
@tanstack/arktype-adapter
@tanstack/directive-functions-plugin
@tanstack/eslint-plugin-router
@tanstack/history
@tanstack/nitro-v2-vite-plugin
@tanstack/react-router
@tanstack/react-router-devtools
@tanstack/react-router-ssr-query
@tanstack/react-start
@tanstack/react-start-client
@tanstack/react-start-server
@tanstack/router-cli
@tanstack/router-core
@tanstack/router-devtools
@tanstack/router-devtools-core
@tanstack/router-generator
@tanstack/router-plugin
@tanstack/router-ssr-query-core
@tanstack/router-utils
@tanstack/router-vite-plugin
@tanstack/server-functions-plugin
@tanstack/solid-router
@tanstack/solid-router-devtools
@tanstack/solid-start
@tanstack/solid-start-client
@tanstack/solid-start-server
@tanstack/start-client-core
@tanstack/start-plugin-core
@tanstack/start-server-core
@tanstack/start-static-server-functions
@tanstack/start-storage-context
@tanstack/valibot-adapter
@tanstack/virtual-file-routes
@tanstack/zod-adapter
commit: |
7da5b58
to
90aeec3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/start-plugin-core/src/prerender.ts (1)
251-259
: Retry logic is blocked by theseen
set — retries won’t requeueAfter a failure, calling addCrawlPageTask(page) is a no-op because
seen
already contains the path. Remove it fromseen
(or requeue directly) before retrying.await new Promise((resolve) => setTimeout(resolve, prerenderOptions.retryDelay), ) retriesByPath.set(page.path, retries + 1) - addCrawlPageTask(page) + // Allow requeue on retry + seen.delete(page.path) + addCrawlPageTask(page)Alternatively, re-add the task directly to
queue
without relying onseen
.
🧹 Nitpick comments (19)
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx (1)
1-9
: LGTM! Clean index route implementation.The code correctly implements an index route for
/posts/
using TanStack Router conventions. The component is appropriately simple for e2e testing with adata-testid
attribute for test selection.Optional refinement: Consider adding an explicit return type annotation to
PostsIndexComponent
for stricter type safety:-function PostsIndexComponent() { +function PostsIndexComponent(): JSX.Element { return <div data-testid="PostsIndexComponent">Select a post.</div> }This is a minor enhancement as TypeScript already infers the return type correctly.
e2e/react-start/basic-prerendering/.gitignore (1)
2-3
: Include pnpm lockfile ignore for consistencyWe’re ignoring
package-lock.json
andyarn.lock
, but notpnpm-lock.yaml
. If these fixtures remain package-manager agnostic, please addpnpm-lock.yaml
to avoid committing that lockfile accidentally.e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx (1)
11-13
: Consider removing the wrapper component.
PostDeepErrorComponent
is a simple pass-through wrapper that doesn't add any value. You can directly useErrorComponent
in the route definition instead.Apply this diff to simplify the error handling:
-export const Route = createFileRoute('/posts_/$postId/deep')({ - loader: async ({ params: { postId } }) => fetchPost({ data: postId }), - errorComponent: PostDeepErrorComponent, - component: PostDeepComponent, -}) - -function PostDeepErrorComponent({ error }: ErrorComponentProps) { - return <ErrorComponent error={error} /> -} +export const Route = createFileRoute('/posts_/$postId/deep')({ + loader: async ({ params: { postId } }) => fetchPost({ data: postId }), + errorComponent: ErrorComponent, + component: PostDeepComponent, +})Remove the unused import if no longer needed:
-import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' -import type { ErrorComponentProps } from '@tanstack/react-router' +import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router'e2e/react-start/basic-prerendering/src/utils/seo.ts (2)
1-11
: Add explicit return type annotation for better type safety.The function lacks an explicit return type, which reduces type safety and makes the API less clear to consumers.
Apply this diff to add an explicit return type:
+type MetaTag = + | { title: string } + | { name: string; content: string | undefined } + export const seo = ({ title, description, keywords, image, }: { title: string description?: string image?: string keywords?: string -}) => { +}): MetaTag[] => {Note: If you apply the filter suggestion from the previous comment, adjust the type to remove
| undefined
from content:type MetaTag = | { title: string } | { name: string; content: string }
18-19
: Hardcoded Twitter handles may need configuration.The Twitter creator and site handles are hardcoded as
@tannerlinsley
. While this might be acceptable for an e2e test scenario, consider whether these should be:
- Configurable parameters if this utility might be reused
- Documented as intentionally hardcoded for test purposes
If configurability is needed, consider adding these as optional parameters with defaults:
export const seo = ({ title, description, keywords, image, + twitterCreator = '@tannerlinsley', + twitterSite = '@tannerlinsley', }: { title: string description?: string image?: string keywords?: string + twitterCreator?: string + twitterSite?: string }) => { const tags = [ { title }, { name: 'description', content: description }, { name: 'keywords', content: keywords }, { name: 'twitter:title', content: title }, { name: 'twitter:description', content: description }, - { name: 'twitter:creator', content: '@tannerlinsley' }, - { name: 'twitter:site', content: '@tannerlinsley' }, + { name: 'twitter:creator', content: twitterCreator }, + { name: 'twitter:site', content: twitterSite }, { name: 'og:type', content: 'website' }, { name: 'og:title', content: title }, { name: 'og:description', content: description },e2e/react-start/basic-prerendering/src/routes/stream.tsx (1)
49-61
: Consider using idiomatic JSX children syntax.While the current
children
prop approach works withAwait
, the more idiomatic React pattern places children between JSX tags.Apply this diff for more idiomatic syntax:
- <Await - promise={promise} - children={(promiseData) => ( + <Await promise={promise}> + {(promiseData) => ( <div className="p-2" data-testid="promise-data"> {promiseData} <div data-testid="stream-data"> {streamData.map((d) => ( <div key={d}>{d}</div> ))} </div> </div> - )} - /> + )} + </Await>packages/start-plugin-core/src/schema.ts (1)
189-190
: ConstrainredirectCount
to non-negative integers.This count represents a discrete redirect limit; allowing floats or negatives introduces ambiguous behavior downstream. Please tighten the schema with
.int().min(0)
(or.nonnegative()
) so only sensible values pass validation.- redirectCount: z.number().optional(), + redirectCount: z.number().int().min(0).optional(),e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx (1)
3-8
: Simplify type assertion.The explicit
as string
type assertion on line 6 is unnecessary since'world'
is already a string literal.Apply this diff to remove the redundant type assertion:
- return { hello: 'world' as string } + return { hello: 'world' }e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx (1)
8-15
: Clarify fallback behavior for unknown target values.The switch statement lacks a default case, which means if
target
is neither'internal'
nor'external'
, the loader completes without redirecting and the component renders. While this may be intentional for testing purposes, consider adding a comment to clarify this fallback behavior or explicitly handle unexpected values.Consider adding either a comment or a default case:
loader: ({ params: { target }, deps: { externalHost, reloadDocument } }) => { switch (target) { case 'internal': throw redirect({ to: '/posts', reloadDocument }) case 'external': throw redirect({ href: externalHost }) + // Intentionally allows other target values to render the component } },
Or with explicit handling:
loader: ({ params: { target }, deps: { externalHost, reloadDocument } }) => { switch (target) { case 'internal': throw redirect({ to: '/posts', reloadDocument }) case 'external': throw redirect({ href: externalHost }) + default: + // Allow rendering component for testing fallback behavior + break } },e2e/react-start/basic-prerendering/src/routes/scripts.tsx (1)
5-19
: Consider filtering undefined scripts for clarity.The conditional script inclusion works correctly, but the scripts array will contain
undefined
in production. While frameworks typically handle this, it's cleaner to filter out undefined values explicitly.Apply this diff for a cleaner implementation:
export const Route = createFileRoute('/scripts')({ head: () => ({ - scripts: [ - { - src: 'script.js', - }, - isProd - ? undefined - : { - src: 'script2.js', - }, - ], + scripts: [ + { + src: 'script.js', + }, + ...(!isProd ? [{ src: 'script2.js' }] : []), + ], }), component: ScriptsComponent, })e2e/react-start/basic-prerendering/src/routes/deferred.tsx (1)
40-55
: Consider using JSX children instead of the children prop.Static analysis tools flag the use of the
children
prop withAwait
components. While this works, the canonical React pattern is to use JSX children. Verify whetherAwait
supports JSX children syntax.If
Await
supports JSX children, apply this diff:<Suspense fallback={<div>Loading person...</div>}> <Await promise={deferredPerson} - children={(data) => ( + > + {(data) => ( <div data-testid="deferred-person"> {data.name} - {data.randomNumber} </div> - )} + )} /> </Suspense> <Suspense fallback={<div>Loading stuff...</div>}> <Await promise={deferredStuff} - children={(data) => <h3 data-testid="deferred-stuff">{data}</h3>} + > + {(data) => <h3 data-testid="deferred-stuff">{data}</h3>} /> </Suspense>e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
5-9
: Consider aligning PostType.id with upstream API (number) or coerce to stringJSONPlaceholder returns numeric ids. Either:
- Change id to number, or
- Explicitly coerce to string when returning to avoid downstream surprises.
-export type PostType = { - id: string +export type PostType = { + id: number title: string body: string }Or map:
return { ...post, id: String(post.id) }
.packages/start-plugin-core/src/prerender.ts (2)
92-105
: Redirect handling: parse Location and allow https/ports; avoid fragile string replaceCurrent checks only handle
http://localhost
and naive replace. Parse the URL to support https and ports; resolve relative paths cleanly.- if ( + if ( response.status >= 300 && response.status < 400 && response.headers.get('location') && maxRedirects > 0 ) { - const location = response.headers.get('location')! - if (location.startsWith('http://localhost') || location.startsWith('/')) { - const newUrl = location.replace('http://localhost', '') - return localFetch(newUrl, options, maxRedirects - 1) - } else { - logger.warn(`Skipping redirect to external location: ${location}`) - } + const location = response.headers.get('location')! + try { + const target = new URL(location, url) // resolves relative to current + if (target.hostname === 'localhost') { + const newPath = `${target.pathname}${target.search}${target.hash}` + return localFetch(newPath, options, maxRedirects - 1) + } + logger.warn(`Skipping redirect to external location: ${target.href}`) + } catch { + logger.warn(`Invalid redirect location: ${location}`) + } }
146-146
: Reduce log noise when listing pagesLogging the entire pages array can get verbose. Consider logging count and sample instead.
- logger.info(startConfig.pages) + logger.info(`Initial pages to crawl: ${startConfig.pages.length}`)e2e/react-start/basic-prerendering/stop-dummy-server.mjs (1)
6-8
: Consider adding error handling.The script lacks error handling around
e2eStopDummyServer
. If the stop operation fails, the error will be unhandled and may not surface clearly in CI logs.Consider wrapping the call in a try-catch block:
console.log('Stopping dummy server...') -await e2eStopDummyServer(packageJson.name) -console.log('Dummy server stopped successfully!') +try { + await e2eStopDummyServer(packageJson.name) + console.log('Dummy server stopped successfully!') +} catch (error) { + console.error('Failed to stop dummy server:', error) + process.exit(1) +}e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
2-2
: Consider using named import for zod.While this works, the zod documentation recommends using a named import rather than the default export for better tree-shaking and consistency.
-import z from 'zod' +import { z } from 'zod'e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
3-3
: Improve type safety for children prop.The
children
prop is typed asany
, which bypasses TypeScript's type checking.Use
React.ReactNode
for better type safety:-export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: React.ReactNode }) {e2e/react-start/basic-prerendering/vite.config.ts (1)
17-24
: Consider exact path matching for the prerender filter.The current filter uses
includes()
which performs substring matching. This could potentially exclude unintended routes if a route path contains any of the excluded strings as a substring (e.g.,/my-redirect-page
would be excluded because it contains/redirect
).If this behavior is intentional for this test suite, the current implementation is fine. Otherwise, consider exact path matching:
filter: (page) => ![ '/this-route-does-not-exist', '/redirect', '/i-do-not-exist', '/not-found/via-beforeLoad', '/not-found/via-loader', - ].some((p) => page.path.includes(p)), + ].includes(page.path),e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx (1)
2-2
: Use named import for z
Replaceimport z from 'zod’
withimport { z } from 'zod’
to match the prevalent pattern across the codebase.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
e2e/react-start/basic-prerendering/public/android-chrome-192x192.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/android-chrome-512x512.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/apple-touch-icon.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon-16x16.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon-32x32.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon.ico
is excluded by!**/*.ico
e2e/react-start/basic-prerendering/public/favicon.png
is excluded by!**/*.png
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
docs/start/framework/react/guide/static-prerendering.md
(2 hunks)e2e/react-start/basic-prerendering/.gitignore
(1 hunks)e2e/react-start/basic-prerendering/.prettierignore
(1 hunks)e2e/react-start/basic-prerendering/package.json
(1 hunks)e2e/react-start/basic-prerendering/playwright.config.ts
(1 hunks)e2e/react-start/basic-prerendering/postcss.config.mjs
(1 hunks)e2e/react-start/basic-prerendering/public/script.js
(1 hunks)e2e/react-start/basic-prerendering/public/script2.js
(1 hunks)e2e/react-start/basic-prerendering/public/site.webmanifest
(1 hunks)e2e/react-start/basic-prerendering/server.js
(1 hunks)e2e/react-start/basic-prerendering/src/client.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/NotFound.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routeTree.gen.ts
(1 hunks)e2e/react-start/basic-prerendering/src/router.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/__root.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/api.users.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routes/deferred.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/links.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/scripts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/stream.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/server.ts
(1 hunks)e2e/react-start/basic-prerendering/src/styles/app.css
(1 hunks)e2e/react-start/basic-prerendering/src/utils/posts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/utils/seo.ts
(1 hunks)e2e/react-start/basic-prerendering/src/utils/users.tsx
(1 hunks)e2e/react-start/basic-prerendering/start-dummy-server.mjs
(1 hunks)e2e/react-start/basic-prerendering/stop-dummy-server.mjs
(1 hunks)e2e/react-start/basic-prerendering/tailwind.config.mjs
(1 hunks)e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
(1 hunks)e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
(1 hunks)e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
(1 hunks)e2e/react-start/basic-prerendering/tsconfig.json
(1 hunks)e2e/react-start/basic-prerendering/vite.config.ts
(1 hunks)packages/start-plugin-core/src/prerender.ts
(7 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/plugin.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/basic-prerendering/tsconfig.json
e2e/react-start/basic-prerendering/public/script.js
e2e/react-start/basic-prerendering/src/utils/users.tsx
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/public/site.webmanifest
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
e2e/react-start/basic-prerendering/src/components/NotFound.tsx
e2e/react-start/basic-prerendering/src/styles/app.css
e2e/react-start/basic-prerendering/public/script2.js
e2e/react-start/basic-prerendering/src/utils/seo.ts
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
e2e/react-start/basic-prerendering/tailwind.config.mjs
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/playwright.config.ts
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/start-dummy-server.mjs
e2e/react-start/basic-prerendering/src/router.tsx
e2e/react-start/basic-prerendering/vite.config.ts
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
e2e/react-start/basic-prerendering/postcss.config.mjs
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/client.tsx
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
e2e/react-start/basic-prerendering/stop-dummy-server.mjs
e2e/react-start/basic-prerendering/src/utils/posts.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
e2e/react-start/basic-prerendering/src/server.ts
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
e2e/react-start/basic-prerendering/package.json
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
e2e/react-start/basic-prerendering/server.js
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/index.tsx
e2e/react-start/basic-prerendering/src/routeTree.gen.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/basic-prerendering/src/utils/users.tsx
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
packages/start-plugin-core/src/start-router-plugin/plugin.ts
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
e2e/react-start/basic-prerendering/src/components/NotFound.tsx
e2e/react-start/basic-prerendering/src/utils/seo.ts
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
packages/start-plugin-core/src/schema.ts
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/playwright.config.ts
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/src/router.tsx
e2e/react-start/basic-prerendering/vite.config.ts
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/client.tsx
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
e2e/react-start/basic-prerendering/src/utils/posts.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
e2e/react-start/basic-prerendering/src/server.ts
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
packages/start-plugin-core/src/prerender.ts
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/index.tsx
e2e/react-start/basic-prerendering/src/routeTree.gen.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/index.tsx
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/start-router-plugin/plugin.ts
packages/start-plugin-core/src/schema.ts
packages/start-plugin-core/src/prerender.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
e2e/react-start/basic-prerendering/package.json
🧠 Learnings (1)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase
Applied to files:
e2e/react-start/basic-prerendering/tsconfig.json
🧬 Code graph analysis (51)
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx (2)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx (1)
Route
(18-29)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx (3)
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
Route
(12-32)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx (1)
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts (1)
throwRedirect
(4-23)
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx (1)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/components/NotFound.tsx (5)
e2e/react-start/basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)e2e/react-start/server-routes/src/components/NotFound.tsx (1)
NotFound
(3-25)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)examples/react/start-basic-cloudflare/src/routes/__root.tsx (1)
NotFound
(61-61)e2e/react-start/basic-cloudflare/src/routes/__root.tsx (1)
NotFound
(55-55)
e2e/react-start/basic-prerendering/src/utils/seo.ts (1)
scripts/llms-generate.mjs (1)
title
(96-96)
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx (1)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPost
(17-33)
e2e/react-start/basic-prerendering/src/routes/posts.tsx (1)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPosts
(35-42)
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts (8)
e2e/react-router/basic-file-based-code-splitting/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/solid-router/basic-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/basic-virtual-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/basic-virtual-named-export-config-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/rspack-basic-virtual-named-export-config-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/basic/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/basic-esbuild-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/react-router/basic-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)
e2e/react-start/basic-prerendering/src/routes/users.tsx (3)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
Route
(13-28)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)examples/solid/start-basic/src/routes/users.tsx (1)
UsersComponent
(18-48)
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx (1)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/src/routes/stream.tsx (1)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx (1)
Route
(18-29)
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (4)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/scripts.tsx (2)
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx (1)
Route
(3-18)packages/router-core/src/ssr/tsrScript.ts (1)
p
(7-9)
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/playwright.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx (1)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/start-dummy-server.mjs (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/router.tsx (2)
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx (2)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPost
(17-33)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (4)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (3)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)e2e/react-start/basic-prerendering/src/components/throwRedirect.ts (1)
throwRedirect
(4-23)
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts (2)
e2e/solid-router/basic-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/react-router/generator-cli-only/tests/setup/global.teardown.ts (1)
teardown
(4-6)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx (1)
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx (1)
RedirectOnClick
(10-26)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx (3)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (3)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx (1)
packages/router-core/src/ssr/tsrScript.ts (1)
p
(7-9)
e2e/react-start/basic-prerendering/stop-dummy-server.mjs (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
e2e/react-router/js-only-file-based/src/posts.js (1)
queryURL
(5-5)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/users.index.tsx (3)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/index.tsx (1)
Route
(4-6)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (3)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx (3)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)
e2e/react-start/basic-prerendering/src/routes/links.tsx (3)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/index.tsx (1)
Route
(4-6)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx (1)
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts (1)
throwRedirect
(4-23)
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (2)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
Route
(13-28)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)
packages/start-plugin-core/src/prerender.ts (1)
packages/router-generator/src/generator.ts (1)
getCrawlingResult
(1183-1186)
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (2)
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
Route
(12-32)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx (3)
e2e/react-start/server-routes/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)examples/react/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)packages/react-router/src/CatchBoundary.tsx (2)
CatchBoundaryImpl
(31-78)CatchBoundary
(5-29)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx (1)
e2e/react-start/basic/src/routes/deferred.tsx (1)
deferredStuff
(19-27)
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-router/basic-file-based/src/routes/search-params/default.tsx (1)
search
(18-27)
e2e/react-start/basic-prerendering/src/routes/index.tsx (1)
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx (1)
CustomMessage
(3-10)
e2e/react-start/basic-prerendering/src/routeTree.gen.ts (2)
e2e/react-router/js-only-file-based/src/routeTree.gen.js (3)
IndexRoute
(30-34)PostsIndexRoute
(35-39)PostsPostIdRoute
(40-44)e2e/react-start/basic-prerendering/src/router.tsx (1)
getRouter
(6-16)
🪛 Biome (2.1.2)
e2e/react-start/basic-prerendering/src/routes/stream.tsx
[error] 51-51: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
[error] 43-43: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 53-53: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~12-~12: There might be a mistake here.
Context: ... parameters (e.g., /about
, /contact
) - Routes with search parameters that have ...
(QB_NEW_EN)
[grammar] ~13-~13: There might be a mistake here.
Context: ...arch parameters that have default values - Routes that don't require dynamic data f...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Nitpick comments (31)
e2e/react-start/basic-prerendering/.prettierignore (1)
1-4
: Looks good. Optional: ignore Playwright artifacts too.Current ignores are sensible for build and generated files. Consider also ignoring Playwright outputs to avoid formatting large reports.
**/build **/public pnpm-lock.yaml routeTree.gen.ts +playwright-report +test-resultse2e/react-start/basic-prerendering/src/server.ts (1)
7-11
: Add explicit return type for improved type safety.The fetch method lacks an explicit return type annotation. To align with the strict TypeScript coding guidelines, add the return type.
As per coding guidelines.
Apply this diff to add the return type:
export default { - fetch(request: Request) { + fetch(request: Request): ReturnType<typeof handler.fetch> { return handler.fetch(request) }, }e2e/react-start/basic-prerendering/.gitignore (3)
1-4
: Include pnpm lockfile (repo uses pnpm).To keep lockfile policy consistent, ignore pnpm-lock.yaml alongside npm/yarn locks (or decide to commit locks). Given pnpm usage in this PR, add:
node_modules package-lock.json yarn.lock +pnpm-lock.yaml
6-8
: Broaden env ignores to prevent secret leaks.Ignore all dotenv variants and keep an allowlisted example file.
.DS_Store .cache -.env +.env +.env.* +!.env.example .vercel .output @@ # Sentry Config File .env.sentry-build-pluginAlso applies to: 16-16
11-20
: Add common logs/caches and coverage artifacts.These are frequently generated during builds/tests and can clutter diffs.
/build/ /api/ /server/build /public/build # Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ /blob-report/ /playwright/.cache/ +coverage/ +.nyc_output/ +*.tsbuildinfo +npm-debug.log* +yarn-error.log* +pnpm-debug.log* +node_modules/.vite/ +.vite/ +.vscode/ +.idea/ +Thumbs.dbe2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
7-11
: Preferconst
and validateVITE_EXTERNAL_PORT
in test mode.The
queryURL
variable is declared withlet
but could beconst
with a conditional expression. Additionally,VITE_EXTERNAL_PORT
is used without validation, which could result in an invalid URL if the environment variable is undefined or malformed in test mode.Apply this diff to use
const
and add validation:-let queryURL = 'https://jsonplaceholder.typicode.com' - -if (import.meta.env.VITE_NODE_ENV === 'test') { - queryURL = `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT}` -} +const queryURL = + import.meta.env.VITE_NODE_ENV === 'test' + ? `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT || '3000'}` + : 'https://jsonplaceholder.typicode.com'packages/start-plugin-core/src/schema.ts (1)
189-189
: Consider adding a minimum constraint toredirectCount
.The
redirectCount
field accepts any number, including negative values. To prevent unexpected behavior, consider adding a minimum constraint.Apply this diff to add a minimum constraint:
- redirectCount: z.number().optional(), + redirectCount: z.number().min(0).optional(),e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
1-9
: Consider renaming to.ts
extension.The file contains only type definitions and constants, with no JSX. Renaming from
.tsx
to.ts
would align with the actual content.e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx (1)
3-8
: Consider removing the redundant type assertion.The type assertion
'world' as string
is unnecessary since'world'
is already inferred as a string literal type.Apply this diff:
- return { hello: 'world' as string } + return { hello: 'world' }e2e/react-start/basic-prerendering/tsconfig.json (1)
3-21
: Add Vite types for import.meta.envYou reference import.meta.env in TS (e.g., API routes). Add vite/client to types so TS knows ImportMetaEnv.
Apply this diff:
"compilerOptions": { "strict": true, "esModuleInterop": true, "jsx": "react-jsx", "module": "ESNext", "moduleResolution": "Bundler", "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["vite/client"], "isolatedModules": true, "resolveJsonModule": true, "skipLibCheck": true, "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, "noEmit": true }
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
15-28
: Harden the handler (param validation + timeout)Optional but useful for tests and robustness:
- Validate params.id is a positive integer; return 400 on invalid.
- Add a request timeout to avoid hanging on slow upstreams.
Example diff:
- GET: async ({ request, params }) => { + GET: async ({ request, params }) => { console.info(`Fetching users by id=${params.id}... @`, request.url) try { - const res = await axios.get<User>(`${queryURL}/users/` + params.id) + const idNum = Number(params.id) + if (!Number.isInteger(idNum) || idNum <= 0) { + return json({ error: 'Invalid id' }, { status: 400 }) + } + const res = await axios.get<User>(`${queryURL}/users/${idNum}`, { + timeout: 5000, + })e2e/react-start/basic-prerendering/src/routes/deferred.tsx (1)
40-55
: Refactor to use JSX children pattern instead of children prop.The
Await
components use thechildren
prop, which is not the canonical React pattern and is flagged by the linter.Apply this diff to use JSX children:
<Suspense fallback={<div>Loading person...</div>}> <Await promise={deferredPerson} - children={(data) => ( + > + {(data) => ( <div data-testid="deferred-person"> {data.name} - {data.randomNumber} </div> - )} + )} - /> + </Await> </Suspense> <Suspense fallback={<div>Loading stuff...</div>}> <Await promise={deferredStuff} - children={(data) => <h3 data-testid="deferred-stuff">{data}</h3>} + > + {(data) => <h3 data-testid="deferred-stuff">{data}</h3>} - /> + </Await> </Suspense>e2e/react-start/basic-prerendering/src/routes/stream.tsx (2)
30-45
: Addstream
to useEffect dependency array.The
stream
object is referenced inside the effect but not included in the dependency array. While the stream reference is likely stable from the loader, explicitly including it follows React Hook best practices and avoids potential stale closure issues.Apply this diff:
fetchStream() - }, []) + }, [stream])
47-63
: Refactor to use JSX children pattern instead of children prop.The
Await
component uses thechildren
prop, which is not the canonical React pattern and is flagged by the linter.Apply this diff:
<Await promise={promise} - children={(promiseData) => ( + > + {(promiseData) => ( <div className="p-2" data-testid="promise-data"> {promiseData} <div data-testid="stream-data"> {streamData.map((d) => ( <div key={d}>{d}</div> ))} </div> </div> - )} + )} - /> + </Await>e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
3-3
: Replaceany
type withReact.ReactNode
for strict type safety.The
children
prop is typed asany
, which bypasses TypeScript's type checking. UseReact.ReactNode
for proper type safety.As per coding guidelines
Apply this diff:
-export function NotFound({ children }: { children?: any }) { +export function NotFound({ children }: { children?: React.ReactNode }) {e2e/react-start/basic-prerendering/tests/setup/global.setup.ts (1)
2-2
: Consider usingimport attributes
syntax.The
with { type: 'json' }
syntax is from an older stage-3 proposal. Node.js v20.10+ and TypeScript 5.3+ support theimport attributes
form, which is now the standardized syntax.Apply this diff if your environment supports it:
-import packageJson from '../../package.json' with { type: 'json' } +import packageJson from '../../package.json' with { type: 'json' }Note: If the project is targeting older Node versions, the current syntax is acceptable.
e2e/react-start/basic-prerendering/src/router.tsx (1)
6-16
: Consider consistent component assignment.The router configuration is correct. For consistency with
defaultErrorComponent
, you could simplifydefaultNotFoundComponent
.Apply this diff for consistency:
export function getRouter() { const router = createRouter({ routeTree, scrollRestoration: true, defaultPreload: 'intent', defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => <NotFound />, + defaultNotFoundComponent: NotFound, }) return router }Note: Both forms are valid; this is purely a stylistic suggestion.
e2e/react-start/basic-prerendering/stop-dummy-server.mjs (2)
4-4
: Consider usingimport attributes
syntax.The
with { type: 'json' }
syntax is from an older stage-3 proposal. The standardizedimport attributes
form is now supported in Node.js v20.10+ and TypeScript 5.3+.Apply this diff if targeting modern Node versions:
-import packageJson from './package.json' with { type: 'json' } +import packageJson from './package.json' with { type: 'json' }Note: The current syntax works but may be deprecated in future Node versions.
6-8
: Add error handling for robustness.The script lacks error handling. If
e2eStopDummyServer
fails, users won't see a clear error message, and the exit code may not reflect the failure.Apply this diff to add proper error handling:
console.log('Stopping dummy server...') -await e2eStopDummyServer(packageJson.name) -console.log('Dummy server stopped successfully!') +try { + await e2eStopDummyServer(packageJson.name) + console.log('Dummy server stopped successfully!') +} catch (error) { + console.error('Failed to stop dummy server:', error) + process.exit(1) +}e2e/react-start/basic-prerendering/src/routes/users.tsx (1)
7-14
: Simplify loader for clarityAvoid mixing
await
with.then/.catch
. Usetry/catch
with a singleawait
.- loader: async () => { - return await axios - .get<Array<User>>('/api/users') - .then((r) => r.data) - .catch(() => { - throw new Error('Failed to fetch users') - }) - }, + loader: async () => { + try { + const r = await axios.get<Array<User>>('/api/users') + return r.data + } catch { + throw new Error('Failed to fetch users') + } + },e2e/react-start/basic-prerendering/playwright.config.ts (1)
12-12
: Improve error handling and cross-platform compatibility in the command chain.The
ssrModeCommand
has two concerns:
- No error propagation: If
pnpm build
fails, the subsequent commands still execute. The chain should abort on failure.- Unix-only syntax: The
&&
operator works on Unix/macOS but may behave differently on Windows in some shells.Consider using a dedicated script (e.g.,
scripts/e2e-setup.sh
or.mjs
) that provides explicit error handling and cross-platform compatibility:// scripts/e2e-setup.mjs import { execSync } from 'child_process' const commands = [ 'pnpm test:e2e:dummyServer', 'pnpm build', 'pnpm test:e2e:stopDummyServer', 'pnpm start' ] for (const cmd of commands) { try { execSync(cmd, { stdio: 'inherit' }) } catch (error) { console.error(`Command failed: ${cmd}`) process.exit(1) } }Then update the config:
-const ssrModeCommand = `pnpm test:e2e:dummyServer && pnpm build && pnpm test:e2e:stopDummyServer && pnpm start` +const ssrModeCommand = 'node scripts/e2e-setup.mjs'e2e/react-start/basic-prerendering/package.json (1)
12-14
: Replace Unix-specific commands for cross-platform compatibility.The test scripts use Unix-specific syntax (
&
for backgrounding andrm -rf
) that won't work on Windows without WSL or Git Bash.Consider using cross-platform alternatives:
- For backgrounding processes, use a Node.js script or a tool like
concurrently
- For file deletion, use a cross-platform utility like
rimraf
ordel-cli
Example refactor using Node scripts:
"scripts": { - "test:e2e:dummyServer": "node start-dummy-server.mjs &", + "test:e2e:dummyServer": "node start-dummy-server.mjs", "test:e2e:stopDummyServer": "node stop-dummy-server.mjs", - "test:e2e": "rm -rf port*.txt; pnpm run test:e2e:ssrMode" + "test:e2e": "node -e \"require('fs').readdirSync('.').filter(f=>f.match(/^port.*\\.txt$/)).forEach(f=>require('fs').unlinkSync(f))\" && pnpm run test:e2e:ssrMode" },Or add
rimraf
as a devDependency and use:- "test:e2e": "rm -rf port*.txt; pnpm run test:e2e:ssrMode" + "test:e2e": "rimraf port*.txt && pnpm run test:e2e:ssrMode"e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx (1)
13-17
: Consider makingexternalHost
conditionally required based on the redirect target.The
externalHost
search parameter is optional, but child routes (e.g.,via-beforeLoad.tsx
) require it whentarget
is'external'
. This creates a validation gap where the route can be accessed with invalid combinations.Zod doesn't natively support conditional validation across separate schema fields in this context, but you can add runtime validation in child route
beforeLoad
hooks or document the requirement clearly. Alternatively, split into separate routes:// Option 1: Document the requirement export const Route = createFileRoute('/redirect/$target')({ // ... existing code validateSearch: z.object({ reloadDocument: z.boolean().optional(), preload: z.literal(false).optional(), // externalHost is required when target is 'external' externalHost: z.string().optional(), }),Or implement validation in each child route as suggested for
via-beforeLoad.tsx
.docs/start/framework/react/guide/static-prerendering.md (1)
18-21
: Remove redundant explanation.Line 20 duplicates the automatic discovery explanation already provided in lines 10-16. The Manual Page Configuration section should focus on when and how to manually configure pages.
Consider this revision:
## Manual Page Configuration -TanStack Start can prerender your application to static HTML files, which can then be served to users without having to generate them on the fly. When prerendering is enabled without specifying pages, TanStack Start will automatically discover and prerender all static routes in your application. +You can manually specify which pages to prerender using the `pages` array. This is useful when you need custom output paths or want to override the automatic discovery behavior. To prerender your application, you can add the `prerender` option to your tanstackStart configuration in `vite.config.ts` file:e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx (1)
17-21
: Avoid unhandled promise from useServerFn; explicitly ignore or handle itonClick returns a Promise that isn’t awaited/caught. Use void to signal intentional fire-and-forget (prevents no-floating-promises).
- onClick={() => - execute({ data: { target, reloadDocument, externalHost } }) - } + onClick={() => + void execute({ data: { target, reloadDocument, externalHost } }) + }e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx (1)
6-8
: Optional: improve readability by hoisting paramsSlightly clearer to read and avoids calling the hook inline in JSX.
- redirect test with server functions (target {Route.useParams().target}) + {(() => { + const { target } = Route.useParams() + return <>redirect test with server functions (target {target})</> + })()}e2e/react-start/basic-prerendering/server.js (2)
16-16
: Prefer absolute paths for static assetsAvoid CWD sensitivity by resolving to absolute paths.
- app.use(express.static('./dist/client')) + app.use(express.static(path.resolve('./dist/client')))Repeat the same change for the other static middleware.
Also applies to: 48-48
57-61
: Add startup error handling to avoid unhandled rejectionsIf dynamic import or binding fails, the promise rejects and nothing logs.
-createSpaServer().then(async ({ app }) => - app.listen(port, () => { - console.info(`Client Server: http://localhost:${port}`) - }), -) +createSpaServer() + .then(({ app }) => { + app.listen(port, () => { + console.info(`Client Server: http://localhost:${port}`) + }) + }) + .catch((err) => { + console.error('Failed to start SPA server', err) + process.exitCode = 1 + }) -createStartServer().then(async ({ app }) => - app.listen(startPort, () => { - console.info(`Start Server: http://localhost:${startPort}`) - }), -) +createStartServer() + .then(({ app }) => { + app.listen(startPort, () => { + console.info(`Start Server: http://localhost:${startPort}`) + }) + }) + .catch((err) => { + console.error('Failed to start Start server', err) + process.exitCode = 1 + })Also applies to: 63-67
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
3-15
: Route always notFound — consider removing unused componentSince loader throws notFound unconditionally, the route component won’t render. If not needed for tests, drop the component to reduce dead code; otherwise, add a short comment clarifying the intent.
e2e/react-start/basic-prerendering/src/routes/__root.tsx (2)
95-101
: Add html lang attribute for accessibility/SEORecommend (or appropriate locale).
- return ( - <html> + return ( + <html lang="en">
26-31
: Use standard theme color meta; remove non-standard 'color' on manifest link'color' isn’t a standard attribute for rel="manifest". Prefer a meta tag for theme color.
...seo({ title: 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, }), + { name: 'theme-color', content: '#ffffff' }, ],
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, + { rel: 'manifest', href: '/site.webmanifest' },Also applies to: 51-53
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
e2e/react-start/basic-prerendering/public/android-chrome-192x192.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/android-chrome-512x512.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/apple-touch-icon.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon-16x16.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon-32x32.png
is excluded by!**/*.png
e2e/react-start/basic-prerendering/public/favicon.ico
is excluded by!**/*.ico
e2e/react-start/basic-prerendering/public/favicon.png
is excluded by!**/*.png
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
docs/start/framework/react/guide/static-prerendering.md
(2 hunks)e2e/react-start/basic-prerendering/.gitignore
(1 hunks)e2e/react-start/basic-prerendering/.prettierignore
(1 hunks)e2e/react-start/basic-prerendering/package.json
(1 hunks)e2e/react-start/basic-prerendering/playwright.config.ts
(1 hunks)e2e/react-start/basic-prerendering/postcss.config.mjs
(1 hunks)e2e/react-start/basic-prerendering/public/script.js
(1 hunks)e2e/react-start/basic-prerendering/public/script2.js
(1 hunks)e2e/react-start/basic-prerendering/public/site.webmanifest
(1 hunks)e2e/react-start/basic-prerendering/server.js
(1 hunks)e2e/react-start/basic-prerendering/src/client.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/NotFound.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routeTree.gen.ts
(1 hunks)e2e/react-start/basic-prerendering/src/router.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/__root.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/api.users.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
(1 hunks)e2e/react-start/basic-prerendering/src/routes/deferred.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/links.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/scripts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/stream.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.index.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/users.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/server.ts
(1 hunks)e2e/react-start/basic-prerendering/src/styles/app.css
(1 hunks)e2e/react-start/basic-prerendering/src/utils/posts.tsx
(1 hunks)e2e/react-start/basic-prerendering/src/utils/seo.ts
(1 hunks)e2e/react-start/basic-prerendering/src/utils/users.tsx
(1 hunks)e2e/react-start/basic-prerendering/start-dummy-server.mjs
(1 hunks)e2e/react-start/basic-prerendering/stop-dummy-server.mjs
(1 hunks)e2e/react-start/basic-prerendering/tailwind.config.mjs
(1 hunks)e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
(1 hunks)e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
(1 hunks)e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
(1 hunks)e2e/react-start/basic-prerendering/tsconfig.json
(1 hunks)e2e/react-start/basic-prerendering/vite.config.ts
(1 hunks)packages/start-plugin-core/src/prerender.ts
(8 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/plugin.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
packages/start-plugin-core/src/prerender.ts
e2e/react-start/basic-prerendering/src/client.tsx
e2e/react-start/basic-prerendering/src/server.ts
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
packages/start-plugin-core/src/start-router-plugin/plugin.ts
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
e2e/react-start/basic-prerendering/src/components/NotFound.tsx
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
packages/start-plugin-core/src/schema.ts
e2e/react-start/basic-prerendering/src/utils/users.tsx
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/utils/posts.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/vite.config.ts
e2e/react-start/basic-prerendering/src/utils/seo.ts
e2e/react-start/basic-prerendering/src/routes/index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routeTree.gen.ts
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/router.tsx
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/playwright.config.ts
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/src/routes/index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx
e2e/react-start/basic-prerendering/start-dummy-server.mjs
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx
e2e/react-start/basic-prerendering/src/client.tsx
e2e/react-start/basic-prerendering/src/server.ts
e2e/react-start/basic-prerendering/public/site.webmanifest
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx
e2e/react-start/basic-prerendering/stop-dummy-server.mjs
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx
e2e/react-start/basic-prerendering/package.json
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx
e2e/react-start/basic-prerendering/tailwind.config.mjs
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts
e2e/react-start/basic-prerendering/src/components/NotFound.tsx
e2e/react-start/basic-prerendering/public/script2.js
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx
e2e/react-start/basic-prerendering/src/routes/posts.tsx
e2e/react-start/basic-prerendering/src/utils/users.tsx
e2e/react-start/basic-prerendering/src/styles/app.css
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx
e2e/react-start/basic-prerendering/src/routes/_layout.tsx
e2e/react-start/basic-prerendering/src/utils/posts.tsx
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx
e2e/react-start/basic-prerendering/server.js
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts
e2e/react-start/basic-prerendering/src/routes/__root.tsx
e2e/react-start/basic-prerendering/postcss.config.mjs
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts
e2e/react-start/basic-prerendering/src/routes/stream.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx
e2e/react-start/basic-prerendering/public/script.js
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-loader.tsx
e2e/react-start/basic-prerendering/src/routes/users.index.tsx
e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx
e2e/react-start/basic-prerendering/src/routes/links.tsx
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx
e2e/react-start/basic-prerendering/vite.config.ts
e2e/react-start/basic-prerendering/tsconfig.json
e2e/react-start/basic-prerendering/src/utils/seo.ts
e2e/react-start/basic-prerendering/src/routes/index.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx
e2e/react-start/basic-prerendering/src/routeTree.gen.ts
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx
e2e/react-start/basic-prerendering/src/router.tsx
e2e/react-start/basic-prerendering/src/routes/scripts.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx
e2e/react-start/basic-prerendering/src/routes/redirect/$target.tsx
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
e2e/react-start/basic-prerendering/playwright.config.ts
e2e/react-start/basic-prerendering/src/routes/users.tsx
e2e/react-start/basic-prerendering/src/routes/api.users.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/start-router-plugin/plugin.ts
packages/start-plugin-core/src/schema.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
e2e/react-start/basic-prerendering/package.json
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
🧠 Learnings (2)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase
Applied to files:
e2e/react-start/basic-prerendering/tsconfig.json
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
PR: TanStack/router#5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/react-start/basic-prerendering/src/routeTree.gen.ts
🧬 Code graph analysis (48)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx (1)
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts (1)
throwRedirect
(4-23)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic/src/routes/redirect/$target/index.tsx (1)
preload
(4-75)
e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (3)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/start-dummy-server.mjs (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx (2)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)packages/router-core/src/ssr/tsrScript.ts (1)
p
(7-9)
packages/start-plugin-core/src/prerender.ts (1)
packages/router-generator/src/generator.ts (1)
getCrawlingResult
(1183-1186)
e2e/react-start/basic-prerendering/src/routes/search-params/loader-throws-redirect.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/stop-dummy-server.mjs (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/redirect/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx (1)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/tests/setup/global.setup.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/components/NotFound.tsx (6)
e2e/react-start/basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)e2e/react-start/server-routes/src/components/NotFound.tsx (1)
NotFound
(3-25)examples/react/start-basic-cloudflare/src/components/NotFound.tsx (1)
NotFound
(3-25)examples/react/start-basic-cloudflare/src/routes/__root.tsx (1)
NotFound
(61-61)e2e/react-start/basic-cloudflare/src/routes/__root.tsx (1)
NotFound
(55-55)examples/react/start-basic-cloudflare/src/router.tsx (1)
NotFound
(11-11)
e2e/react-start/basic-prerendering/src/routes/대한민국.tsx (1)
e2e/react-router/basic-file-based/src/routes/대한민국.tsx (1)
RouteComponent
(7-9)
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx (1)
e2e/react-start/basic-prerendering/src/components/throwRedirect.ts (1)
throwRedirect
(4-23)
e2e/react-start/basic-prerendering/src/routes/posts.tsx (1)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPosts
(35-42)
e2e/react-start/basic-prerendering/src/routes/posts.$postId.tsx (2)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPost
(17-33)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx (2)
examples/solid/start-basic/src/routes/deferred.tsx (1)
Deferred
(31-62)e2e/react-start/basic/src/routes/deferred.tsx (1)
deferredStuff
(19-27)
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx (1)
e2e/react-start/server-routes/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (2)
e2e/react-router/basic-esbuild-file-based/src/routes/_layout.tsx (1)
LayoutComponent
(7-16)e2e/react-router/basic-file-based-code-splitting/src/routes/_layout.tsx (1)
LayoutComponent
(7-16)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
e2e/react-router/js-only-file-based/src/posts.js (1)
queryURL
(5-5)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here.tsx (1)
e2e/react-start/basic-prerendering/src/routes/foo/$bar/$qux/_here/index.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/posts_.$postId.deep.tsx (1)
e2e/react-start/basic-prerendering/src/utils/posts.tsx (1)
fetchPost
(17-33)
e2e/react-start/basic-prerendering/tests/setup/global.teardown.ts (2)
e2e/solid-router/basic-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-virtual-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)
e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (3)
e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-loader.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
e2e/react-start/server-routes/src/routes/__root.tsx (1)
RootDocument
(57-82)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-loader.tsx (3)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (3)
e2e/react-router/js-only-file-based/src/posts.js (1)
queryURL
(5-5)e2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
Route
(13-28)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)
e2e/react-start/basic-prerendering/src/routes/stream.tsx (1)
e2e/react-start/basic/src/routes/stream.tsx (1)
Home
(26-64)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/serverFn/via-useServerFn.tsx (1)
e2e/react-start/basic-prerendering/src/components/RedirectOnClick.tsx (1)
RedirectOnClick
(10-26)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (4)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-b.tsx (3)
e2e/react-start/basic-prerendering/src/routes/_layout.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2.tsx (1)
Route
(3-5)e2e/react-start/basic-prerendering/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route
(3-5)
e2e/react-start/basic-prerendering/vite.config.ts (1)
packages/router-core/src/ssr/tsrScript.ts (1)
p
(7-9)
e2e/react-start/basic-prerendering/src/routes/index.tsx (1)
e2e/react-start/basic-prerendering/src/components/CustomMessage.tsx (1)
CustomMessage
(3-10)
e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx (2)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)e2e/react-start/basic-prerendering/src/routes/not-found/index.tsx (1)
Route
(3-31)
e2e/react-start/basic-prerendering/src/routeTree.gen.ts (2)
e2e/react-router/js-only-file-based/src/routeTree.gen.js (4)
IndexRoute
(30-34)PostsIndexRoute
(35-39)PostsPostIdRoute
(40-44)rootRouteChildren
(90-94)e2e/react-start/basic-prerendering/src/router.tsx (1)
getRouter
(6-16)
e2e/react-start/basic-prerendering/src/routes/posts.index.tsx (1)
e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)
e2e/react-start/basic-prerendering/src/router.tsx (2)
e2e/react-start/basic-prerendering/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/src/routes/scripts.tsx (2)
e2e/react-start/basic-prerendering/src/routes/__root.tsx (1)
Route
(16-75)e2e/react-start/basic-prerendering/src/routes/inline-scripts.tsx (1)
Route
(3-18)
e2e/react-start/basic-prerendering/src/routes/search-params/route.tsx (2)
e2e/react-start/basic-prerendering/src/routes/not-found/route.tsx (1)
Route
(4-8)e2e/react-start/basic-prerendering/src/routes/not-found/via-beforeLoad.tsx (1)
Route
(3-15)
e2e/react-start/basic-prerendering/src/routes/search-params/index.tsx (2)
e2e/react-start/basic-prerendering/src/routes/index.tsx (1)
Route
(4-6)e2e/react-start/basic-prerendering/src/routes/links.tsx (1)
Route
(3-47)
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx (4)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
Route
(13-28)e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
Route
(12-32)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)e2e/react-start/basic-prerendering/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/react-start/basic-prerendering/playwright.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/react-start/basic-prerendering/src/routes/users.tsx (3)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (1)
Route
(13-28)e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
Route
(12-32)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)
e2e/react-start/basic-prerendering/src/routes/api.users.ts (2)
e2e/react-start/basic-prerendering/src/routes/api/users.$id.ts (1)
Route
(12-32)e2e/react-start/basic-prerendering/src/utils/users.tsx (1)
User
(1-5)
🪛 Biome (2.1.2)
e2e/react-start/basic-prerendering/src/routes/deferred.tsx
[error] 43-43: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 53-53: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
e2e/react-start/basic-prerendering/src/routes/stream.tsx
[error] 51-51: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~12-~12: There might be a mistake here.
Context: ... parameters (e.g., /about
, /contact
) - Routes with search parameters that have ...
(QB_NEW_EN)
[grammar] ~13-~13: There might be a mistake here.
Context: ...arch parameters that have default values - Routes that don't require dynamic data f...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
e2e/react-start/basic-prerendering/src/routes/search-params/default.tsx
Outdated
Show resolved
Hide resolved
e2e/react-start/basic-prerendering/src/routes/users.$userId.tsx
Outdated
Show resolved
Hide resolved
i dont think we need a separate e2e test for this, can we please just add this to the existing start-basic e2e test? |
I will check, but i didn't want to change the existing testing by turning on WDYT? |
if (!route.routePath) continue | ||
|
||
// filter routes that are layout | ||
if (route.isNonPath === true) continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldnt we just want to render leaf routes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure I understand, but this code just check that it's not a layout, and nodes that doesn't have routePath
what are leaf routes? do they not have routePath
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a route does not have children it's a leaf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, so you I should just check if the route has children?
how would it work for
users.tsx
users/details.tsx
user.tsx has children and a leaf node at the same time right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, after testing. we still need to render non leaf children, i.e routes that have
let me know if you have other conrences regarding this point, otherwise, please resolve this conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what are "non leaf children"?
in your example
users.tsx << non leaf
users/index.tsx << leaf
users/details.tsx << leaf
@schiller-manuel thanks for the review🙏, I will have to address your comments tomorrow, it's getting late here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
docs/start/framework/react/guide/static-prerendering.md (2)
12-14
: Revise the automatic discovery criteria to match implementation.The documentation incorrectly states that automatic discovery only includes routes that "don't require dynamic data fetching." However, based on the e2e tests (
e2e/react-start/basic-prerendering/tests/prerendering.spec.ts
), routes with loaders and API calls (e.g.,/users
,/posts
) are successfully prerendered. Additionally, there's no evidence in the code that search parameters with default values are checked during discovery.Apply this diff to accurately describe the discovery behavior:
-- Routes with no path parameters (e.g., `/about`, `/contact`) -- Routes with search parameters that have default values -- Routes that don't require dynamic data fetching +- Routes with no path parameters (e.g., `/about`, `/contact`) +- Routes that may fetch data via loaders or API calls (these are prerendered with their initial data)
20-20
: Remove duplicate text.This sentence repeats information already stated in the "Automatic Static Route Discovery" section above.
Apply this diff:
-TanStack Start can prerender your application to static HTML files, which can then be served to users without having to generate them on the fly. When prerendering is enabled without specifying pages, TanStack Start will automatically discover and prerender all static routes in your application. +TanStack Start can prerender your application to static HTML files, which can then be served to users without having to generate them on the fly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
docs/start/framework/react/guide/static-prerendering.md
(2 hunks)packages/router-generator/src/index.ts
(1 hunks)packages/start-plugin-core/src/global.d.ts
(1 hunks)packages/start-plugin-core/src/prerender.ts
(6 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/plugin.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/start-plugin-core/src/start-router-plugin/plugin.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-plugin-core/src/global.d.ts
packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts
packages/router-generator/src/index.ts
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/schema.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/global.d.ts
packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/schema.ts
packages/{router-cli,router-generator,router-plugin,virtual-file-routes}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep CLI, generators, bundler plugins, and virtual file routing utilities in their dedicated tooling package directories
Files:
packages/router-generator/src/index.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
🧬 Code graph analysis (1)
packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts (2)
packages/router-generator/src/index.ts (3)
GeneratorPlugin
(12-12)RouteNode
(34-34)inferFullPath
(30-30)packages/router-core/src/route.ts (1)
path
(1551-1553)
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~12-~12: There might be a mistake here.
Context: ... parameters (e.g., /about
, /contact
) - Routes with search parameters that have ...
(QB_NEW_EN)
[grammar] ~13-~13: There might be a mistake here.
Context: ...arch parameters that have default values - Routes that don't require dynamic data f...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (8)
packages/router-generator/src/index.ts (1)
30-30
: LGTM! Export addition follows existing patterns.The addition of
inferFullPath
to the public exports is appropriate for enabling automatic prerenderable path discovery. The change is backward compatible and follows the established re-export pattern in this index file.docs/start/framework/react/guide/static-prerendering.md (1)
55-56
: LGTM! Clear documentation of the new option.The
maxRedirect
option is well documented with its default value, making it easy for users to understand and configure redirect limits during prerendering.packages/start-plugin-core/src/global.d.ts (1)
6-6
: LGTM! Clean global type declaration.The new
TSS_PRERENDABLE_PATHS
global follows the existing pattern and provides appropriate typing for the automatic route discovery feature.packages/start-plugin-core/src/schema.ts (1)
189-189
: LGTM! Schema properly validates the new option.The
maxRedirect
field is correctly added as an optional number, aligning with its usage inprerender.ts
where it defaults to 5.packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts (2)
23-32
: LGTM! Comprehensive filtering logic.The filtering logic appropriately excludes:
- Routes without a path
- Layout routes (non-path routes)
- Dynamic routes (containing
$
)- API routes (without a component)
The comment on Line 32 helpfully clarifies why routes without components are filtered.
17-38
: Avoid adding'/'
unconditionallyThe function seeds
paths
with'/'
, so ifrouteNodes
lacks a root index route you’ll still return{ path: '/' }
. Only include'/'
when a correspondingrouteNode.routePath === '/'
exists.packages/start-plugin-core/src/prerender.ts (2)
73-95
: LGTM! Robust redirect handling with proper limits.The redirect logic correctly:
- Follows internal redirects up to the configured limit
- Warns and skips external redirects
- Returns the last response when the limit is reached
The subsequent check on Lines 182-184 appropriately warns users when
maxRedirect
is exhausted, addressing the maintainer's concern.
126-137
: LGTM! Accurate tracking of successfully prerendered pages.Introducing a separate
prerendered
Set (Line 126) and returning it (Line 137) instead ofseen
ensures the function reports only successfully written pages, not just attempted ones. This is a meaningful improvement for observability.
as I am re-writing the docs, I realize that static path discover should be a config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/start-plugin-core/src/prerender.ts
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-plugin-core/src/prerender.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (5)
packages/start-plugin-core/src/prerender.ts (5)
73-95
: LGTM! Redirect handling logic is sound.The redirect following logic correctly:
- Limits recursion via
maxRedirect
to prevent infinite loops- Restricts following to internal redirects only (localhost or relative paths)
- Warns about external redirects
- Returns the redirect response when max redirects are exhausted (properly handled downstream at lines 182-184)
Note: The
Request
constructor at line 82 preserves the originaloptions
(including headers) when following redirects, which is correct.
126-126
: LGTM! Better tracking of successful prerenders.Introducing the
prerendered
Set separates "attempted" (tracked byseen
) from "successfully prerendered" paths, and returning only successful paths provides accurate reporting to the caller.Also applies to: 137-137
182-184
: LGTM! Helpful logging for redirect exhaustion.The warning clearly indicates when a page fails due to exceeding
maxRedirect
, helping users diagnose redirect loops.Based on learnings (past review comments): This addresses the requested logging when max redirects are reached.
224-224
: LGTM! Correctly tracks successful prerender.The page is added to
prerendered
only after the HTML is successfully written to disk, ensuring accurate success tracking.
171-179
: Naming consistency verified formaxRedirect
. The schema, default parameter, andlocalFetch
invocation all use the singularmaxRedirect
with a default of 5—no changes required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/start-plugin-core/src/prerender.ts (1)
26-31
: Add type guard before assigning discovered paths.The code assigns
globalThis.TSS_PRERENDABLE_PATHS
directly without validating it's an array. If the global is undefined, null, or a non-array value, this will cause a runtime error when checking.length
.Apply this diff to add proper validation:
if (startConfig.prerender?.enabled && !startConfig.pages.length) { try { - startConfig.pages = globalThis.TSS_PRERENDABLE_PATHS - if (!startConfig.pages.length) { + const discovered = globalThis.TSS_PRERENDABLE_PATHS + if (!Array.isArray(discovered) || discovered.length === 0) { logger.warn('No static paths discovered. Falling back to root "/"') startConfig.pages = [{ path: '/' }] + } else { + startConfig.pages = discovered } } catch (error) {Based on learnings
🧹 Nitpick comments (1)
packages/start-plugin-core/src/prerender.ts (1)
88-96
: Consider URL parsing for more robust redirect handling.The current string manipulation (
location.replace('http://localhost', '')
) works but has edge cases:
- If location is exactly
'http://localhost'
(no path),newUrl
becomes an empty string- Only replaces the first occurrence if multiple 'http://localhost' substrings exist
Apply this diff to use URL parsing:
if (isRedirectResponse(response) && maxRedirect > 0) { const location = response.headers.get('location')! - if (location.startsWith('http://localhost') || location.startsWith('/')) { - const newUrl = location.replace('http://localhost', '') - return localFetch(newUrl, options, maxRedirect - 1) + try { + const redirectUrl = new URL(location, 'http://localhost') + if (redirectUrl.hostname === 'localhost' || location.startsWith('/')) { + return localFetch(redirectUrl.pathname + redirectUrl.search + redirectUrl.hash, options, maxRedirect - 1) + } + } catch { + // Malformed URL, skip redirect + logger.warn(`Malformed redirect location: ${location}`) + } - } else { - logger.warn(`Skipping redirect to external location: ${location}`) - } + logger.warn(`Skipping redirect to external location: ${location}`) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/start-plugin-core/src/prerender.ts
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-plugin-core/src/prerender.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (3)
packages/start-plugin-core/src/prerender.ts (3)
130-130
: Good semantic improvement.Tracking
prerendered
separately fromseen
accurately reflects which pages were successfully written to disk versus merely encountered during crawling.Also applies to: 141-141
186-188
: Good diagnostic logging for redirect limits.The warning helps users identify infinite redirect loops or pages requiring more than the configured redirect limit.
228-228
: LGTM!Correctly tracks successfully prerendered pages after writing to disk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (3)
docs/start/framework/react/guide/static-prerendering.md (2)
74-75
: Clarify the automatic discovery description.The sentence is ungrammatical and misses the key takeaway that discovered paths are merged with any explicitly configured
pages
. Suggest rephrasing:-## Automatic Static Route Discovery - -All static paths will be prerendered, and seamlessly merge them with specified `pages` config +## Automatic Static Route Discovery + +When enabled, TanStack Start prerenders every static path it finds and merges those results with any routes you explicitly list in `pages`.
80-82
: Polish the crawling description.The heading and example need better wording:
-## Crawling Links - -Prerender the pages link the prerendered pages - -if `/` --has link to--> `/posts`, `/posts` will also be prerendered +## Crawling Links + +TanStack Start can also follow links found in prerendered HTML. + +For example, if `/` links to `/posts`, the `/posts` page will be prerendered too.packages/start-plugin-core/src/prerender.ts (1)
84-106
: Boolean redirect check and robust redirect resolution (handle https, ports, and relative locations).Make the helper boolean and resolve target using URL(base) instead of string replace.
- const isRedirectResponse = (res: Response) => { - return res.status >= 300 && res.status < 400 && res.headers.get('location') - } + const isRedirectResponse = (res: Response): boolean => { + return res.status >= 300 && res.status < 400 && !!res.headers.get('location') + } async function localFetch( path: string, options?: RequestInit, maxRedirect: number = 5, ): Promise<Response> { - const url = new URL(`http://localhost${path}`) - const response = await serverEntrypoint.fetch(new Request(url, options)) + const requestUrl = new URL(path, 'http://localhost') + const response = await serverEntrypoint.fetch(new Request(requestUrl, options)) - if (isRedirectResponse(response) && maxRedirect > 0) { - const location = response.headers.get('location')! - if (location.startsWith('http://localhost') || location.startsWith('/')) { - const newUrl = location.replace('http://localhost', '') - return localFetch(newUrl, options, maxRedirect - 1) - } else { - logger.warn(`Skipping redirect to external location: ${location}`) - } - } + if (isRedirectResponse(response)) { + if (maxRedirect <= 0) { + return response + } + const location = response.headers.get('location')! + const targetUrl = new URL(location, requestUrl) + if (targetUrl.origin === requestUrl.origin) { + const nextPath = `${targetUrl.pathname}${targetUrl.search}` + return localFetch(nextPath, options, maxRedirect - 1) + } else { + logger.warn(`Skipping redirect to external origin: ${targetUrl.href}`) + } + } return response }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
docs/start/framework/react/guide/static-prerendering.md
(4 hunks)packages/start-plugin-core/src/prerender.ts
(6 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/start-plugin-core/src/schema.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-plugin-core/src/prerender.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~74-~74: There might be a mistake here.
Context: ...ute Discovery All static paths will be prerendered, and seamlessly merge them with specifie...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (2)
packages/start-plugin-core/src/prerender.ts (2)
135-149
: Return only successfully prerendered pages — LGTM.Switching to track and return actually written pages improves reporting accuracy.
235-236
: Record prerendered path after write — LGTM.Accurately marking success post-write is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
docs/start/framework/react/guide/static-prerendering.md (2)
28-30
: Example contradicts the narrative; also fix “pre-rerendered”.The example disables auto discovery while the text says it’s automatic when pages aren’t specified. Align the sample and fix the hyphenation.
- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Enable automatic discovery of static routes when pages aren’t specified + autoStaticPathsDiscovery: true,
57-60
: Remove redundancy.This note repeats what’s explained above. Trim to keep the section focused.
- // Optional configuration for specific pages - // Note: When pages are not specified, TanStack Start will automatically - // discover and prerender all static routes in your application + // Optional configuration for specific pages
🧹 Nitpick comments (3)
docs/start/framework/react/guide/static-prerendering.md (3)
10-10
: Grammar and clarity fix.Tighten the sentence.
-Set the `prerender.enabled` to `true`, others fields are optional +Set `prerender.enabled` to `true`; other fields are optional.Also, your snippet uses defineConfig but doesn’t import it. Add this near the other imports:
import { defineConfig } from 'vite'
74-75
: Clarify and fix grammar in discovery section.Make the sentence clear and correct.
-All static paths will be prerendered, and seamlessly merge them with specified `pages` config +When enabled, all static routes are automatically discovered and prerendered. Any explicitly configured `pages` are merged with the discovered set.
80-82
: Improve wording and mention crawlLinks behavior.Clear grammar and tie to the option.
-Prerender the pages link the prerendered pages - -if `/` --has link to--> `/posts`, `/posts` will also be prerendered +Prerender pages linked from prerendered pages (controlled by `crawlLinks`). + +For example, if `/` links to `/posts`, then `/posts` will also be prerendered.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
docs/start/framework/react/guide/static-prerendering.md
(4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~74-~74: There might be a mistake here.
Context: ...ute Discovery All static paths will be prerendered, and seamlessly merge them with specifie...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
docs/start/framework/react/guide/static-prerendering.md (1)
28-30
: Example contradicts the documented default behavior.Setting
autoStaticPathsDiscovery: false
disables the automatic discovery feature that the surrounding documentation promotes. Since the schema default istrue
and the docs state that discovery happens automatically, either:
- Remove this line to show the default behavior, or
- Change it to
true
with a comment explaining it's the defaultApply this diff to align the example with the documented behavior:
- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Automatically discover static routes and merge with pages config (default: true) + autoStaticPathsDiscovery: true,Or remove it entirely:
- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, -
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/start/framework/react/guide/static-prerendering.md
(4 hunks)packages/start-plugin-core/src/prerender.ts
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-plugin-core/src/prerender.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~74-~74: There might be a mistake here.
Context: ...ute Discovery All static paths will be prerendered, and seamlessly merge them with specifie...
(QB_NEW_EN)
🔇 Additional comments (4)
packages/start-plugin-core/src/prerender.ts (4)
24-44
: Clarify the auto-discovery merging behavior.The current implementation merges discovered static paths with user-defined pages regardless of whether pages were explicitly specified. This differs from the typical interpretation of "automatic discovery when pages are not specified" (as stated in PR objectives and documentation).
However, past comments suggest this merging behavior is intentional. Please confirm:
- Should auto-discovery merge with explicit pages (current behavior)?
- Or should it only activate when
startConfig.pages
is empty (as PR objectives imply)?If merging is the intended design, update the documentation to clearly state that
autoStaticPathsDiscovery
supplements rather than replaces user-specified pages.The implementation looks correct for the merge approach. The
|| []
fallback at line 32 properly handles undefined/missing global paths. However, consider adding validation to ensure discovered pages are valid:const pagesMap = new Map(pages.map((item) => [item.path, item])) const discoveredPages = globalThis.TSS_PRERENDABLE_PATHS || [] for (const page of discoveredPages) { - if (!pagesMap.has(page.path)) { + if (page?.path && !pagesMap.has(page.path)) { pagesMap.set(page.path, page) } }
85-107
: LGTM: Solid redirect handling implementation.The redirect-following logic is well-implemented:
- Correctly identifies redirect responses (300-399 with Location header)
- Follows internal redirects (localhost or root-relative) recursively
- Respects the
maxRedirect
limit to prevent infinite loops- Warns about external redirects instead of following them
- Preserves request options across redirects
One minor suggestion for improved observability when the redirect limit is reached:
if (isRedirectResponse(response) && maxRedirect > 0) { const location = response.headers.get('location')! if (location.startsWith('http://localhost') || location.startsWith('/')) { const newUrl = location.replace('http://localhost', '') return localFetch(newUrl, options, maxRedirect - 1) } else { logger.warn(`Skipping redirect to external location: ${location}`) } + } else if (isRedirectResponse(response) && maxRedirect === 0) { + logger.warn(`Redirect limit reached at ${path}`) }This helps distinguish between "max redirects reached" vs "redirect succeeded" in the calling code.
138-149
: Verify the tracking set change aligns with intended behavior.The return value changed from
seen
toprerendered
. This means:
- Previously: returned all pages that were attempted (including failures)
- Now: returns only successfully prerendered pages
This is likely the correct behavior (only report success), but verify that:
- Calling code expects only successful pages
- Failed pages don't need to be reported separately
- The log message "Prerendered X pages" accurately reflects successful count
The implementation correctly tracks successful prerenders by adding to the set only after
writeFile
succeeds (line 236).
183-196
: LGTM: Proper integration of redirect handling.The
localFetch
call correctly:
- Passes the
maxRedirect
parameter from merged options- Guards against undefined headers with
?? {}
- Checks for redirect responses when
!res.ok
- Logs a warning when max redirects are reached
The warning at line 195 provides useful feedback to users when they hit the redirect limit. Consider whether the error thrown at line 197 should include more context about the redirect chain for debugging.
1c20aad
to
adabf0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (1)
docs/start/framework/react/guide/static-prerendering.md (1)
28-30
: Example contradicts the demonstrated feature.The example shows
autoStaticPathsDiscovery: false
, which disables automatic discovery—the primary feature being documented. Since the default istrue
(as seen in prerender.ts line 29) and this section demonstrates "Enabling Prerendering," consider:Option 1 (recommended): Remove the line entirely to use the default:
- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false,Option 2: Show it enabled with an updated comment:
- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Automatically discover and merge static routes with pages config (default: true) + autoStaticPathsDiscovery: true,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (12)
docs/start/framework/react/guide/static-prerendering.md
(4 hunks)e2e/react-start/basic/package.json
(1 hunks)e2e/react-start/basic/playwright.config.ts
(3 hunks)e2e/react-start/basic/tests/search-params.spec.ts
(4 hunks)e2e/react-start/basic/tests/utils/isPrerender.ts
(1 hunks)e2e/react-start/basic/vite.config.ts
(3 hunks)packages/router-generator/src/index.ts
(1 hunks)packages/start-plugin-core/src/global.d.ts
(1 hunks)packages/start-plugin-core/src/prerender.ts
(6 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts
(1 hunks)packages/start-plugin-core/src/start-router-plugin/plugin.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/start-plugin-core/src/start-router-plugin/plugin.ts
- packages/start-plugin-core/src/schema.ts
- packages/start-plugin-core/src/start-router-plugin/generator-plugins/prerender-routes-plugin.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/basic/tests/search-params.spec.ts
e2e/react-start/basic/tests/utils/isPrerender.ts
e2e/react-start/basic/playwright.config.ts
packages/start-plugin-core/src/prerender.ts
packages/router-generator/src/index.ts
e2e/react-start/basic/vite.config.ts
packages/start-plugin-core/src/global.d.ts
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/basic/tests/search-params.spec.ts
e2e/react-start/basic/tests/utils/isPrerender.ts
e2e/react-start/basic/playwright.config.ts
e2e/react-start/basic/package.json
e2e/react-start/basic/vite.config.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/global.d.ts
packages/{router-cli,router-generator,router-plugin,virtual-file-routes}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep CLI, generators, bundler plugins, and virtual file routing utilities in their dedicated tooling package directories
Files:
packages/router-generator/src/index.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
e2e/react-start/basic/package.json
🧬 Code graph analysis (3)
e2e/react-start/basic/tests/search-params.spec.ts (2)
e2e/react-start/basic/tests/utils/isSpaMode.ts (1)
isSpaMode
(1-1)e2e/react-start/basic/tests/utils/isPrerender.ts (1)
isPrerender
(1-1)
e2e/react-start/basic/playwright.config.ts (2)
e2e/react-start/basic/tests/utils/isSpaMode.ts (1)
isSpaMode
(1-1)e2e/react-start/basic/tests/utils/isPrerender.ts (1)
isPrerender
(1-1)
e2e/react-start/basic/vite.config.ts (1)
e2e/react-start/basic/tests/utils/isPrerender.ts (1)
isPrerender
(1-1)
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g API route...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (14)
packages/router-generator/src/index.ts (1)
30-30
: LGTM – inferFullPath is exported and has JSDoc documentation.e2e/react-start/basic/playwright.config.ts (2)
22-26
: LGTM!The
getCommand()
helper provides clean mode selection logic with appropriate fallback to SSR mode.
20-20
: Dummy server scripts are defined in package.json.The
test:e2e:startDummyServer
andtest:e2e:stopDummyServer
scripts are confirmed to exist. TheprerenderModeCommand
is properly configured.The 152+ character command string is readable as-is, though breaking it into multiple lines or storing commands in separate variables would improve maintainability if this grows further.
e2e/react-start/basic/tests/utils/isPrerender.ts (1)
1-1
: LGTM!The implementation is clean and follows the same pattern as
isSpaMode.ts
. The explicit boolean type annotation ensures type safety.e2e/react-start/basic/tests/search-params.spec.ts (2)
31-33
: Verify that skipping redirect expectations aligns with prerender behavior.The test now skips redirect expectations when
isPrerender
is true. This suggests that during prerendering, redirects are followed server-side and baked into the static HTML, so the browser won't observe the redirect.Confirm this matches the intended prerender behavior described in the PR (redirect-following logic during prerendering).
56-58
: Consistent with the redirect handling above.This check mirrors the logic at line 31, ensuring redirect expectations are skipped consistently across prerender mode tests.
e2e/react-start/basic/vite.config.ts (2)
15-26
: Verify the maxRedirect value and document the filter logic.The
prerenderConfiguration
looks well-structured, but:
maxRedirect: 100 — This value seems arbitrary. Verify if it aligns with the "redirect count limit" mentioned in the PR objectives or if it should be documented/made configurable.
Filter paths — The hardcoded exclusion list is appropriate for e2e tests (excluding 404s, redirects, etc.), but consider adding a brief inline comment explaining why these specific paths are filtered out for future maintainability.
39-39
: LGTM!The conditional prerender configuration follows the same pattern as the SPA configuration, maintaining consistency in the codebase.
packages/start-plugin-core/src/global.d.ts (1)
6-6
: LGTM! Clean global type declaration.The type definition correctly declares the global as optional with an appropriate structure that matches the Page type's minimal shape. The optional nature aligns with the fallback handling in prerender.ts (
|| []
).packages/start-plugin-core/src/prerender.ts (4)
24-44
: Clarify merge behavior in documentation.The implementation merges discovered static paths with user-specified pages (as confirmed in your "scope changed" comment). However, the PR objectives state: "When prerender.enabled: true and no pages specified, automatically prerender all static routes."
This creates an inconsistency between the stated objectives and the actual behavior. While the documentation at line 74 correctly states paths are "merged with the specified
pages
config," the comment at lines 57-60 in the docs says "When pages are not specified" which contradicts the merging behavior.Please clarify the intended behavior and update either:
- The PR objectives/description to reflect that discovery merges with specified pages, OR
- The implementation to only auto-discover when
startConfig.pages
is emptyAdditionally, the documentation example at line 29 shows
autoStaticPathsDiscovery: false
, which disables the feature being demonstrated. Consider setting it totrue
or removing it to use the default.
85-107
: LGTM! Solid redirect handling logic.The redirect-following logic is well-implemented:
- Correctly identifies redirect responses (3xx status with Location header)
- Limits redirect depth with configurable
maxRedirect
parameter- Only follows internal redirects (localhost or root-relative paths) for security
- Warns about external redirects appropriately
- Previous concerns about parameter naming and header spreading have been addressed
138-138
: LGTM! Accurate tracking of prerendered pages.The change from tracking "seen" pages to tracking actually "prerendered" pages improves accuracy. Returning the prerendered set (line 149) ensures the reported count reflects pages that were successfully written to disk, not just attempted.
Also applies to: 149-149, 236-236
183-191
: All previous concerns addressed.The localFetch invocation correctly:
- Passes
maxRedirect
parameter matching the schema field- Guards header spreading with nullish coalescing (
?? {}
)- Includes redirect warning at lines 194-196 as requested in past reviews
docs/start/framework/react/guide/static-prerendering.md (1)
72-82
: LGTM! Accurate description of auto-discovery behavior.The section correctly describes:
- Merging of discovered paths with specified pages config (line 74)
- Exclusions from automatic discovery (layout routes, dynamic routes, routes without components)
- Ability to prerender dynamic routes via
crawlLinks
Note: LanguageTool warnings at lines 78-79 appear to be false positives—the markdown list syntax is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (3)
docs/start/framework/react/guide/static-prerendering.md (3)
28-30
: Align the example with the documented default behavior.Setting
autoStaticPathsDiscovery
tofalse
disables the very feature this section is introducing, and the comment still uses the incorrect “pre-rerendered” wording. Please show it enabled (or drop the override) and clarify the comment.- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Automatically discover static routes and merge them with the pages config (default) + autoStaticPathsDiscovery: true,
57-59
: Update the note to reflect path merging.Discovered static paths are merged with the
pages
array when auto discovery is on; the current note still claims the opposite. Please reword it to describe the merge behavior controlled byautoStaticPathsDiscovery
.
88-88
: Remove the stray+
marker.The leading plus sign looks like a diff artifact; drop it so the sentence renders properly.
🧹 Nitpick comments (1)
docs/start/framework/solid/guide/static-prerendering.md (1)
80-80
: Grammar nit: add the comma in “e.g., API routes”.Tiny readability tweak: “Routes without components (e.g., API routes)”.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/start/framework/react/guide/static-prerendering.md
(3 hunks)docs/start/framework/solid/guide/static-prerendering.md
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g API route...
(QB_NEW_EN)
docs/start/framework/solid/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g API route...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/start/framework/solid/guide/static-prerendering.md (1)
15-68
: Restore the Solid-specific Vite plugins.This Solid guide now imports the React Start and Vite React plugins, which won’t work in a Solid project. Please switch back to the Solid equivalents (e.g.,
@tanstack/solid-start/plugin/vite
andvite-plugin-solid
) and update the plugin invocation accordingly.-import { tanstackStart } from '@tanstack/react-start/plugin/vite' -import viteReact from '@vitejs/plugin-react' +import { tanstackStart } from '@tanstack/solid-start/plugin/vite' +import solid from 'vite-plugin-solid' @@ - }), - viteReact(), + }), + solid(),
♻️ Duplicate comments (2)
docs/start/framework/solid/guide/static-prerendering.md (1)
28-30
: Keep auto discovery enabled in the example.Explicitly setting
autoStaticPathsDiscovery: false
disables static route discovery and contradicts the text. Either remove the override or show it enabled.- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Disable only if you want to prerender just the root or the paths defined in pages config + // autoStaticPathsDiscovery: false,docs/start/framework/react/guide/static-prerendering.md (1)
28-30
: Keep auto discovery enabled in the example.Setting
autoStaticPathsDiscovery
tofalse
here disables the very behavior this section explains and misleads readers following the sample. Either drop the override (to inherit the defaulttrue
) or explicitly set it totrue
and adjust the comment copy.- // If disabled only root or the paths defined in pages config will be pre-rerendered - autoStaticPathsDiscovery: false, + // Disable only if you want to prerender just the root or the paths defined in pages config + // autoStaticPathsDiscovery: false,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
docs/start/framework/react/guide/static-prerendering.md
(3 hunks)docs/start/framework/solid/guide/static-prerendering.md
(3 hunks)e2e/react-start/basic/package.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- e2e/react-start/basic/package.json
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g API route...
(QB_NEW_EN)
docs/start/framework/solid/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g API route...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
…in static prerendering documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/start/framework/react/guide/static-prerendering.md
(3 hunks)docs/start/framework/solid/guide/static-prerendering.md
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g., API rou...
(QB_NEW_EN)
docs/start/framework/solid/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g., API rou...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
…rerendering behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
docs/start/framework/solid/guide/static-prerendering.md (1)
12-20
: Add missing import for defineConfig in the Vite config snippet.Copy-pasting will fail without importing defineConfig.
// vite.config.ts - +import { defineConfig } from 'vite' import { tanstackStart } from '@tanstack/solid-start/plugin/vite' import viteSolid from 'vite-plugin-solid'docs/start/framework/react/guide/static-prerendering.md (2)
57-66
: Example config bug:pages
is outside theprerender
block.In the snippet,
pages
is a sibling ofprerender
. It must be nested insideprerender
for the config to work.Replace the
prerender
section with this corrected block:prerender: { // Enable prerendering enabled: true, // Enable if you need pages to be at `/page/index.html` instead of `/page.html` autoSubfolderIndex: true, // If disabled, only the root path or the paths defined in the pages config will be prerendered autoStaticPathsDiscovery: true, // How many prerender jobs to run at once concurrency: 14, // Whether to extract links from the HTML and prerender them also crawlLinks: true, // Filter function takes the page object and returns whether it should prerender filter: ({ path }) => !path.startsWith('/do-not-render-me'), // Number of times to retry a failed prerender job retryCount: 2, // Delay between retries in milliseconds retryDelay: 1000, // Maximum number of redirects to follow during prerendering maxRedirect: 5, // Fail if an error occurs during prerendering failOnError: true, // Callback when page is successfully rendered onSuccess: ({ page }) => { console.log(`Rendered ${page.path}!`) }, // Optional configuration for specific pages // Note: When autoStaticPathsDiscovery is enabled (default), discovered static // routes will be merged with the pages specified below pages: [ { path: '/my-page', prerender: { enabled: true, outputPath: '/my-page/index.html' }, }, ], },
12-20
: Missing import for defineConfig in the snippet.Add the import so the example is copy‑paste runnable.
// vite.config.ts - -import { tanstackStart } from '@tanstack/react-start/plugin/vite' +import { defineConfig } from 'vite' +import { tanstackStart } from '@tanstack/react-start/plugin/vite' import viteReact from '@vitejs/plugin-react'
♻️ Duplicate comments (2)
docs/start/framework/solid/guide/static-prerendering.md (1)
74-75
: Reword claim to align with listed exclusions.Current sentence over-promises (“All static paths...”) while the bullets list exclusions. Suggest:
-All static paths will be automatically discovered and seamlessly merged with the specified `pages` config +Static routes that meet the criteria below are automatically discovered and seamlessly merged with the specified `pages` configdocs/start/framework/react/guide/static-prerendering.md (1)
74-74
: Overpromise: not “All static paths.” Limit to eligible routes.Rephrase to match the exclusion list that follows.
- All static paths will be automatically discovered and seamlessly merged with the specified `pages` config + Static routes that meet the criteria below are automatically discovered and seamlessly merged with the specified `pages` config
🧹 Nitpick comments (2)
docs/start/framework/solid/guide/static-prerendering.md (1)
46-51
: Document defaults/behavior for new options (maxRedirect, failOnError).State their default values and effect (e.g., does failOnError exit the build?). Helps readers rely on implied defaults without copying values.
docs/start/framework/react/guide/static-prerendering.md (1)
28-30
: Clarify disabled behavior (mention crawlLinks).When auto discovery is disabled, root-linked pages can still be prerendered if
crawlLinks
is true. Add that to avoid confusion.- // If disabled, only the root path or the paths defined in the pages config will be prerendered + // If disabled, only the root path (and any pages discovered via crawlLinks) or the paths defined in the pages config will be prerendered
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/start/framework/react/guide/static-prerendering.md
(3 hunks)docs/start/framework/solid/guide/static-prerendering.md
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/react/guide/static-prerendering.md
docs/start/framework/solid/guide/static-prerendering.md
🪛 LanguageTool
docs/start/framework/react/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g., API rou...
(QB_NEW_EN)
docs/start/framework/solid/guide/static-prerendering.md
[grammar] ~78-~78: There might be a mistake here.
Context: ...e they require specific parameter values - Layout routes (prefixed with _
) since ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...since they don't render standalone pages - Routes without components (e.g., API rou...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (2)
docs/start/framework/solid/guide/static-prerendering.md (2)
15-16
: Solid Start + Vite Solid plugins correctly used.
Looks good and resolves prior feedback to avoid React plugins in Solid docs.
28-30
: Correct default and guidance for autoStaticPathsDiscovery.
Good: default enabled and clear note about behavior when disabled.
@schiller-manuel can you check? please. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
e2e/react-start/basic/tests/prerendering.spec.ts (3)
12-12
: Extract repeateddistDir
path construction.The
distDir
path is constructed identically three times across different tests. Extract it to a shared constant orbeforeEach
hook to reduce duplication and improve maintainability.Apply this refactor to consolidate the path construction:
+let distDir: string + test.describe('Prerender Static Path Discovery', () => { test.skip(!isPrerender, 'Skipping since not in prerender mode') + + test.beforeEach(() => { + distDir = join(process.cwd(), 'dist', 'client') + }) + test.describe('Build Output Verification', () => { test('should automatically discover and prerender static routes', () => { // Check that static routes were automatically discovered and prerendered - const distDir = join(process.cwd(), 'dist', 'client') // These static routes should be automatically discovered and prerenderedtest.describe('Static Files Verification', () => { test('should contain prerendered content in posts.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') expect(existsSync(join(distDir, 'posts.html'))).toBe(true)
test('should contain prerendered content in users.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') expect(existsSync(join(distDir, 'users.html'))).toBe(true)
Also applies to: 36-36, 45-45
35-51
: Refactor duplicate test pattern with parameterization.The two tests in Static Files Verification follow identical patterns, differing only in filename and expected text. Parameterize these tests to reduce duplication and improve maintainability.
Apply this refactor to parameterize the tests:
test.describe('Static Files Verification', () => { - test('should contain prerendered content in posts.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'posts.html'))).toBe(true) - - // "Select a post." should be in the prerendered HTML - const html = readFileSync(join(distDir, 'posts.html'), 'utf-8') - expect(html).toContain('Select a post.') - }) - - test('should contain prerendered content in users.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'users.html'))).toBe(true) - - // "Select a user." should be in the prerendered HTML - const html = readFileSync(join(distDir, 'users.html'), 'utf-8') - expect(html).toContain('Select a user.') - }) + const testCases = [ + { file: 'posts.html', expectedText: 'Select a post.' }, + { file: 'users.html', expectedText: 'Select a user.' }, + ] + + testCases.forEach(({ file, expectedText }) => { + test(`should contain prerendered content in ${file}`, () => { + const filePath = join(distDir, file) + expect(existsSync(filePath)).toBe(true) + + const html = readFileSync(filePath, 'utf-8') + expect(html).toContain(expectedText) + }) + }) })
37-37
: Remove redundantexistsSync
checks.The
existsSync
checks beforereadFileSync
are redundant.readFileSync
will throw a clear error if the file doesn't exist, making the explicit existence check unnecessary. Removing these checks simplifies the code while maintaining the same failure behavior.Apply this diff to remove the redundant checks:
test('should contain prerendered content in posts.html', () => { const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'posts.html'))).toBe(true) // "Select a post." should be in the prerendered HTML const html = readFileSync(join(distDir, 'posts.html'), 'utf-8') expect(html).toContain('Select a post.') }) test('should contain prerendered content in users.html', () => { const distDir = join(process.cwd(), 'dist', 'client') - expect(existsSync(join(distDir, 'users.html'))).toBe(true) // "Select a user." should be in the prerendered HTML const html = readFileSync(join(distDir, 'users.html'), 'utf-8') expect(html).toContain('Select a user.') })Also applies to: 46-46
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
e2e/react-start/basic/package.json
(1 hunks)e2e/react-start/basic/tests/prerendering.spec.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- e2e/react-start/basic/package.json
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/basic/tests/prerendering.spec.ts
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/basic/tests/prerendering.spec.ts
🧬 Code graph analysis (1)
e2e/react-start/basic/tests/prerendering.spec.ts (1)
e2e/react-start/basic/tests/utils/isPrerender.ts (1)
isPrerender
(1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (1)
e2e/react-start/basic/tests/prerendering.spec.ts (1)
7-53
: Remove placement warning for prerendering.spec.ts
Feature-specific e2e tests in e2e/react-start/basic/tests are each in their own .spec.ts file; adding prerendering.spec.ts aligns with the existing pattern.Likely an incorrect or invalid review comment.
…umentation and code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
docs/start/framework/solid/guide/static-prerendering.md (1)
80-80
: Fix punctuation: add comma after "e.g."Apply this diff:
-- Routes without components (e.g API routes) +- Routes without components (e.g., API routes)
🧹 Nitpick comments (1)
packages/start-plugin-core/src/prerender.ts (1)
24-44
: Add defensive validation for discovered pages.While the
|| []
fallback handlesundefined
, the code doesn't validate that each item indiscoveredPages
has a.path
property. If the global is set to an invalid array, line 35 will throw.Apply this diff to add a safeguard:
const discoveredPages = globalThis.TSS_PRERENDABLE_PATHS || [] for (const page of discoveredPages) { - if (!pagesMap.has(page.path)) { + if (page?.path && !pagesMap.has(page.path)) { pagesMap.set(page.path, page) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
docs/start/framework/react/guide/static-prerendering.md
(3 hunks)docs/start/framework/solid/guide/static-prerendering.md
(3 hunks)e2e/react-start/basic/vite.config.ts
(3 hunks)packages/start-plugin-core/src/prerender.ts
(6 hunks)packages/start-plugin-core/src/schema.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/start/framework/react/guide/static-prerendering.md
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/basic/vite.config.ts
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/schema.ts
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/basic/vite.config.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-plugin-core/src/prerender.ts
packages/start-plugin-core/src/schema.ts
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Use internal docs links relative to the docs/ folder (e.g., ./guide/data-loading)
Files:
docs/start/framework/solid/guide/static-prerendering.md
docs/{router,start}/**
📄 CodeRabbit inference engine (AGENTS.md)
Place router docs under docs/router/ and start framework docs under docs/start/
Files:
docs/start/framework/solid/guide/static-prerendering.md
🧬 Code graph analysis (1)
e2e/react-start/basic/vite.config.ts (1)
e2e/react-start/basic/tests/utils/isPrerender.ts (1)
isPrerender
(1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (10)
docs/start/framework/solid/guide/static-prerendering.md (3)
28-30
: Documentation looks good!The comment accurately describes the behavior when
autoStaticPathsDiscovery
is disabled, and setting it totrue
(the default) is the correct example for users.
57-59
: Clear documentation of merging behavior.The note effectively communicates that discovered routes are merged with explicitly specified pages when auto-discovery is enabled.
72-88
: Documentation sections are comprehensive.The Automatic Static Route Discovery and Crawling Links sections provide clear guidance on how the feature works and what to expect. The exclusion list and the note about dynamic routes are helpful.
packages/start-plugin-core/src/prerender.ts (4)
85-107
: Redirect handling logic is sound.The implementation correctly:
- Follows internal redirects up to the configured limit
- Decrements the counter to prevent infinite loops
- Skips external redirects with a warning
- Returns the final response
The edge case where
maxRedirects
is exhausted is properly handled by the caller at lines 194-196, which logs a warning when a redirect response is returned with!res.ok
.
183-196
: Fetch and error handling implemented correctly.The code properly:
- Guards against undefined headers with nullish coalescing
- Passes the
maxRedirects
parameter consistently (plural form throughout)- Provides a specific warning when redirect limits are exhausted
- Throws an appropriate error for other failure cases
136-149
: Prerendered tracking improves accuracy.The introduction of the
prerendered
set (separate fromseen
) ensures the function returns only pages that were successfully written to disk, which is the correct semantic for the return value.
236-237
: Correct placement of prerendered tracking.Adding the page to
prerendered
after the successfulwriteFile
ensures that only pages that were actually written are counted, with failures properly excluded.e2e/react-start/basic/vite.config.ts (3)
6-6
: LGTM!The import follows the established pattern and is consistent with the existing
isSpaMode
import.
39-39
: LGTM!The conditional configuration follows the established pattern and enables proper test isolation by only activating prerender when
MODE=prerender
.
15-26
: Verify themaxRedirects
value and the filter matching approach.Based on examination of the codebase:
High redirect limit is intentional but unclear: The default
maxRedirects
in the prerender implementation is 5, but this configuration sets it to 100—20 times higher. While the routes in this test app include legitimate redirects (/redirect/$target/via-beforeLoad
,/redirect/$target/via-loader
), there's no comment explaining why such a high limit is needed. This warrants clarification.Filter matching is fragile: The filter excludes routes matching
/redirect
,/not-found/via-beforeLoad
, and/not-found/via-loader
using.includes()
. Currently, this works for the existing routes. However, this approach could accidentally exclude unintended routes if future paths contain these substrings (e.g., a hypothetical/my-redirect-page
would be unintentionally excluded). Consider using exact path matching or a more explicit exclusion strategy to prevent future issues.
Fixes #5455
Previously, when prerendering was enabled without specifying pages, only the root path (/) was prerendered plus whatever was crawled from the
/
ifcrawlLinks
is enabled. This change automatically discovers and prerenders all static routes.Changes
Core Prerendering Improvements
getPrerenderablePaths()
function that filters out:crawlLinks
is enabled then it will also be prerenderedE2E Testing
basic-prerendering
e2e testTechnical Details
GeneratorPlugin
to discover route structureisNonPath
, dynamic parameters, and component existenceExpected Behavior
When
prerender.enabled: true
&&prerender.autoStaticPathsDiscovery: true
(default: true) :This brings TanStack Start's prerendering behavior in line with Next.js where all static routes are automatically prerendered by default.
Testing
The new
basic-prerendering
e2e test verifies:Breaking Changes
None - this change is fully backward compatible. Existing page specifications continue to work exactly as before.
Migration Guide
No migration needed. Users who previously had to manually specify all static routes can now simply use:
Summary by CodeRabbit
New Features
Documentation
Tests