<html lang="en">
<head></head>
<body>

<form id="mainForm" method="post" action="https://stackblitz.com/run" target="_self">
<input type="hidden" name="project[files][.gitignore]" value="node_modules
package-lock.json
yarn.lock

.DS_Store
.cache
.env
.vercel
.output
/build/
/api/
/server/build
/public/build# Sentry Config File
.env.sentry-build-plugin
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
">
<input type="hidden" name="project[files][README.md]" value="# TanStack Router - tRPC Integration Example

An example demonstrating integration with tRPC for type-safe APIs.

- [TanStack Router Docs](https://tanstack.com/router)
- [tRPC Documentation](https://trpc.io)

## Start a new project based on this example

To start a new project based on this example, run:

```sh
npx gitpick TanStack/router/tree/main/examples/react/with-trpc with-trpc
```

## Getting Started

Install dependencies:

```sh
pnpm install
```

Start the development server:

```sh
pnpm dev
```

## Build

Build for production:

```sh
pnpm build
```

## About This Example

This example demonstrates:

- tRPC integration with TanStack Router
- Type-safe API calls
- End-to-end type safety
- Server and client setup
- Procedure definitions
">
<input type="hidden" name="project[files][index.html]" value="&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Vite App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
    &lt;script type=&quot;module&quot; src=&quot;/src/main.tsx&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
">
<input type="hidden" name="project[files][package.json]" value="{&quot;name&quot;:&quot;tanstack-router-react-example-with-trpc&quot;,&quot;private&quot;:true,&quot;type&quot;:&quot;module&quot;,&quot;scripts&quot;:{&quot;dev&quot;:&quot;pnpm tsx ./src/server/server.ts --watch&quot;,&quot;build&quot;:&quot;pnpm run build:server &amp;&amp; pnpm run build:client&quot;,&quot;build:client&quot;:&quot;vite build &amp;&amp; tsc --noEmit&quot;,&quot;build:server&quot;:&quot;vite build --mode server&quot;,&quot;start&quot;:&quot;NODE_ENV=production node dist/server/server.js&quot;},&quot;dependencies&quot;:{&quot;@tailwindcss/vite&quot;:&quot;^4.1.18&quot;,&quot;@tanstack/react-router&quot;:&quot;https://pkg.pr.new/TanStack/router/@tanstack/react-router@d7ab9056820e6849f34d639f3039559e1427038c&quot;,&quot;@tanstack/react-router-devtools&quot;:&quot;https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@d7ab9056820e6849f34d639f3039559e1427038c&quot;,&quot;@tanstack/router-plugin&quot;:&quot;https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@d7ab9056820e6849f34d639f3039559e1427038c&quot;,&quot;@trpc/client&quot;:&quot;^11.4.3&quot;,&quot;@trpc/server&quot;:&quot;^11.4.3&quot;,&quot;express&quot;:&quot;^4.21.2&quot;,&quot;react&quot;:&quot;^19.1.0&quot;,&quot;react-dom&quot;:&quot;^19.1.0&quot;,&quot;redaxios&quot;:&quot;^0.5.1&quot;,&quot;tailwindcss&quot;:&quot;^4.1.18&quot;,&quot;zod&quot;:&quot;^3.24.2&quot;},&quot;devDependencies&quot;:{&quot;@types/express&quot;:&quot;^4.17.23&quot;,&quot;@types/react&quot;:&quot;^19.0.8&quot;,&quot;@types/react-dom&quot;:&quot;^19.0.3&quot;,&quot;@vitejs/plugin-react&quot;:&quot;^4.3.4&quot;,&quot;tsx&quot;:&quot;^4.20.3&quot;,&quot;vite&quot;:&quot;^7.3.1&quot;}}">
<input type="hidden" name="project[files][tsconfig.json]" value="{
  &quot;compilerOptions&quot;: {
    &quot;strict&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;jsx&quot;: &quot;react-jsx&quot;,
    &quot;target&quot;: &quot;ES2022&quot;,
    &quot;module&quot;: &quot;ES2022&quot;,
    &quot;moduleResolution&quot;: &quot;bundler&quot;,
    &quot;skipLibCheck&quot;: true,
    &quot;lib&quot;: [&quot;DOM&quot;, &quot;DOM.Iterable&quot;, &quot;ES2022&quot;],
    &quot;types&quot;: [&quot;node&quot;, &quot;vite/client&quot;]
  },
  &quot;include&quot;: [&quot;src&quot;, &quot;vite.config.ts&quot;, &quot;tsup.config.ts&quot;]
}
">
<input type="hidden" name="project[files][vite.config.ts]" value="import url from &#39;node:url&#39;
import path from &#39;node:path&#39;
import { defineConfig } from &#39;vite&#39;
import react from &#39;@vitejs/plugin-react&#39;
import { tanstackRouter } from &#39;@tanstack/router-plugin/vite&#39;
import type { BuildEnvironmentOptions } from &#39;vite&#39;
import tailwindcss from &#39;@tailwindcss/vite&#39;

const __filename = url.fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

// Client Build Configuration
const clientBuildConfig: BuildEnvironmentOptions = {
  outDir: &#39;dist/client&#39;,
  emitAssets: true,
  copyPublicDir: true,
  emptyOutDir: true,
}

// Server Build Configuration
const serverBuildConfig: BuildEnvironmentOptions = {
  ssr: true,
  outDir: &#39;dist/server&#39;,
  copyPublicDir: false,
  emptyOutDir: true,
  rollupOptions: {
    input: path.resolve(__dirname, &#39;src/server/server.ts&#39;),
    output: {
      entryFileNames: &#39;[name].js&#39;,
      chunkFileNames: &#39;assets/[name]-[hash].js&#39;,
      assetFileNames: &#39;assets/[name]-[hash][extname]&#39;,
    },
  },
}

// https://vitejs.dev/config/
export default defineConfig((configEnv) =&gt; {
  return {
    plugins: [
      tailwindcss(),
      tanstackRouter({
        target: &#39;react&#39;,
        autoCodeSplitting: true,
      }),
      react(),
    ],
    build: configEnv.mode === &#39;server&#39; ? serverBuildConfig : clientBuildConfig,
  }
})
">
<input type="hidden" name="project[files][.vscode/settings.json]" value="{
  &quot;files.watcherExclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  },
  &quot;search.exclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  },
  &quot;files.readonlyInclude&quot;: {
    &quot;**/routeTree.gen.ts&quot;: true
  }
}
">
<input type="hidden" name="project[files][src/main.tsx]" value="import React from &#39;react&#39;
import ReactDOM from &#39;react-dom/client&#39;
import { RouterProvider, createRouter } from &#39;@tanstack/react-router&#39;
import { trpc } from &#39;./trpc&#39;

