diff --git a/examples/react/basic-file-based/src/routes/posts.$postId.tsx b/examples/react/basic-file-based/src/routes/posts.$postId.tsx
index febb02ab2f..cded91ef96 100644
--- a/examples/react/basic-file-based/src/routes/posts.$postId.tsx
+++ b/examples/react/basic-file-based/src/routes/posts.$postId.tsx
@@ -5,7 +5,7 @@ import type { ErrorComponentProps } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => fetchPost(postId),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
notFoundComponent: () => {
return
Post not found
},
diff --git a/examples/react/basic-react-query-file-based/src/routes/posts.$postId.tsx b/examples/react/basic-react-query-file-based/src/routes/posts.$postId.tsx
index 78455fdcdf..4cf6beca88 100644
--- a/examples/react/basic-react-query-file-based/src/routes/posts.$postId.tsx
+++ b/examples/react/basic-react-query-file-based/src/routes/posts.$postId.tsx
@@ -20,7 +20,7 @@ export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
-export function PostErrorComponent({ error, reset }: ErrorComponentProps) {
+export function PostErrorComponent({ error }: ErrorComponentProps) {
const router = useRouter()
if (error instanceof PostNotFoundError) {
return
{error.message}
diff --git a/examples/react/basic-react-query/src/main.tsx b/examples/react/basic-react-query/src/main.tsx
index a5455491c0..0601c115e4 100644
--- a/examples/react/basic-react-query/src/main.tsx
+++ b/examples/react/basic-react-query/src/main.tsx
@@ -2,7 +2,6 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import {
ErrorComponent,
- type ErrorComponentProps,
Link,
Outlet,
RouterProvider,
@@ -20,6 +19,7 @@ import {
useSuspenseQuery,
} from '@tanstack/react-query'
import { NotFoundError, postQueryOptions, postsQueryOptions } from './posts'
+import type { ErrorComponentProps } from '@tanstack/react-router'
const rootRoute = createRootRouteWithContext<{
queryClient: QueryClient
@@ -122,7 +122,7 @@ const postRoute = createRoute({
component: PostRouteComponent,
})
-function PostErrorComponent({ error, reset }: ErrorComponentProps) {
+function PostErrorComponent({ error }: ErrorComponentProps) {
const router = useRouter()
if (error instanceof NotFoundError) {
return
{error.message}
diff --git a/examples/react/basic-ssr-file-based/src/routes/__root.tsx b/examples/react/basic-ssr-file-based/src/routes/__root.tsx
index 9424dc2259..97a87f8085 100644
--- a/examples/react/basic-ssr-file-based/src/routes/__root.tsx
+++ b/examples/react/basic-ssr-file-based/src/routes/__root.tsx
@@ -8,39 +8,41 @@ import { Meta, Scripts } from '@tanstack/start'
import type { RouterContext } from '../routerContext'
export const Route = createRootRouteWithContext
()({
- meta: () => [
- {
- title: 'TanStack Router SSR Basic File Based',
- },
- {
- charSet: 'UTF-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1.0',
- },
- ],
- scripts: () => [
- {
- src: 'https://cdn.tailwindcss.com',
- },
- {
- type: 'module',
- children: `import RefreshRuntime from "/@react-refresh"
-RefreshRuntime.injectIntoGlobalHook(window)
-window.$RefreshReg$ = () => {}
-window.$RefreshSig$ = () => (type) => type
-window.__vite_plugin_react_preamble_installed__ = true`,
- },
- {
- type: 'module',
- src: '/@vite/client',
- },
- {
- type: 'module',
- src: '/src/entry-client.tsx',
- },
- ],
+ head: () => ({
+ meta: [
+ {
+ title: 'TanStack Router SSR Basic File Based',
+ },
+ {
+ charSet: 'UTF-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1.0',
+ },
+ ],
+ scripts: [
+ {
+ src: 'https://cdn.tailwindcss.com',
+ },
+ {
+ type: 'module',
+ children: `import RefreshRuntime from "/@react-refresh"
+ RefreshRuntime.injectIntoGlobalHook(window)
+ window.$RefreshReg$ = () => {}
+ window.$RefreshSig$ = () => (type) => type
+ window.__vite_plugin_react_preamble_installed__ = true`,
+ },
+ {
+ type: 'module',
+ src: '/@vite/client',
+ },
+ {
+ type: 'module',
+ src: '/src/entry-client.tsx',
+ },
+ ],
+ }),
component: RootComponent,
})
diff --git a/examples/react/basic-ssr-file-based/src/routes/error.tsx b/examples/react/basic-ssr-file-based/src/routes/error.tsx
index 2b3599380f..52d42f2a99 100644
--- a/examples/react/basic-ssr-file-based/src/routes/error.tsx
+++ b/examples/react/basic-ssr-file-based/src/routes/error.tsx
@@ -10,7 +10,7 @@ export const Route = createFileRoute('/error')({
errorComponent: ({ error }) => {
return (
-
Caught: {(error as Error).message}
+
Caught: {error.message}
(This page has a 50% chance of throwing an error)
)
diff --git a/examples/react/basic-ssr-file-based/src/routes/posts.tsx b/examples/react/basic-ssr-file-based/src/routes/posts.tsx
index 33da97b194..3699478d0a 100644
--- a/examples/react/basic-ssr-file-based/src/routes/posts.tsx
+++ b/examples/react/basic-ssr-file-based/src/routes/posts.tsx
@@ -1,5 +1,5 @@
import * as React from 'react'
-import { createFileRoute, Link, Outlet } from '@tanstack/react-router'
+import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
export type PostType = {
id: string
@@ -14,7 +14,7 @@ export const Route = createFileRoute('/posts')({
setTimeout(r, 300 + Math.round(Math.random() * 300)),
)
return fetch('https://jsonplaceholder.typicode.com/posts')
- .then((d) => d.json() as Promise)
+ .then((d) => d.json() as Promise>)
.then((d) => d.slice(0, 10))
},
component: PostsComponent,
@@ -26,7 +26,7 @@ function PostsComponent() {
return (
- {posts?.map((post) => {
+ {posts.map((post) => {
return (
-
{
diff --git a/examples/react/basic-ssr-streaming-file-based/src/routes/__root.tsx b/examples/react/basic-ssr-streaming-file-based/src/routes/__root.tsx
index 272dd22eb5..e9eff8ee7a 100644
--- a/examples/react/basic-ssr-streaming-file-based/src/routes/__root.tsx
+++ b/examples/react/basic-ssr-streaming-file-based/src/routes/__root.tsx
@@ -9,39 +9,41 @@ import { Meta, Scripts } from '@tanstack/start'
import type { RouterContext } from '../routerContext'
export const Route = createRootRouteWithContext()({
- meta: () => [
- {
- title: 'TanStack Router SSR Basic File Based',
- },
- {
- charSet: 'UTF-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1.0',
- },
- ],
- scripts: () => [
- {
- src: 'https://cdn.tailwindcss.com',
- },
- {
- type: 'module',
- children: `import RefreshRuntime from "/@react-refresh"
-RefreshRuntime.injectIntoGlobalHook(window)
-window.$RefreshReg$ = () => {}
-window.$RefreshSig$ = () => (type) => type
-window.__vite_plugin_react_preamble_installed__ = true`,
- },
- {
- type: 'module',
- src: '/@vite/client',
- },
- {
- type: 'module',
- src: '/src/entry-client.tsx',
- },
- ],
+ head: () => ({
+ meta: [
+ {
+ title: 'TanStack Router SSR Basic File Based',
+ },
+ {
+ charSet: 'UTF-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1.0',
+ },
+ ],
+ scripts: [
+ {
+ src: 'https://cdn.tailwindcss.com',
+ },
+ {
+ type: 'module',
+ children: `import RefreshRuntime from "/@react-refresh"
+ RefreshRuntime.injectIntoGlobalHook(window)
+ window.$RefreshReg$ = () => {}
+ window.$RefreshSig$ = () => (type) => type
+ window.__vite_plugin_react_preamble_installed__ = true`,
+ },
+ {
+ type: 'module',
+ src: '/@vite/client',
+ },
+ {
+ type: 'module',
+ src: '/src/entry-client.tsx',
+ },
+ ],
+ }),
component: RootComponent,
})
diff --git a/examples/react/basic-ssr-streaming-file-based/src/routes/posts.tsx b/examples/react/basic-ssr-streaming-file-based/src/routes/posts.tsx
index 5dad9b0623..ad2b0082ad 100644
--- a/examples/react/basic-ssr-streaming-file-based/src/routes/posts.tsx
+++ b/examples/react/basic-ssr-streaming-file-based/src/routes/posts.tsx
@@ -1,5 +1,5 @@
import * as React from 'react'
-import { createFileRoute, Link, Outlet } from '@tanstack/react-router'
+import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
export type PostType = {
id: string
@@ -14,7 +14,7 @@ export const Route = createFileRoute('/posts')({
setTimeout(r, 300 + Math.round(Math.random() * 300)),
)
return fetch('https://jsonplaceholder.typicode.com/posts')
- .then((d) => d.json() as Promise)
+ .then((d) => d.json() as Promise>)
.then((d) => d.slice(0, 10))
},
component: PostsComponent,
@@ -26,7 +26,7 @@ function PostsComponent() {
return (
- {posts?.map((post) => {
+ {posts.map((post) => {
return (
-
This is the index
,
diff --git a/examples/react/basic-virtual-inside-file-based/src/routes/posts/details.tsx b/examples/react/basic-virtual-inside-file-based/src/routes/posts/details.tsx
index 948d52d6d6..6479bdf803 100644
--- a/examples/react/basic-virtual-inside-file-based/src/routes/posts/details.tsx
+++ b/examples/react/basic-virtual-inside-file-based/src/routes/posts/details.tsx
@@ -5,7 +5,7 @@ import type { ErrorComponentProps } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => fetchPost(postId),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
notFoundComponent: () => {
return Post not found
},
diff --git a/examples/react/basic/src/main.tsx b/examples/react/basic/src/main.tsx
index f75bdb8629..873374a010 100644
--- a/examples/react/basic/src/main.tsx
+++ b/examples/react/basic/src/main.tsx
@@ -1,7 +1,6 @@
import ReactDOM from 'react-dom/client'
import {
ErrorComponent,
- type ErrorComponentProps,
Link,
Outlet,
RouterProvider,
@@ -11,6 +10,7 @@ import {
} from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { NotFoundError, fetchPost, fetchPosts } from './posts'
+import type { ErrorComponentProps } from '@tanstack/react-router'
const rootRoute = createRootRoute({
component: RootComponent,
diff --git a/examples/react/kitchen-sink-file-based/src/routes/_auth.tsx b/examples/react/kitchen-sink-file-based/src/routes/_auth.tsx
index 30fdcf9f28..f4f3876f26 100644
--- a/examples/react/kitchen-sink-file-based/src/routes/_auth.tsx
+++ b/examples/react/kitchen-sink-file-based/src/routes/_auth.tsx
@@ -1,4 +1,3 @@
-import * as React from 'react'
import { createFileRoute, redirect } from '@tanstack/react-router'
import { auth } from '../utils/auth'
diff --git a/examples/react/router-monorepo-react-query/packages/app/src/main.tsx b/examples/react/router-monorepo-react-query/packages/app/src/main.tsx
index ffb2c00f4f..dc22c54020 100644
--- a/examples/react/router-monorepo-react-query/packages/app/src/main.tsx
+++ b/examples/react/router-monorepo-react-query/packages/app/src/main.tsx
@@ -2,7 +2,7 @@ import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'
import { QueryClientProvider } from '@tanstack/react-query'
-import { Outlet, queryClient, router } from '@router-mono-react-query/router'
+import { queryClient, router } from '@router-mono-react-query/router'
import {
PostErrorComponent,
PostIdComponent,
diff --git a/examples/react/router-monorepo-simple/packages/app/src/main.tsx b/examples/react/router-monorepo-simple/packages/app/src/main.tsx
index 74283c5c8b..e4bac0e6d9 100644
--- a/examples/react/router-monorepo-simple/packages/app/src/main.tsx
+++ b/examples/react/router-monorepo-simple/packages/app/src/main.tsx
@@ -26,6 +26,7 @@ function EmptyComponent() {
Object.entries(routerMap).forEach(([path, component]) => {
const foundRoute = router.routesById[path as RouterIds]
foundRoute.update({
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
component: component ?? EmptyComponent,
})
})
diff --git a/examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx
index f0ce51dc57..15f316681c 100644
--- a/examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx
+++ b/examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx
@@ -1,11 +1,11 @@
import {
ErrorComponent,
- ErrorComponentProps,
Link,
rootRouteId,
useMatch,
useRouter,
} from '@tanstack/react-router'
+import type { ErrorComponentProps } from '@tanstack/react-router'
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
const router = useRouter()
diff --git a/examples/react/start-basic-auth/app/routes/__root.tsx b/examples/react/start-basic-auth/app/routes/__root.tsx
index 3ab9c663b8..1b09411989 100644
--- a/examples/react/start-basic-auth/app/routes/__root.tsx
+++ b/examples/react/start-basic-auth/app/routes/__root.tsx
@@ -27,42 +27,44 @@ const fetchUser = createServerFn({ method: 'GET' }).handler(async () => {
})
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
beforeLoad: async () => {
const user = await fetchUser()
diff --git a/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx b/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx
index e4680c6070..039271bb89 100644
--- a/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx
+++ b/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx
@@ -5,7 +5,7 @@ import { fetchPost } from '~/utils/posts.js'
export const Route = createFileRoute('/_authed/posts/$postId')({
loader: ({ params: { postId } }) => fetchPost({ data: postId }),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return Post not found
diff --git a/examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx
index f0ce51dc57..15f316681c 100644
--- a/examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx
+++ b/examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx
@@ -1,11 +1,11 @@
import {
ErrorComponent,
- ErrorComponentProps,
Link,
rootRouteId,
useMatch,
useRouter,
} from '@tanstack/react-router'
+import type { ErrorComponentProps } from '@tanstack/react-router'
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
const router = useRouter()
diff --git a/examples/react/start-basic-react-query/app/routes/__root.tsx b/examples/react/start-basic-react-query/app/routes/__root.tsx
index 849d02e1ba..c916cbeda5 100644
--- a/examples/react/start-basic-react-query/app/routes/__root.tsx
+++ b/examples/react/start-basic-react-query/app/routes/__root.tsx
@@ -17,42 +17,44 @@ import { seo } from '~/utils/seo'
export const Route = createRootRouteWithContext<{
queryClient: QueryClient
}>()({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
errorComponent: (props) => {
return (
diff --git a/examples/react/start-basic-react-query/app/routes/posts.$postId.tsx b/examples/react/start-basic-react-query/app/routes/posts.$postId.tsx
index 546e3d2795..542a12a9f6 100644
--- a/examples/react/start-basic-react-query/app/routes/posts.$postId.tsx
+++ b/examples/react/start-basic-react-query/app/routes/posts.$postId.tsx
@@ -14,12 +14,10 @@ export const Route = createFileRoute('/posts/$postId')({
title: data.title,
}
},
- meta: ({ loaderData }) => [
- {
- title: loaderData.title,
- },
- ],
- errorComponent: PostErrorComponent as any,
+ head: ({ loaderData }) => ({
+ meta: loaderData ? [{ title: loaderData.title }] : undefined,
+ }),
+ errorComponent: PostErrorComponent,
notFoundComponent: () => {
return Post not found
},
diff --git a/examples/react/start-basic-react-query/app/routes/posts.tsx b/examples/react/start-basic-react-query/app/routes/posts.tsx
index 64600d15c4..b545663be2 100644
--- a/examples/react/start-basic-react-query/app/routes/posts.tsx
+++ b/examples/react/start-basic-react-query/app/routes/posts.tsx
@@ -6,7 +6,9 @@ export const Route = createFileRoute('/posts')({
loader: async ({ context }) => {
await context.queryClient.ensureQueryData(postsQueryOptions())
},
- meta: () => [{ title: 'Posts' }],
+ head: () => ({
+ meta: [{ title: 'Posts' }],
+ }),
component: PostsComponent,
})
diff --git a/examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx
index 219ba4771b..33f6475a55 100644
--- a/examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx
+++ b/examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx
@@ -13,12 +13,10 @@ export const Route = createFileRoute('/posts_/$postId/deep')({
title: data.title,
}
},
- meta: ({ loaderData }) => [
- {
- title: loaderData.title,
- },
- ],
- errorComponent: PostErrorComponent as any,
+ head: ({ loaderData }) => ({
+ meta: loaderData ? [{ title: loaderData.title }] : undefined,
+ }),
+ errorComponent: PostErrorComponent,
component: PostDeepComponent,
})
diff --git a/examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx
index f0ce51dc57..15f316681c 100644
--- a/examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx
+++ b/examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx
@@ -1,11 +1,11 @@
import {
ErrorComponent,
- ErrorComponentProps,
Link,
rootRouteId,
useMatch,
useRouter,
} from '@tanstack/react-router'
+import type { ErrorComponentProps } from '@tanstack/react-router'
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
const router = useRouter()
diff --git a/examples/react/start-basic-rsc/app/routes/__root.tsx b/examples/react/start-basic-rsc/app/routes/__root.tsx
index a938538aea..2e19225490 100644
--- a/examples/react/start-basic-rsc/app/routes/__root.tsx
+++ b/examples/react/start-basic-rsc/app/routes/__root.tsx
@@ -13,42 +13,44 @@ import appCss from '~/styles/app.css?url'
import { seo } from '~/utils/seo'
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
errorComponent: (props) => {
return (
diff --git a/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx b/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx
index c682378671..b857d05e06 100644
--- a/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx
+++ b/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx
@@ -29,7 +29,7 @@ const renderPost = createServerFn({ method: 'GET' })
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => renderPost({ data: postId }),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return Post not found
diff --git a/examples/react/start-basic-rsc/app/routes/posts.index.tsx b/examples/react/start-basic-rsc/app/routes/posts.index.tsx
index 1b491e46be..5b5f08f95b 100644
--- a/examples/react/start-basic-rsc/app/routes/posts.index.tsx
+++ b/examples/react/start-basic-rsc/app/routes/posts.index.tsx
@@ -1,6 +1,5 @@
import { createFileRoute } from '@tanstack/react-router'
-// @ts-ignore
export const Route = createFileRoute('/posts/')({
component: PostsIndexComponent,
})
diff --git a/examples/react/start-basic-rsc/app/routes/posts.tsx b/examples/react/start-basic-rsc/app/routes/posts.tsx
index eda2c4f0cf..1e0be42f75 100644
--- a/examples/react/start-basic-rsc/app/routes/posts.tsx
+++ b/examples/react/start-basic-rsc/app/routes/posts.tsx
@@ -1,4 +1,3 @@
-// import * as React from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn, renderRsc } from '@tanstack/start'
import { renderPosts } from '~/utils/renderPosts'
diff --git a/examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx
index b095d42294..13d368cf9c 100644
--- a/examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx
+++ b/examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx
@@ -1,10 +1,10 @@
-import { createFileRoute, Link } from '@tanstack/react-router'
-import { PostErrorComponent } from './posts.$postId'
+import { Link, createFileRoute } from '@tanstack/react-router'
import { fetchPost } from '../utils/posts'
+import { PostErrorComponent } from './posts.$postId'
export const Route = createFileRoute('/posts_/$postId/deep')({
loader: async ({ params: { postId } }) => fetchPost(postId),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostDeepComponent,
})
diff --git a/examples/react/start-basic/app/routeTree.gen.ts b/examples/react/start-basic/app/routeTree.gen.ts
index 22021a2af7..9f7ab8107b 100644
--- a/examples/react/start-basic/app/routeTree.gen.ts
+++ b/examples/react/start-basic/app/routeTree.gen.ts
@@ -21,10 +21,10 @@ import { Route as UsersIndexImport } from './routes/users.index'
import { Route as PostsIndexImport } from './routes/posts.index'
import { Route as UsersUserIdImport } from './routes/users.$userId'
import { Route as PostsPostIdImport } from './routes/posts.$postId'
-import { Route as LayoutTestLayoutTest2Import } from './routes/_layoutTest/_layoutTest-2'
+import { Route as LayoutLayout2Import } from './routes/_layout/_layout-2'
import { Route as PostsPostIdDeepImport } from './routes/posts_.$postId.deep'
-import { Route as LayoutTestLayoutTest2LayoutTestBImport } from './routes/_layoutTest/_layoutTest-2/layoutTest-b'
-import { Route as LayoutTestLayoutTest2LayoutTestAImport } from './routes/_layoutTest/_layoutTest-2/layoutTest-a'
+import { Route as LayoutLayout2LayoutBImport } from './routes/_layout/_layout-2/layout-b'
+import { Route as LayoutLayout2LayoutAImport } from './routes/_layout/_layout-2/layout-a'
// Create/Update Routes
@@ -87,9 +87,9 @@ const PostsPostIdRoute = PostsPostIdImport.update({
getParentRoute: () => PostsRoute,
} as any)
-const LayoutTestLayoutTest2Route = LayoutTestLayoutTest2Import.update({
- id: '/_layoutTest/_layoutTest-2',
- getParentRoute: () => rootRoute,
+const LayoutLayout2Route = LayoutLayout2Import.update({
+ id: '/_layout-2',
+ getParentRoute: () => LayoutRoute,
} as any)
const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({
@@ -98,19 +98,17 @@ const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({
getParentRoute: () => rootRoute,
} as any)
-const LayoutTestLayoutTest2LayoutTestBRoute =
- LayoutTestLayoutTest2LayoutTestBImport.update({
- id: '/layoutTest-b',
- path: '/layoutTest-b',
- getParentRoute: () => LayoutTestLayoutTest2Route,
- } as any)
+const LayoutLayout2LayoutBRoute = LayoutLayout2LayoutBImport.update({
+ id: '/layout-b',
+ path: '/layout-b',
+ getParentRoute: () => LayoutLayout2Route,
+} as any)
-const LayoutTestLayoutTest2LayoutTestARoute =
- LayoutTestLayoutTest2LayoutTestAImport.update({
- id: '/layoutTest-a',
- path: '/layoutTest-a',
- getParentRoute: () => LayoutTestLayoutTest2Route,
- } as any)
+const LayoutLayout2LayoutARoute = LayoutLayout2LayoutAImport.update({
+ id: '/layout-a',
+ path: '/layout-a',
+ getParentRoute: () => LayoutLayout2Route,
+} as any)
// Populate the FileRoutesByPath interface
@@ -158,12 +156,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof UsersImport
parentRoute: typeof rootRoute
}
- '/_layoutTest/_layoutTest-2': {
- id: '/_layoutTest/_layoutTest-2'
+ '/_layout/_layout-2': {
+ id: '/_layout/_layout-2'
path: ''
fullPath: ''
- preLoaderRoute: typeof LayoutTestLayoutTest2Import
- parentRoute: typeof rootRoute
+ preLoaderRoute: typeof LayoutLayout2Import
+ parentRoute: typeof LayoutImport
}
'/posts/$postId': {
id: '/posts/$postId'
@@ -193,19 +191,19 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof UsersIndexImport
parentRoute: typeof UsersImport
}
- '/_layoutTest/_layoutTest-2/layoutTest-a': {
- id: '/_layoutTest/_layoutTest-2/layoutTest-a'
- path: '/layoutTest-a'
- fullPath: '/layoutTest-a'
- preLoaderRoute: typeof LayoutTestLayoutTest2LayoutTestAImport
- parentRoute: typeof LayoutTestLayoutTest2Import
+ '/_layout/_layout-2/layout-a': {
+ id: '/_layout/_layout-2/layout-a'
+ path: '/layout-a'
+ fullPath: '/layout-a'
+ preLoaderRoute: typeof LayoutLayout2LayoutAImport
+ parentRoute: typeof LayoutLayout2Import
}
- '/_layoutTest/_layoutTest-2/layoutTest-b': {
- id: '/_layoutTest/_layoutTest-2/layoutTest-b'
- path: '/layoutTest-b'
- fullPath: '/layoutTest-b'
- preLoaderRoute: typeof LayoutTestLayoutTest2LayoutTestBImport
- parentRoute: typeof LayoutTestLayoutTest2Import
+ '/_layout/_layout-2/layout-b': {
+ id: '/_layout/_layout-2/layout-b'
+ path: '/layout-b'
+ fullPath: '/layout-b'
+ preLoaderRoute: typeof LayoutLayout2LayoutBImport
+ parentRoute: typeof LayoutLayout2Import
}
'/posts_/$postId/deep': {
id: '/posts_/$postId/deep'
@@ -219,6 +217,31 @@ declare module '@tanstack/react-router' {
// Create and export the route tree
+interface LayoutLayout2RouteChildren {
+ LayoutLayout2LayoutARoute: typeof LayoutLayout2LayoutARoute
+ LayoutLayout2LayoutBRoute: typeof LayoutLayout2LayoutBRoute
+}
+
+const LayoutLayout2RouteChildren: LayoutLayout2RouteChildren = {
+ LayoutLayout2LayoutARoute: LayoutLayout2LayoutARoute,
+ LayoutLayout2LayoutBRoute: LayoutLayout2LayoutBRoute,
+}
+
+const LayoutLayout2RouteWithChildren = LayoutLayout2Route._addFileChildren(
+ LayoutLayout2RouteChildren,
+)
+
+interface LayoutRouteChildren {
+ LayoutLayout2Route: typeof LayoutLayout2RouteWithChildren
+}
+
+const LayoutRouteChildren: LayoutRouteChildren = {
+ LayoutLayout2Route: LayoutLayout2RouteWithChildren,
+}
+
+const LayoutRouteWithChildren =
+ LayoutRoute._addFileChildren(LayoutRouteChildren)
+
interface PostsRouteChildren {
PostsPostIdRoute: typeof PostsPostIdRoute
PostsIndexRoute: typeof PostsIndexRoute
@@ -243,24 +266,9 @@ const UsersRouteChildren: UsersRouteChildren = {
const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren)
-interface LayoutTestLayoutTest2RouteChildren {
- LayoutTestLayoutTest2LayoutTestARoute: typeof LayoutTestLayoutTest2LayoutTestARoute
- LayoutTestLayoutTest2LayoutTestBRoute: typeof LayoutTestLayoutTest2LayoutTestBRoute
-}
-
-const LayoutTestLayoutTest2RouteChildren: LayoutTestLayoutTest2RouteChildren = {
- LayoutTestLayoutTest2LayoutTestARoute: LayoutTestLayoutTest2LayoutTestARoute,
- LayoutTestLayoutTest2LayoutTestBRoute: LayoutTestLayoutTest2LayoutTestBRoute,
-}
-
-const LayoutTestLayoutTest2RouteWithChildren =
- LayoutTestLayoutTest2Route._addFileChildren(
- LayoutTestLayoutTest2RouteChildren,
- )
-
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
- '': typeof LayoutTestLayoutTest2RouteWithChildren
+ '': typeof LayoutLayout2RouteWithChildren
'/deferred': typeof DeferredRoute
'/posts': typeof PostsRouteWithChildren
'/redirect': typeof RedirectRoute
@@ -269,40 +277,40 @@ export interface FileRoutesByFullPath {
'/users/$userId': typeof UsersUserIdRoute
'/posts/': typeof PostsIndexRoute
'/users/': typeof UsersIndexRoute
- '/layoutTest-a': typeof LayoutTestLayoutTest2LayoutTestARoute
- '/layoutTest-b': typeof LayoutTestLayoutTest2LayoutTestBRoute
+ '/layout-a': typeof LayoutLayout2LayoutARoute
+ '/layout-b': typeof LayoutLayout2LayoutBRoute
'/posts/$postId/deep': typeof PostsPostIdDeepRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
- '': typeof LayoutTestLayoutTest2RouteWithChildren
+ '': typeof LayoutLayout2RouteWithChildren
'/deferred': typeof DeferredRoute
'/redirect': typeof RedirectRoute
'/posts/$postId': typeof PostsPostIdRoute
'/users/$userId': typeof UsersUserIdRoute
'/posts': typeof PostsIndexRoute
'/users': typeof UsersIndexRoute
- '/layoutTest-a': typeof LayoutTestLayoutTest2LayoutTestARoute
- '/layoutTest-b': typeof LayoutTestLayoutTest2LayoutTestBRoute
+ '/layout-a': typeof LayoutLayout2LayoutARoute
+ '/layout-b': typeof LayoutLayout2LayoutBRoute
'/posts/$postId/deep': typeof PostsPostIdDeepRoute
}
export interface FileRoutesById {
__root__: typeof rootRoute
'/': typeof IndexRoute
- '/_layout': typeof LayoutRoute
+ '/_layout': typeof LayoutRouteWithChildren
'/deferred': typeof DeferredRoute
'/posts': typeof PostsRouteWithChildren
'/redirect': typeof RedirectRoute
'/users': typeof UsersRouteWithChildren
- '/_layoutTest/_layoutTest-2': typeof LayoutTestLayoutTest2RouteWithChildren
+ '/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren
'/posts/$postId': typeof PostsPostIdRoute
'/users/$userId': typeof UsersUserIdRoute
'/posts/': typeof PostsIndexRoute
'/users/': typeof UsersIndexRoute
- '/_layoutTest/_layoutTest-2/layoutTest-a': typeof LayoutTestLayoutTest2LayoutTestARoute
- '/_layoutTest/_layoutTest-2/layoutTest-b': typeof LayoutTestLayoutTest2LayoutTestBRoute
+ '/_layout/_layout-2/layout-a': typeof LayoutLayout2LayoutARoute
+ '/_layout/_layout-2/layout-b': typeof LayoutLayout2LayoutBRoute
'/posts_/$postId/deep': typeof PostsPostIdDeepRoute
}
@@ -319,8 +327,8 @@ export interface FileRouteTypes {
| '/users/$userId'
| '/posts/'
| '/users/'
- | '/layoutTest-a'
- | '/layoutTest-b'
+ | '/layout-a'
+ | '/layout-b'
| '/posts/$postId/deep'
fileRoutesByTo: FileRoutesByTo
to:
@@ -332,8 +340,8 @@ export interface FileRouteTypes {
| '/users/$userId'
| '/posts'
| '/users'
- | '/layoutTest-a'
- | '/layoutTest-b'
+ | '/layout-a'
+ | '/layout-b'
| '/posts/$postId/deep'
id:
| '__root__'
@@ -343,36 +351,34 @@ export interface FileRouteTypes {
| '/posts'
| '/redirect'
| '/users'
- | '/_layoutTest/_layoutTest-2'
+ | '/_layout/_layout-2'
| '/posts/$postId'
| '/users/$userId'
| '/posts/'
| '/users/'
- | '/_layoutTest/_layoutTest-2/layoutTest-a'
- | '/_layoutTest/_layoutTest-2/layoutTest-b'
+ | '/_layout/_layout-2/layout-a'
+ | '/_layout/_layout-2/layout-b'
| '/posts_/$postId/deep'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
- LayoutRoute: typeof LayoutRoute
+ LayoutRoute: typeof LayoutRouteWithChildren
DeferredRoute: typeof DeferredRoute
PostsRoute: typeof PostsRouteWithChildren
RedirectRoute: typeof RedirectRoute
UsersRoute: typeof UsersRouteWithChildren
- LayoutTestLayoutTest2Route: typeof LayoutTestLayoutTest2RouteWithChildren
PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
- LayoutRoute: LayoutRoute,
+ LayoutRoute: LayoutRouteWithChildren,
DeferredRoute: DeferredRoute,
PostsRoute: PostsRouteWithChildren,
RedirectRoute: RedirectRoute,
UsersRoute: UsersRouteWithChildren,
- LayoutTestLayoutTest2Route: LayoutTestLayoutTest2RouteWithChildren,
PostsPostIdDeepRoute: PostsPostIdDeepRoute,
}
@@ -392,7 +398,6 @@ export const routeTree = rootRoute
"/posts",
"/redirect",
"/users",
- "/_layoutTest/_layoutTest-2",
"/posts_/$postId/deep"
]
},
@@ -400,7 +405,10 @@ export const routeTree = rootRoute
"filePath": "index.tsx"
},
"/_layout": {
- "filePath": "_layout.tsx"
+ "filePath": "_layout.tsx",
+ "children": [
+ "/_layout/_layout-2"
+ ]
},
"/deferred": {
"filePath": "deferred.tsx"
@@ -422,11 +430,12 @@ export const routeTree = rootRoute
"/users/"
]
},
- "/_layoutTest/_layoutTest-2": {
- "filePath": "_layoutTest/_layoutTest-2.tsx",
+ "/_layout/_layout-2": {
+ "filePath": "_layout/_layout-2.tsx",
+ "parent": "/_layout",
"children": [
- "/_layoutTest/_layoutTest-2/layoutTest-a",
- "/_layoutTest/_layoutTest-2/layoutTest-b"
+ "/_layout/_layout-2/layout-a",
+ "/_layout/_layout-2/layout-b"
]
},
"/posts/$postId": {
@@ -445,13 +454,13 @@ export const routeTree = rootRoute
"filePath": "users.index.tsx",
"parent": "/users"
},
- "/_layoutTest/_layoutTest-2/layoutTest-a": {
- "filePath": "_layoutTest/_layoutTest-2/layoutTest-a.tsx",
- "parent": "/_layoutTest/_layoutTest-2"
+ "/_layout/_layout-2/layout-a": {
+ "filePath": "_layout/_layout-2/layout-a.tsx",
+ "parent": "/_layout/_layout-2"
},
- "/_layoutTest/_layoutTest-2/layoutTest-b": {
- "filePath": "_layoutTest/_layoutTest-2/layoutTest-b.tsx",
- "parent": "/_layoutTest/_layoutTest-2"
+ "/_layout/_layout-2/layout-b": {
+ "filePath": "_layout/_layout-2/layout-b.tsx",
+ "parent": "/_layout/_layout-2"
},
"/posts_/$postId/deep": {
"filePath": "posts_.$postId.deep.tsx"
diff --git a/examples/react/start-basic/app/routes/__root.tsx b/examples/react/start-basic/app/routes/__root.tsx
index eb004a7c08..a2376f8364 100644
--- a/examples/react/start-basic/app/routes/__root.tsx
+++ b/examples/react/start-basic/app/routes/__root.tsx
@@ -13,42 +13,44 @@ import appCss from '~/styles/app.css?url'
import { seo } from '~/utils/seo'
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
errorComponent: (props) => {
return (
diff --git a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2.tsx b/examples/react/start-basic/app/routes/_layout/_layout-2.tsx
similarity index 90%
rename from examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2.tsx
rename to examples/react/start-basic/app/routes/_layout/_layout-2.tsx
index 42ec4ec5b7..3b7dbf2903 100644
--- a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2.tsx
+++ b/examples/react/start-basic/app/routes/_layout/_layout-2.tsx
@@ -1,6 +1,6 @@
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
-export const Route = createFileRoute('/_layoutTest/_layoutTest-2')({
+export const Route = createFileRoute('/_layout/_layout-2')({
component: LayoutComponent,
})
diff --git a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-a.tsx b/examples/react/start-basic/app/routes/_layout/_layout-2/layout-a.tsx
similarity index 50%
rename from examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-a.tsx
rename to examples/react/start-basic/app/routes/_layout/_layout-2/layout-a.tsx
index 85a4797b98..61e19b4d9f 100644
--- a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-a.tsx
+++ b/examples/react/start-basic/app/routes/_layout/_layout-2/layout-a.tsx
@@ -1,10 +1,8 @@
import { createFileRoute } from '@tanstack/react-router'
-export const Route = createFileRoute('/_layoutTest/_layoutTest-2/layoutTest-a')(
- {
- component: LayoutAComponent,
- },
-)
+export const Route = createFileRoute('/_layout/_layout-2/layout-a')({
+ component: LayoutAComponent,
+})
function LayoutAComponent() {
return I'm layout A!
diff --git a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-b.tsx b/examples/react/start-basic/app/routes/_layout/_layout-2/layout-b.tsx
similarity index 50%
rename from examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-b.tsx
rename to examples/react/start-basic/app/routes/_layout/_layout-2/layout-b.tsx
index 6cf55f5e8d..cceed1fb9a 100644
--- a/examples/react/start-basic/app/routes/_layoutTest/_layoutTest-2/layoutTest-b.tsx
+++ b/examples/react/start-basic/app/routes/_layout/_layout-2/layout-b.tsx
@@ -1,10 +1,8 @@
import { createFileRoute } from '@tanstack/react-router'
-export const Route = createFileRoute('/_layoutTest/_layoutTest-2/layoutTest-b')(
- {
- component: LayoutBComponent,
- },
-)
+export const Route = createFileRoute('/_layout/_layout-2/layout-b')({
+ component: LayoutBComponent,
+})
function LayoutBComponent() {
return I'm layout B!
diff --git a/examples/react/start-basic/app/routes/posts.$postId.tsx b/examples/react/start-basic/app/routes/posts.$postId.tsx
index 63cd7f8731..0d4d2de8eb 100644
--- a/examples/react/start-basic/app/routes/posts.$postId.tsx
+++ b/examples/react/start-basic/app/routes/posts.$postId.tsx
@@ -5,7 +5,7 @@ import { NotFound } from '~/components/NotFound'
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params: { postId } }) => fetchPost({ data: postId }),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return Post not found
diff --git a/examples/react/start-basic/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic/app/routes/posts_.$postId.deep.tsx
index 148223c8df..a1cad68409 100644
--- a/examples/react/start-basic/app/routes/posts_.$postId.deep.tsx
+++ b/examples/react/start-basic/app/routes/posts_.$postId.deep.tsx
@@ -7,7 +7,7 @@ export const Route = createFileRoute('/posts_/$postId/deep')({
fetchPost({
data: postId,
}),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostDeepComponent,
})
diff --git a/examples/react/start-basic/app/routes/users.$userId.tsx b/examples/react/start-basic/app/routes/users.$userId.tsx
index 573377c758..df3f569146 100644
--- a/examples/react/start-basic/app/routes/users.$userId.tsx
+++ b/examples/react/start-basic/app/routes/users.$userId.tsx
@@ -1,7 +1,8 @@
import { ErrorComponent, createFileRoute } from '@tanstack/react-router'
import axios from 'redaxios'
import type { ErrorComponentProps } from '@tanstack/react-router'
-import { DEPLOY_URL, type User } from '~/utils/users'
+import type { User } from '~/utils/users'
+import { DEPLOY_URL } from '~/utils/users'
import { NotFound } from '~/components/NotFound'
export const Route = createFileRoute('/users/$userId')({
diff --git a/examples/react/start-clerk-basic/app/routes/__root.tsx b/examples/react/start-clerk-basic/app/routes/__root.tsx
index db877d6e11..ffcca2b011 100644
--- a/examples/react/start-clerk-basic/app/routes/__root.tsx
+++ b/examples/react/start-clerk-basic/app/routes/__root.tsx
@@ -30,37 +30,39 @@ const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => {
})
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
beforeLoad: async () => {
const { user } = await fetchClerkAuth()
diff --git a/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx b/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx
index e4680c6070..039271bb89 100644
--- a/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx
+++ b/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx
@@ -5,7 +5,7 @@ import { fetchPost } from '~/utils/posts.js'
export const Route = createFileRoute('/_authed/posts/$postId')({
loader: ({ params: { postId } }) => fetchPost({ data: postId }),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return Post not found
diff --git a/examples/react/start-convex-trellaux/app/components/Column.tsx b/examples/react/start-convex-trellaux/app/components/Column.tsx
index 220482da64..6f248103df 100644
--- a/examples/react/start-convex-trellaux/app/components/Column.tsx
+++ b/examples/react/start-convex-trellaux/app/components/Column.tsx
@@ -3,7 +3,7 @@ import invariant from 'tiny-invariant'
import { twMerge } from 'tailwind-merge'
import { flushSync } from 'react-dom'
-import { CONTENT_TYPES, type RenderedItem } from '../types'
+import { CONTENT_TYPES } from '../types'
import { Icon } from '../icons/icons'
import {
useDeleteColumnMutation,
@@ -13,6 +13,7 @@ import {
import { EditableText } from './EditableText'
import { NewCard } from './NewCard'
import { Card } from './Card'
+import type { RenderedItem } from '../types'
interface ColumnProps {
name: string
diff --git a/examples/react/start-convex-trellaux/app/routes/__root.tsx b/examples/react/start-convex-trellaux/app/routes/__root.tsx
index e5d97fa7fc..c0f06fa36f 100644
--- a/examples/react/start-convex-trellaux/app/routes/__root.tsx
+++ b/examples/react/start-convex-trellaux/app/routes/__root.tsx
@@ -21,42 +21,44 @@ import { Loader } from '~/components/Loader'
export const Route = createRootRouteWithContext<{
queryClient: QueryClient
}>()({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
errorComponent: (props) => {
return (
diff --git a/examples/react/start-counter/app/client.tsx b/examples/react/start-counter/app/client.tsx
index 8d07d8bac1..b14d8aac68 100644
--- a/examples/react/start-counter/app/client.tsx
+++ b/examples/react/start-counter/app/client.tsx
@@ -1,4 +1,3 @@
-// app/client.tsx
///
import { hydrateRoot } from 'react-dom/client'
import { StartClient } from '@tanstack/start'
@@ -6,4 +5,4 @@ import { createRouter } from './router'
const router = createRouter()
-hydrateRoot(document!, )
+hydrateRoot(document, )
diff --git a/examples/react/start-counter/app/router.tsx b/examples/react/start-counter/app/router.tsx
index dc640c5f4c..d0e2297dce 100644
--- a/examples/react/start-counter/app/router.tsx
+++ b/examples/react/start-counter/app/router.tsx
@@ -1,4 +1,3 @@
-// app/router.tsx
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
diff --git a/examples/react/start-counter/app/routes/__root.tsx b/examples/react/start-counter/app/routes/__root.tsx
index 34ed08e02c..5a48b25d39 100644
--- a/examples/react/start-counter/app/routes/__root.tsx
+++ b/examples/react/start-counter/app/routes/__root.tsx
@@ -1,22 +1,26 @@
-// app/routes/__root.tsx
-import { createRootRoute } from '@tanstack/react-router'
-import { Outlet, ScrollRestoration } from '@tanstack/react-router'
-import { Meta, Scripts } from '@tanstack/start'
import * as React from 'react'
+import {
+ Outlet,
+ ScrollRestoration,
+ createRootRoute,
+} from '@tanstack/react-router'
+import { Meta, Scripts } from '@tanstack/start'
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- {
- title: 'TanStack Start Starter',
- },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ {
+ title: 'TanStack Start Starter',
+ },
+ ],
+ }),
component: RootComponent,
})
diff --git a/examples/react/start-counter/app/routes/index.tsx b/examples/react/start-counter/app/routes/index.tsx
index 3fc16b6677..6a41044351 100644
--- a/examples/react/start-counter/app/routes/index.tsx
+++ b/examples/react/start-counter/app/routes/index.tsx
@@ -1,4 +1,3 @@
-// app/routes/index.tsx
import * as fs from 'node:fs'
import { createFileRoute, useRouter } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/start'
diff --git a/examples/react/start-counter/app/ssr.tsx b/examples/react/start-counter/app/ssr.tsx
index c74eeaedc7..f2d33f9030 100644
--- a/examples/react/start-counter/app/ssr.tsx
+++ b/examples/react/start-counter/app/ssr.tsx
@@ -1,4 +1,3 @@
-// app/ssr.tsx
///
import {
createStartHandler,
diff --git a/examples/react/start-supabase-basic/app.config.ts b/examples/react/start-supabase-basic/app.config.ts
index a1ee0f2776..732f04eabe 100644
--- a/examples/react/start-supabase-basic/app.config.ts
+++ b/examples/react/start-supabase-basic/app.config.ts
@@ -1,3 +1,12 @@
import { defineConfig } from '@tanstack/start/config'
+import tsConfigPaths from 'vite-tsconfig-paths'
-export default defineConfig({})
+export default defineConfig({
+ vite: {
+ plugins: [
+ tsConfigPaths({
+ projects: ['./tsconfig.json'],
+ }),
+ ],
+ },
+})
diff --git a/examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx b/examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx
index e646acbd45..e14ef8d6c1 100644
--- a/examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx
+++ b/examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx
@@ -1,12 +1,11 @@
+import * as React from 'react'
import {
ErrorComponent,
Link,
rootRouteId,
- // ErrorComponentProps,
useMatch,
useRouter,
} from '@tanstack/react-router'
-import * as React from 'react'
import type { ErrorComponentProps } from '@tanstack/react-router'
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
diff --git a/examples/react/start-supabase-basic/app/routes/__root.tsx b/examples/react/start-supabase-basic/app/routes/__root.tsx
index a4b1784ca9..184c977f68 100644
--- a/examples/react/start-supabase-basic/app/routes/__root.tsx
+++ b/examples/react/start-supabase-basic/app/routes/__root.tsx
@@ -15,7 +15,7 @@ import { getSupabaseServerClient } from '../utils/supabase'
const fetchUser = createServerFn({ method: 'GET' }).handler(async () => {
const supabase = await getSupabaseServerClient()
- const { data, error } = await supabase.auth.getUser()
+ const { data, error: _error } = await supabase.auth.getUser()
if (!data.user?.email) {
return null
@@ -25,42 +25,44 @@ const fetchUser = createServerFn({ method: 'GET' }).handler(async () => {
})
export const Route = createRootRoute({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
beforeLoad: async () => {
const user = await fetchUser()
diff --git a/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx b/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx
index 87d52ffcc6..4dd11756a8 100644
--- a/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx
+++ b/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx
@@ -1,11 +1,11 @@
import { ErrorComponent, createFileRoute } from '@tanstack/react-router'
-import { NotFound } from '../../components/NotFound'
-import { fetchPost } from '../../utils/posts'
import type { ErrorComponentProps } from '@tanstack/react-router'
+import { NotFound } from '~/components/NotFound'
+import { fetchPost } from '~/utils/posts'
export const Route = createFileRoute('/_authed/posts/$postId')({
loader: ({ params: { postId } }) => fetchPost({ data: postId }),
- errorComponent: PostErrorComponent as any,
+ errorComponent: PostErrorComponent,
component: PostComponent,
notFoundComponent: () => {
return Post not found
diff --git a/examples/react/start-supabase-basic/package.json b/examples/react/start-supabase-basic/package.json
index b6e2da2723..97a679cb4e 100644
--- a/examples/react/start-supabase-basic/package.json
+++ b/examples/react/start-supabase-basic/package.json
@@ -28,6 +28,7 @@
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.14",
- "typescript": "^5.6.2"
+ "typescript": "^5.6.2",
+ "vite-tsconfig-paths": "^5.1.2"
}
}
diff --git a/examples/react/start-supabase-basic/tailwind.config.ts b/examples/react/start-supabase-basic/tailwind.config.ts
deleted file mode 100644
index d0253e59a8..0000000000
--- a/examples/react/start-supabase-basic/tailwind.config.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type { Config } from 'tailwindcss'
-
-export default {
- content: [],
- theme: {
- extend: {},
- },
- plugins: [],
-} satisfies Config
diff --git a/examples/react/start-trellaux/app/components/Board.tsx b/examples/react/start-trellaux/app/components/Board.tsx
index 5c7f388e40..1fe1179abf 100644
--- a/examples/react/start-trellaux/app/components/Board.tsx
+++ b/examples/react/start-trellaux/app/components/Board.tsx
@@ -2,9 +2,9 @@ import { useCallback, useMemo, useRef } from 'react'
import invariant from 'tiny-invariant'
import { useSuspenseQuery } from '@tanstack/react-query'
import { boardQueries, useUpdateBoardMutation } from '../queries.js'
-import { type Column } from '../db/schema.js'
import { NewColumn } from './NewColumn.js'
import { Column as ColumnComponent } from './Column.js'
+import type { Column } from '../db/schema.js'
import { EditableText } from '~/components/EditableText.js'
export function Board({ boardId }: { boardId: string }) {
diff --git a/examples/react/start-trellaux/app/components/Column.tsx b/examples/react/start-trellaux/app/components/Column.tsx
index 220482da64..6f248103df 100644
--- a/examples/react/start-trellaux/app/components/Column.tsx
+++ b/examples/react/start-trellaux/app/components/Column.tsx
@@ -3,7 +3,7 @@ import invariant from 'tiny-invariant'
import { twMerge } from 'tailwind-merge'
import { flushSync } from 'react-dom'
-import { CONTENT_TYPES, type RenderedItem } from '../types'
+import { CONTENT_TYPES } from '../types'
import { Icon } from '../icons/icons'
import {
useDeleteColumnMutation,
@@ -13,6 +13,7 @@ import {
import { EditableText } from './EditableText'
import { NewCard } from './NewCard'
import { Card } from './Card'
+import type { RenderedItem } from '../types'
interface ColumnProps {
name: string
diff --git a/examples/react/start-trellaux/app/components/NewColumn.tsx b/examples/react/start-trellaux/app/components/NewColumn.tsx
index 52e250b781..34a024a86a 100644
--- a/examples/react/start-trellaux/app/components/NewColumn.tsx
+++ b/examples/react/start-trellaux/app/components/NewColumn.tsx
@@ -3,7 +3,6 @@ import invariant from 'tiny-invariant'
import { Icon } from '../icons/icons'
import { useCreateColumnMutation } from '../queries'
-import { newColumnSchema } from '../db/schema'
import { CancelButton } from '~/components/CancelButton'
import { SaveButton } from '~/components/SaveButton'
diff --git a/examples/react/start-trellaux/app/routes/__root.tsx b/examples/react/start-trellaux/app/routes/__root.tsx
index e5d97fa7fc..c0f06fa36f 100644
--- a/examples/react/start-trellaux/app/routes/__root.tsx
+++ b/examples/react/start-trellaux/app/routes/__root.tsx
@@ -21,42 +21,44 @@ import { Loader } from '~/components/Loader'
export const Route = createRootRouteWithContext<{
queryClient: QueryClient
}>()({
- meta: () => [
- {
- charSet: 'utf-8',
- },
- {
- name: 'viewport',
- content: 'width=device-width, initial-scale=1',
- },
- ...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. `,
- }),
- ],
- links: () => [
- { rel: 'stylesheet', href: appCss },
- {
- rel: 'apple-touch-icon',
- sizes: '180x180',
- href: '/apple-touch-icon.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '32x32',
- href: '/favicon-32x32.png',
- },
- {
- rel: 'icon',
- type: 'image/png',
- sizes: '16x16',
- href: '/favicon-16x16.png',
- },
- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
- { rel: 'icon', href: '/favicon.ico' },
- ],
+ head: () => ({
+ meta: [
+ {
+ charSet: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...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. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ }),
errorComponent: (props) => {
return (
diff --git a/packages/react-router/src/route.ts b/packages/react-router/src/route.ts
index 701de16bae..7be86a89cb 100644
--- a/packages/react-router/src/route.ts
+++ b/packages/react-router/src/route.ts
@@ -434,7 +434,10 @@ export interface UpdatableRouteOptions<
TLoaderDeps
>,
) => void
- meta?: (ctx: {
+ headers?: (ctx: {
+ loaderData: ResolveLoaderData
+ }) => Record
+ head?: (ctx: {
matches: Array<
RouteMatch<
TRouteId,
@@ -466,13 +469,12 @@ export interface UpdatableRouteOptions<
TLoaderDeps
>
params: ResolveAllParamsFromParent
- loaderData: ResolveLoaderData
- }) => Array
- links?: () => Array
- scripts?: () => Array
- headers?: (ctx: {
- loaderData: ResolveLoaderData
- }) => Record
+ loaderData: ResolveLoaderData | undefined
+ }) => {
+ links?: Array | undefined
+ scripts?: Array | undefined
+ meta?: Array | undefined
+ }
ssr?: boolean
}
diff --git a/packages/react-router/src/router.ts b/packages/react-router/src/router.ts
index 54a7fd448b..20c33ec42a 100644
--- a/packages/react-router/src/router.ts
+++ b/packages/react-router/src/router.ts
@@ -1298,25 +1298,30 @@ export class Router<
: loaderDeps,
invalid: false,
preload: false,
- links: route.options.links?.(),
- scripts: route.options.scripts?.(),
+ links: undefined,
+ scripts: undefined,
+ meta: undefined,
staticData: route.options.staticData || {},
loadPromise: createControlledPromise(),
fullPath: route.fullPath,
}
}
- // If it's already a success, update the meta and headers
+ const headFnContent = route.options.head?.({
+ matches,
+ match,
+ params: match.params,
+ loaderData: match.loaderData ?? undefined,
+ })
+
+ match.links = headFnContent?.links
+ match.scripts = headFnContent?.scripts
+ match.meta = headFnContent?.meta
+
+ // If it's already a success, update the headers
// These may get updated again if the match is refreshed
// due to being stale
if (match.status === 'success') {
- match.meta = route.options.meta?.({
- matches,
- match,
- params: match.params,
- loaderData: match.loaderData,
- })
-
match.headers = route.options.headers?.({
loaderData: match.loaderData,
})
@@ -2516,12 +2521,13 @@ export class Router<
await potentialPendingMinPromise()
- const meta = route.options.meta?.({
+ const headFnContent = route.options.head?.({
matches,
match: this.getMatch(matchId)!,
params: this.getMatch(matchId)!.params,
loaderData,
})
+ const meta = headFnContent?.meta
const headers = route.options.headers?.({
loaderData,
diff --git a/packages/start/src/client/serialization.tsx b/packages/start/src/client/serialization.tsx
index 2f0091264a..067c18a20f 100644
--- a/packages/start/src/client/serialization.tsx
+++ b/packages/start/src/client/serialization.tsx
@@ -111,20 +111,17 @@ export function afterHydrate({ router }: { router: AnyRouter }) {
}
}
- const meta =
- match.status === 'success'
- ? route.options.meta?.({
- matches: router.state.matches,
- match,
- params: match.params,
- loaderData: match.loaderData,
- })
- : undefined
+ const headFnContent = route.options.head?.({
+ matches: router.state.matches,
+ match,
+ params: match.params,
+ loaderData: match.loaderData,
+ })
Object.assign(match, {
- meta,
- links: route.options.links?.(),
- scripts: route.options.scripts?.(),
+ meta: headFnContent?.meta,
+ links: headFnContent?.links,
+ scripts: headFnContent?.scripts,
})
})
}
diff --git a/packages/start/src/client/tests/index.test.tsx b/packages/start/src/client/tests/index.test.tsx
index b973d55cc5..82ebf9bb88 100644
--- a/packages/start/src/client/tests/index.test.tsx
+++ b/packages/start/src/client/tests/index.test.tsx
@@ -17,14 +17,18 @@ describe('ssr scripts', () => {
test('it works', async () => {
const rootRoute = createRootRoute({
// loader: () => new Promise((r) => setTimeout(r, 1)),
- scripts: () => [
- {
- src: 'script.js',
- },
- {
- src: 'script2.js',
- },
- ],
+ head: () => {
+ return {
+ scripts: [
+ {
+ src: 'script.js',
+ },
+ {
+ src: 'script2.js',
+ },
+ ],
+ }
+ },
component: () => {
return
},
@@ -34,11 +38,15 @@ describe('ssr scripts', () => {
path: '/',
getParentRoute: () => rootRoute,
// loader: () => new Promise((r) => setTimeout(r, 2)),
- scripts: () => [
- {
- src: 'script3.js',
- },
- ],
+ head: () => {
+ return {
+ scripts: [
+ {
+ src: 'script3.js',
+ },
+ ],
+ }
+ },
})
const router = createRouter({
@@ -77,19 +85,27 @@ describe('ssr meta', () => {
new Promise((r) => setTimeout(r, 1)).then(() => ({
description: 'Root',
})),
- meta: ({ loaderData }) => [
- {
- title: 'Root',
- },
- {
- name: 'description',
- content: loaderData.description,
- },
- {
- name: 'image',
- content: 'image.jpg',
- },
- ],
+ head: ({ loaderData }) => {
+ if (!loaderData) {
+ return {}
+ }
+
+ return {
+ meta: [
+ {
+ title: 'Root',
+ },
+ {
+ name: 'description',
+ content: loaderData.description,
+ },
+ {
+ name: 'image',
+ content: 'image.jpg',
+ },
+ ],
+ }
+ },
component: () => {
return
},
@@ -102,19 +118,27 @@ describe('ssr meta', () => {
new Promise((r) => setTimeout(r, 2)).then(() => ({
description: 'Index',
})),
- meta: ({ loaderData }) => [
- {
- title: 'Index',
- },
- {
- name: 'description',
- content: loaderData.description,
- },
- {
- name: 'last-modified',
- content: '2021-10-10',
- },
- ],
+ head: ({ loaderData }) => {
+ if (!loaderData) {
+ return {}
+ }
+
+ return {
+ meta: [
+ {
+ title: 'Index',
+ },
+ {
+ name: 'description',
+ content: loaderData.description,
+ },
+ {
+ name: 'last-modified',
+ content: '2021-10-10',
+ },
+ ],
+ }
+ },
})
const router = createRouter({
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 29a4a6b036..b7422d060d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1781,10 +1781,10 @@ importers:
version: 18.3.1
html-webpack-plugin:
specifier: ^5.6.3
- version: 5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ version: 5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1)
swc-loader:
specifier: ^0.2.6
- version: 0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ version: 0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1)
typescript:
specifier: ^5.6.2
version: 5.6.3
@@ -2674,6 +2674,9 @@ importers:
typescript:
specifier: ^5.6.2
version: 5.6.3
+ vite-tsconfig-paths:
+ specifier: ^5.1.2
+ version: 5.1.2(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(terser@5.36.0))
examples/react/start-trellaux:
dependencies:
@@ -2932,7 +2935,7 @@ importers:
version: 4.3.3(vite@5.4.11(@types/node@22.9.0)(terser@5.36.0))
html-webpack-plugin:
specifier: ^5.6.0
- version: 5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ version: 5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1)
react:
specifier: ^18.3.1
version: 18.3.1
@@ -2941,7 +2944,7 @@ importers:
version: 18.3.1(react@18.3.1)
swc-loader:
specifier: ^0.2.6
- version: 0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ version: 0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1)
typescript:
specifier: ^5.6.2
version: 5.6.3
@@ -13849,17 +13852,17 @@ snapshots:
'@webassemblyjs/ast': 1.14.1
'@xtuc/long': 4.2.2
- '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))':
+ '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.96.1)':
dependencies:
webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1)
- '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))':
+ '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.96.1)':
dependencies:
webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1)
- '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack-dev-server@5.1.0(webpack-cli@5.1.4)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))':
+ '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.1.0)(webpack@5.96.1)':
dependencies:
webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
webpack-cli: 5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1)
@@ -15918,7 +15921,7 @@ snapshots:
html-void-elements@3.0.0: {}
- html-webpack-plugin@5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)):
+ html-webpack-plugin@5.6.3(@rspack/core@1.1.1(@swc/helpers@0.5.15))(webpack@5.96.1):
dependencies:
'@types/html-minifier-terser': 6.1.0
html-minifier-terser: 6.1.0
@@ -18211,7 +18214,7 @@ snapshots:
csso: 5.0.5
picocolors: 1.1.1
- swc-loader@0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)):
+ swc-loader@0.2.6(@swc/core@1.9.2(@swc/helpers@0.5.15))(webpack@5.96.1):
dependencies:
'@swc/core': 1.9.2(@swc/helpers@0.5.15)
'@swc/counter': 0.1.3
@@ -18281,26 +18284,26 @@ snapshots:
mkdirp: 1.0.4
yallist: 4.0.0
- terser-webpack-plugin@5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)):
+ terser-webpack-plugin@5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)):
dependencies:
'@jridgewell/trace-mapping': 0.3.25
jest-worker: 27.5.1
schema-utils: 3.3.0
serialize-javascript: 6.0.2
terser: 5.36.0
- webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
+ webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)
optionalDependencies:
'@swc/core': 1.9.2(@swc/helpers@0.5.15)
esbuild: 0.24.0
- terser-webpack-plugin@5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)):
+ terser-webpack-plugin@5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1):
dependencies:
'@jridgewell/trace-mapping': 0.3.25
jest-worker: 27.5.1
schema-utils: 3.3.0
serialize-javascript: 6.0.2
terser: 5.36.0
- webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)
+ webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
optionalDependencies:
'@swc/core': 1.9.2(@swc/helpers@0.5.15)
esbuild: 0.24.0
@@ -18958,9 +18961,9 @@ snapshots:
webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1):
dependencies:
'@discoveryjs/json-ext': 0.5.7
- '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
- '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
- '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.1.0)(webpack@5.96.1))(webpack-dev-server@5.1.0(webpack-cli@5.1.4)(webpack@5.96.1))(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.96.1)
+ '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.96.1)
+ '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.1.0)(webpack@5.96.1)
colorette: 2.0.20
commander: 10.0.1
cross-spawn: 7.0.5
@@ -18974,7 +18977,7 @@ snapshots:
optionalDependencies:
webpack-dev-server: 5.1.0(webpack-cli@5.1.4)(webpack@5.96.1)
- webpack-dev-middleware@7.4.2(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)):
+ webpack-dev-middleware@7.4.2(webpack@5.96.1):
dependencies:
colorette: 2.0.20
memfs: 4.14.0
@@ -19013,7 +19016,7 @@ snapshots:
serve-index: 1.9.1
sockjs: 0.3.24
spdy: 4.0.2
- webpack-dev-middleware: 7.4.2(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ webpack-dev-middleware: 7.4.2(webpack@5.96.1)
ws: 8.18.0
optionalDependencies:
webpack: 5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4)
@@ -19086,7 +19089,7 @@ snapshots:
neo-async: 2.6.2
schema-utils: 3.3.0
tapable: 2.2.1
- terser-webpack-plugin: 5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack-cli@5.1.4))
+ terser-webpack-plugin: 5.3.10(@swc/core@1.9.2(@swc/helpers@0.5.15))(esbuild@0.24.0)(webpack@5.96.1)
watchpack: 2.4.2
webpack-sources: 3.2.3
optionalDependencies: