oRPC TanStack Start Adapter

Use oRPC inside a TanStack Start project with server routes, isomorphic links, and SSR optimization.

SKILL.md

GitHub

TanStack Start Adapter

TanStack Start is a full-stack React framework built on Vite and the Fetch API. For additional context, see the HTTP Adapter guide.

Server

Set up an oRPC server inside TanStack Start using its Server Routes.

// src/routes/api/rpc.$.ts
import { RPCHandler } from '@orpc/server/fetch'
import { createFileRoute } from '@tanstack/react-router'
import { onError } from '@orpc/server'

const handler = new RPCHandler(router, {
  interceptors: [
    onError((error) => {
      console.error(error)
    }),
  ],
})

export const Route = createFileRoute('/api/rpc/$')({
  server: {
    handlers: {
      ANY: async ({ request }) => {
        const { response } = await handler.handle(request, {
          prefix: '/api/rpc',
          context: {},
        })

        return response ?? new Response('Not Found', { status: 404 })
      },
    },
  },
})

The handler can be any supported oRPC handler (RPCHandler, OpenAPIHandler, or custom).

Client

Use createIsomorphicFn to configure the RPC link for both browser and SSR environments:

import { RPCLink } from '@orpc/client/fetch'
import { createIsomorphicFn } from '@tanstack/react-start'
import { getRequestHeaders } from '@tanstack/react-start/server'

const getClientLink = createIsomorphicFn()
  .client(() => new RPCLink({
    url: `${window.location.origin}/api/rpc`,
  }))
  .server(() => new RPCLink({
    url: 'http://localhost:3000/api/rpc',
    headers: () => getRequestHeaders(),
  }))

Optimize SSR

Use a Server-Side Client during SSR to reduce HTTP requests:

// src/lib/orpc.ts
import { createRouterClient } from '@orpc/server'
import type { RouterClient } from '@orpc/server'
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
import { getRequestHeaders } from '@tanstack/react-start/server'
import { createIsomorphicFn } from '@tanstack/react-start'

const getORPCClient = createIsomorphicFn()
  .server(() => createRouterClient(router, {
    context: async () => ({
      headers: getRequestHeaders(),
    }),
  }))
  .client((): RouterClient<typeof router> => {
    const link = new RPCLink({
      url: `${window.location.origin}/api/rpc`,
    })
    return createORPCClient(link)
  })

export const client: RouterClient<typeof router> = getORPCClient()