import { Spinner } from &#39;./routes/-components/spinner&#39;
import &#39;./styles.css&#39;

// Import the generated route tree
import { routeTree } from &#39;./routeTree.gen&#39;

// Create a router instance
const router = createRouter({
  routeTree,
  scrollRestoration: true,
  defaultPreload: &#39;intent&#39;,
  defaultPendingComponent: () =&gt; (
    &lt;div className={`p-2 text-2xl`}&gt;
      &lt;Spinner /&gt;
    &lt;/div&gt;
  ),
  context: {
    trpc,
  },
})

// Register the router instance for type safety
declare module &#39;@tanstack/react-router&#39; {
  interface Register {
    router: typeof router
  }
}

const rootElement = document.getElementById(&#39;root&#39;)!
if (!rootElement.innerHTML) {
  const root = ReactDOM.createRoot(rootElement)
  root.render(
    &lt;React.StrictMode&gt;
      &lt;RouterProvider router={router} /&gt;
    &lt;/React.StrictMode&gt;,
  )
}
">
<input type="hidden" name="project[files][src/routeTree.gen.ts]" value="/* eslint-disable */

// @ts-nocheck

// noinspection JSUnusedGlobalSymbols

// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.

import { Route as rootRouteImport } from &#39;./routes/__root&#39;
import { Route as DashboardRouteImport } from &#39;./routes/dashboard&#39;
import { Route as IndexRouteImport } from &#39;./routes/index&#39;
import { Route as DashboardIndexRouteImport } from &#39;./routes/dashboard.index&#39;
import { Route as DashboardPostsRouteImport } from &#39;./routes/dashboard.posts&#39;
import { Route as DashboardPostsIndexRouteImport } from &#39;./routes/dashboard.posts.index&#39;
import { Route as DashboardPostsPostIdRouteImport } from &#39;./routes/dashboard.posts.$postId&#39;

const DashboardRoute = DashboardRouteImport.update({
  id: &#39;/dashboard&#39;,
  path: &#39;/dashboard&#39;,
  getParentRoute: () =&gt; rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
  id: &#39;/&#39;,
  path: &#39;/&#39;,
  getParentRoute: () =&gt; rootRouteImport,
} as any)
const DashboardIndexRoute = DashboardIndexRouteImport.update({
  id: &#39;/&#39;,
  path: &#39;/&#39;,
  getParentRoute: () =&gt; DashboardRoute,
} as any)
const DashboardPostsRoute = DashboardPostsRouteImport.update({
  id: &#39;/posts&#39;,
  path: &#39;/posts&#39;,
  getParentRoute: () =&gt; DashboardRoute,
} as any)
const DashboardPostsIndexRoute = DashboardPostsIndexRouteImport.update({
  id: &#39;/&#39;,
  path: &#39;/&#39;,
  getParentRoute: () =&gt; DashboardPostsRoute,
} as any)
const DashboardPostsPostIdRoute = DashboardPostsPostIdRouteImport.update({
  id: &#39;/$postId&#39;,
  path: &#39;/$postId&#39;,
  getParentRoute: () =&gt; DashboardPostsRoute,
} as any)

export interface FileRoutesByFullPath {
  &#39;/&#39;: typeof IndexRoute
  &#39;/dashboard&#39;: typeof DashboardRouteWithChildren
  &#39;/dashboard/posts&#39;: typeof DashboardPostsRouteWithChildren
  &#39;/dashboard/&#39;: typeof DashboardIndexRoute
  &#39;/dashboard/posts/$postId&#39;: typeof DashboardPostsPostIdRoute
  &#39;/dashboard/posts/&#39;: typeof DashboardPostsIndexRoute
}
export interface FileRoutesByTo {
  &#39;/&#39;: typeof IndexRoute
  &#39;/dashboard&#39;: typeof DashboardIndexRoute
  &#39;/dashboard/posts/$postId&#39;: typeof DashboardPostsPostIdRoute
  &#39;/dashboard/posts&#39;: typeof DashboardPostsIndexRoute
}
export interface FileRoutesById {
  __root__: typeof rootRouteImport
  &#39;/&#39;: typeof IndexRoute
  &#39;/dashboard&#39;: typeof DashboardRouteWithChildren
  &#39;/dashboard/posts&#39;: typeof DashboardPostsRouteWithChildren
  &#39;/dashboard/&#39;: typeof DashboardIndexRoute
  &#39;/dashboard/posts/$postId&#39;: typeof DashboardPostsPostIdRoute
  &#39;/dashboard/posts/&#39;: typeof DashboardPostsIndexRoute
}
export interface FileRouteTypes {
  fileRoutesByFullPath: FileRoutesByFullPath
  fullPaths:
    | &#39;/&#39;
    | &#39;/dashboard&#39;
    | &#39;/dashboard/posts&#39;
    | &#39;/dashboard/&#39;
    | &#39;/dashboard/posts/$postId&#39;
    | &#39;/dashboard/posts/&#39;
  fileRoutesByTo: FileRoutesByTo
  to: &#39;/&#39; | &#39;/dashboard&#39; | &#39;/dashboard/posts/$postId&#39; | &#39;/dashboard/posts&#39;
  id:
    | &#39;__root__&#39;
    | &#39;/&#39;
    | &#39;/dashboard&#39;
    | &#39;/dashboard/posts&#39;
    | &#39;/dashboard/&#39;
    | &#39;/dashboard/posts/$postId&#39;
    | &#39;/dashboard/posts/&#39;
  fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
  IndexRoute: typeof IndexRoute
  DashboardRoute: typeof DashboardRouteWithChildren
}

declare module &#39;@tanstack/react-router&#39; {
  interface FileRoutesByPath {
    &#39;/dashboard&#39;: {
      id: &#39;/dashboard&#39;
      path: &#39;/dashboard&#39;
      fullPath: &#39;/dashboard&#39;
      preLoaderRoute: typeof DashboardRouteImport
      parentRoute: typeof rootRouteImport
    }
    &#39;/&#39;: {
      id: &#39;/&#39;
      path: &#39;/&#39;
      fullPath: &#39;/&#39;
      preLoaderRoute: typeof IndexRouteImport
      parentRoute: typeof rootRouteImport
    }
    &#39;/dashboard/&#39;: {
      id: &#39;/dashboard/&#39;
      path: &#39;/&#39;
      fullPath: &#39;/dashboard/&#39;
      preLoaderRoute: typeof DashboardIndexRouteImport
      parentRoute: typeof DashboardRoute
    }
    &#39;/dashboard/posts&#39;: {
      id: &#39;/dashboard/posts&#39;
      path: &#39;/posts&#39;
      fullPath: &#39;/dashboard/posts&#39;
      preLoaderRoute: typeof DashboardPostsRouteImport
      parentRoute: typeof DashboardRoute
    }
    &#39;/dashboard/posts/&#39;: {
      id: &#39;/dashboard/posts/&#39;
      path: &#39;/&#39;
      fullPath: &#39;/dashboard/posts/&#39;
      preLoaderRoute: typeof DashboardPostsIndexRouteImport
      parentRoute: typeof DashboardPostsRoute
    }
    &#39;/dashboard/posts/$postId&#39;: {
      id: &#39;/dashboard/posts/$postId&#39;
      path: &#39;/$postId&#39;
      fullPath: &#39;/dashboard/posts/$postId&#39;
      preLoaderRoute: typeof DashboardPostsPostIdRouteImport
      parentRoute: typeof DashboardPostsRoute
    }
  }
}

interface DashboardPostsRouteChildren {
  DashboardPostsPostIdRoute: typeof DashboardPostsPostIdRoute
  DashboardPostsIndexRoute: typeof DashboardPostsIndexRoute
}

const DashboardPostsRouteChildren: DashboardPostsRouteChildren = {
  DashboardPostsPostIdRoute: DashboardPostsPostIdRoute,
  DashboardPostsIndexRoute: DashboardPostsIndexRoute,
}

const DashboardPostsRouteWithChildren = DashboardPostsRoute._addFileChildren(
  DashboardPostsRouteChildren,
)

interface DashboardRouteChildren {
  DashboardPostsRoute: typeof DashboardPostsRouteWithChildren
  DashboardIndexRoute: typeof DashboardIndexRoute
}

const DashboardRouteChildren: DashboardRouteChildren = {
  DashboardPostsRoute: DashboardPostsRouteWithChildren,
  DashboardIndexRoute: DashboardIndexRoute,
}

const DashboardRouteWithChildren = DashboardRoute._addFileChildren(
  DashboardRouteChildren,
)

const rootRouteChildren: RootRouteChildren = {
  IndexRoute: IndexRoute,
  DashboardRoute: DashboardRouteWithChildren,
}
export const routeTree = rootRouteImport
  ._addFileChildren(rootRouteChildren)
  ._addFileTypes&lt;FileRouteTypes&gt;()
">
<input type="hidden" name="project[files][src/styles.css]" value="@import &#39;tailwindcss&#39; source(&#39;../&#39;);

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentcolor);
  }
}

html {
  color-scheme: light dark;
}
* {
  @apply border-gray-200 dark:border-gray-800;
}
body {
  @apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
}
">
<input type="hidden" name="project[files][src/trpc.ts]" value="import { createTRPCClient, httpBatchLink } from &#39;@trpc/client&#39;
import type { AppRouter } from &#39;./server/trpc&#39;

export const trpc = createTRPCClient&lt;AppRouter&gt;({
  links: [
    httpBatchLink({
      // since we are using Vite, the server is running on the same port,
      // this means in dev the url is `http://localhost:3000/trpc`
      // and since its from the same origin, we don&#39;t need to explicitly set the full URL
      url: &#39;/trpc&#39;,
    }),
  ],
})
">
<input type="hidden" name="project[files][src/routes/__root.tsx]" value="import {
  Link,
  Outlet,
  createRootRouteWithContext,
  useRouterState,
} from &#39;@tanstack/react-router&#39;
import { TanStackRouterDevtools } from &#39;@tanstack/react-router-devtools&#39;

import { Spinner } from &#39;./-components/spinner&#39;
import type { trpc } from &#39;../trpc&#39;

export interface RouterAppContext {
  trpc: typeof trpc
}

export const Route = createRootRouteWithContext&lt;RouterAppContext&gt;()({
  component: RootComponent,
})

function RootComponent() {
  const isFetching = useRouterState({ select: (s) =&gt; s.isLoading })

  return (
    &lt;&gt;
      &lt;div className={`min-h-screen flex flex-col`}&gt;
        &lt;div className={`flex items-center border-b gap-2`}&gt;
          &lt;h1 className={`text-3xl p-2`}&gt;With tRPC&lt;/h1&gt;
          {/* Show a global spinner when the router is transitioning */}
          &lt;div
            className={`text-3xl duration-300 delay-0 opacity-0 ${
              isFetching ? ` duration-1000 opacity-40` : &#39;&#39;
            }`}
          &gt;
            &lt;Spinner /&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div className={`flex-1 flex`}&gt;
          &lt;div className={`divide-y w-56`}&gt;
            {(
              [
                [&#39;/&#39;, &#39;Home&#39;],
                [&#39;/dashboard&#39;, &#39;Dashboard&#39;],
              ] as const
            ).map(([to, label]) =&gt; {
              return (
                &lt;div key={to}&gt;
                  &lt;Link
                    to={to}
                    activeOptions={
                      {
                        // If the route points to the root of it&#39;s parent,
                        // make sure it&#39;s only active if it&#39;s exact
                        // exact: to === &#39;.&#39;,
                      }
                    }
                    preload=&quot;intent&quot;
                    className={`block py-2 px-3 text-blue-700`}
                    // Make &quot;active&quot; links bold
                    activeProps={{ className: `font-bold` }}
                  &gt;
                    {label}
                  &lt;/Link&gt;
                &lt;/div&gt;
              )
            })}
          &lt;/div&gt;
          &lt;div className={`flex-1 border-l border-gray-200`}&gt;
            {/* Render our first route match */}
            &lt;Outlet /&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;TanStackRouterDevtools position=&quot;bottom-right&quot; /&gt;
    &lt;/&gt;
  )
}
">
<input type="hidden" name="project[files][src/routes/dashboard.index.tsx]" value="import { createFileRoute } from &#39;@tanstack/react-router&#39;

export const Route = createFileRoute(&#39;/dashboard/&#39;)({
  loader: ({ context: { trpc } }) =&gt; trpc.posts.query(),
  component: DashboardIndexComponent,
})

function DashboardIndexComponent() {
  const posts = Route.useLoaderData()

  return (
    &lt;div className=&quot;p-2&quot;&gt;
      &lt;div className=&quot;p-2&quot;&gt;
        Welcome to the dashboard! You have{&#39; &#39;}
        &lt;strong&gt;{posts.length} total posts&lt;/strong&gt;.
      &lt;/div&gt;
    &lt;/div&gt;
  )
}
">
<input type="hidden" name="project[files][src/routes/dashboard.posts.$postId.tsx]" value="import * as React from &#39;react&#39;
import { Link, createFileRoute } from &#39;@tanstack/react-router&#39;
import { z } from &#39;zod&#39;

export const Route = createFileRoute(&#39;/dashboard/posts/$postId&#39;)({
  validateSearch: z.object({
    showNotes: z.boolean().optional(),
    notes: z.string().optional(),
  }),
  loader: async ({ context: { trpc }, params: { postId } }) =&gt;
    trpc.post.query(postId),
  component: DashboardPostsPostIdComponent,
})

function DashboardPostsPostIdComponent() {
  const post = Route.useLoaderData()
  const search = Route.useSearch()
  const navigate = Route.useNavigate()

  const [notes, setNotes] = React.useState(search.notes ?? ``)

  React.useEffect(() =&gt; {
    navigate({
      search: (old) =&gt; ({ ...old, notes: notes ? notes : undefined }),
      replace: true,
      params: true,
    })
  }, [notes])

  if (!post) {
    return &lt;div&gt;Post not found&lt;/div&gt;
  }

  return (
    &lt;div className=&quot;p-2 space-y-2&quot; key={post.id}&gt;
      &lt;div className=&quot;space-y-2&quot;&gt;
        &lt;h2 className=&quot;font-bold text-lg&quot;&gt;
          &lt;input
            defaultValue={post.id}
            className=&quot;border border-opacity-50 rounded-sm p-2 w-full&quot;
            disabled
          /&gt;
        &lt;/h2&gt;
        &lt;div&gt;
          &lt;textarea
            defaultValue={post.title}
            rows={6}
            className=&quot;border border-opacity-50 p-2 rounded-sm w-full&quot;
            disabled
          /&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;
        &lt;Link
          from={Route.fullPath}
          search={(old) =&gt; ({
            ...old,
            showNotes: old.showNotes ? undefined : true,
          })}
          params={true}
          className=&quot;text-blue-700&quot;
        &gt;
          {search.showNotes ? &#39;Close Notes&#39; : &#39;Show Notes&#39;}{&#39; &#39;}
        &lt;/Link&gt;
        {search.showNotes ? (
          &lt;&gt;
            &lt;div&gt;
              &lt;div className=&quot;h-2&quot; /&gt;
              &lt;textarea
                value={notes}
                onChange={(e) =&gt; setNotes(e.target.value)}
                rows={5}
                className=&quot;shadow-sm w-full p-2 rounded-sm&quot;
                placeholder=&quot;Write some notes here...&quot;
              /&gt;
              &lt;div className=&quot;italic text-xs&quot;&gt;
                Notes are stored in the URL. Try copying the URL into a new tab!
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/&gt;
        ) : null}
      &lt;/div&gt;
    &lt;/div&gt;
  )
}
">
<input type="hidden" name="project[files][src/routes/dashboard.posts.index.tsx]" value="import * as React from &#39;react&#39;
import { createFileRoute } from &#39;@tanstack/react-router&#39;

export const Route = createFileRoute(&#39;/dashboard/posts/&#39;)({
  component: DashboardPostsIndexComponent,
})

function DashboardPostsIndexComponent() {
  return &lt;div className=&quot;p-2&quot;&gt;Select a post to view.&lt;/div&gt;
}
">
<input type="hidden" name="project[files][src/routes/dashboard.posts.tsx]" value="import * as React from &#39;react&#39;
import {
  Link,
  MatchRoute,
  Outlet,
  createFileRoute,
} from &#39;@tanstack/react-router&#39;

import { Spinner } from &#39;./-components/spinner&#39;

export const Route = createFileRoute(&#39;/dashboard/posts&#39;)({
  loader: ({ context: { trpc } }) =&gt; trpc.posts.query(),
  component: DashboardPostsComponent,
})

function DashboardPostsComponent() {
  const posts = Route.useLoaderData()

  return (
    &lt;div className=&quot;flex-1 flex&quot;&gt;
      &lt;div className=&quot;divide-y w-48&quot;&gt;
        {posts.map((post) =&gt; {
          return (
            &lt;div key={post.id}&gt;
              &lt;Link
                to=&quot;/dashboard/posts/$postId&quot;
                params={{
                  postId: post.id,
                }}
                preload=&quot;intent&quot;
                className=&quot;block py-2 px-3 text-blue-700&quot;
                activeProps={{ className: `font-bold` }}
              &gt;
                &lt;pre className=&quot;text-sm&quot;&gt;
                  #{post.id} - {post.title.slice(0, 10)}{&#39; &#39;}
                  &lt;MatchRoute
                    to=&quot;/dashboard/posts/$postId&quot;
                    params={{
                      postId: post.id,
                    }}
                    pending
                  &gt;
                    &lt;Spinner /&gt;
                  &lt;/MatchRoute&gt;
                &lt;/pre&gt;
              &lt;/Link&gt;
            &lt;/div&gt;
          )
        })}
      &lt;/div&gt;
      &lt;div className=&quot;flex-1 border-l border-gray-200&quot;&gt;
        &lt;Outlet /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  )
}
">
<input type="hidden" name="project[files][src/routes/dashboard.tsx]" value="import * as React from &#39;react&#39;
import { Link, Outlet, createFileRoute } from &#39;@tanstack/react-router&#39;

export const Route = createFileRoute(&#39;/dashboard&#39;)({
  component: DashboardComponent,
})

function DashboardComponent() {
  return (
    &lt;&gt;
      &lt;div className=&quot;flex items-center border-b&quot;&gt;
        &lt;h2 className=&quot;text-xl p-2&quot;&gt;Dashboard&lt;/h2&gt;
        &lt;Link
          to=&quot;/dashboard/posts/$postId&quot;
          params={{
            postId: &#39;3&#39;,
          }}
          className=&quot;py-1 px-2 text-xs bg-blue-500 text-white rounded-full&quot;
        &gt;
          1 New Invoice
        &lt;/Link&gt;
      &lt;/div&gt;
      &lt;div className=&quot;flex flex-wrap divide-x&quot;&gt;
        {(
          [
            [&#39;.&#39;, &#39;Summary&#39;],
            [&#39;/dashboard/posts&#39;, &#39;Posts&#39;],
          ] as const
        ).map(([to, label]) =&gt; {
          return (
            &lt;Link
              from={Route.fullPath}
              key={to}
              to={to}
              activeOptions={{ exact: to === &#39;.&#39; }}
              activeProps={{ className: `font-bold` }}
              className=&quot;p-2&quot;
            &gt;
              {label}
            &lt;/Link&gt;
          )
        })}
      &lt;/div&gt;
      &lt;hr /&gt;
      &lt;Outlet /&gt;
    &lt;/&gt;
  )
}
">
<input type="hidden" name="project[files][src/routes/index.tsx]" value="import * as React from &#39;react&#39;
import { Link, createFileRoute } from &#39;@tanstack/react-router&#39;

export const Route = createFileRoute(&#39;/&#39;)({
  component: IndexComponent,
})

function IndexComponent() {
  return (
    &lt;div className={`p-2`}&gt;
      &lt;div className={`text-lg`}&gt;Welcome Home!&lt;/div&gt;
      &lt;hr className={`my-2`} /&gt;
      &lt;Link
        to=&quot;/dashboard/posts/$postId&quot;
        params={{
          postId: &#39;3&#39;,
        }}
        className={`py-1 px-2 text-xs bg-blue-500 text-white rounded-full`}
      &gt;
        1 New Invoice
      &lt;/Link&gt;
      &lt;hr className={`my-2`} /&gt;
      &lt;div className={`max-w-xl`}&gt;
        As you navigate around take note of the UX. It should feel
        suspense-like, where routes are only rendered once all of their data and
        elements are ready.
        &lt;hr className={`my-2`} /&gt;
        To exaggerate async effects, play with the artificial request delay
        slider in the bottom-left corner.
        &lt;hr className={`my-2`} /&gt;
        The last 2 sliders determine if link-hover preloading is enabled (and
        how long those preloads stick around) and also whether to cache rendered
        route data (and for how long). Both of these default to 0 (or off).
      &lt;/div&gt;
    &lt;/div&gt;
  )
}
">
<input type="hidden" name="project[files][src/server/server.ts]" value="import path from &#39;node:path&#39;
import url from &#39;node:url&#39;
import * as fs from &#39;node:fs&#39;
import express from &#39;express&#39;
import { trpcMiddleWare } from &#39;./trpc&#39;

const PORT =
  typeof process.env.PORT !== &#39;undefined&#39;
    ? parseInt(process.env.PORT, 10)
    : 3000
const HMR_PORT =
  typeof process.env.HMR_PORT !== &#39;undefined&#39;
    ? parseInt(process.env.HMR_PORT, 10)
    : 3001

const isTest = process.env.NODE_ENV === &#39;test&#39; || !!process.env.VITE_TEST_BUILD

const __filename = url.fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

export const createServer = async (
  root = process.cwd(),
  isProd = process.env.NODE_ENV === &#39;production&#39;,
) =&gt; {
  const app = express()

  app.use(&#39;/trpc&#39;, trpcMiddleWare as any)

  if (!isProd) {
    const vite = await import(&#39;vite&#39;)
    const viteServer = await vite.createServer({
      root,
      logLevel: isTest ? &#39;error&#39; : &#39;info&#39;,
      server: {
        middlewareMode: true,
        watch: {
          // During tests we edit the files too fast and sometimes chokidar
          // misses change events, so enforce polling for consistency
          usePolling: true,
          interval: 100,
        },
        hmr: {
          port: HMR_PORT,
        },
      },
      appType: &#39;custom&#39;,
    })

    // Use vite&#39;s connect instance as middleware
    app.use(viteServer.middlewares)

    // Handle any requests that don&#39;t match an API route by serving the React app&#39;s index.html
    app.get(&#39;*&#39;, async (req, res, next) =&gt; {
      try {
        let html = fs.readFileSync(path.resolve(root, &#39;index.html&#39;), &#39;utf-8&#39;)

        // Transform HTML using Vite plugins.
        html = await viteServer.transformIndexHtml(req.url, html)

        res.send(html)
      } catch (e) {
        return next(e)
      }
    })

    return { app }
  } else {
    app.use(express.static(path.resolve(__dirname, &#39;../client&#39;)))

    // Handle any requests that don&#39;t match an API route by serving the React app&#39;s index.html
    app.get(&#39;*&#39;, (req, res) =&gt; {
      res.sendFile(path.resolve(__dirname, &#39;../client&#39;, &#39;index.html&#39;))
    })
  }

  return { app }
}

if (!isTest) {
  createServer().then(({ app }) =&gt;
    app.listen(PORT, () =&gt; {
      console.info(`Server available at: http://localhost:${PORT}`)
    }),
  )
}
">
<input type="hidden" name="project[files][src/server/trpc.ts]" value="import { initTRPC } from &#39;@trpc/server&#39;
import { createExpressMiddleware } from &#39;@trpc/server/adapters/express&#39;
import type { CreateExpressContextOptions } from &#39;@trpc/server/adapters/express&#39;

const createTRPContext = ({ req, res }: CreateExpressContextOptions) =&gt; ({})

type TRPCContext = Awaited&lt;ReturnType&lt;typeof createTRPContext&gt;&gt;

const t = initTRPC.context&lt;TRPCContext&gt;().create()

const POSTS = [
  { id: &#39;1&#39;, title: &#39;First post&#39; },
  { id: &#39;2&#39;, title: &#39;Second post&#39; },
  { id: &#39;3&#39;, title: &#39;Third post&#39; },
  { id: &#39;4&#39;, title: &#39;Fourth post&#39; },
  { id: &#39;5&#39;, title: &#39;Fifth post&#39; },
  { id: &#39;6&#39;, title: &#39;Sixth post&#39; },
  { id: &#39;7&#39;, title: &#39;Seventh post&#39; },
  { id: &#39;8&#39;, title: &#39;Eighth post&#39; },
  { id: &#39;9&#39;, title: &#39;Ninth post&#39; },
  { id: &#39;10&#39;, title: &#39;Tenth post&#39; },
]

export const appRouter = t.router({
  hello: t.procedure.query(() =&gt; &#39;Hello world!&#39;),
  posts: t.procedure.query(async (_) =&gt; {
    await new Promise((resolve) =&gt; setTimeout(resolve, 1000))
    return POSTS
  }),
  post: t.procedure.input(String).query(async (req) =&gt; {
    await new Promise((resolve) =&gt; setTimeout(resolve, 500))
    return POSTS.find((p) =&gt; p.id === req.input)
  }),
})

export const trpcMiddleWare = createExpressMiddleware({
  router: appRouter,
  createContext: createTRPContext,
})

export type AppRouter = typeof appRouter
">
<input type="hidden" name="project[files][src/routes/-components/spinner.tsx]" value="import * as React from &#39;react&#39;

export function Spinner() {
  return &lt;div className=&quot;inline-block animate-spin px-3&quot;&gt;⍥&lt;/div&gt;
}
">
<input type="hidden" name="project[description]" value="generated by https://pkg.pr.new">
<input type="hidden" name="project[template]" value="node">
<input type="hidden" name="project[title]" value="tanstack-router-react-example-with-trpc">
</form>
<script>document.getElementById("mainForm").submit();</script>

</body></html>