LogoRobo.js

@robojs/trpc

Type-safe APIs with tRPC, fully managed for Robo.js.

Install @robojs/trpc with:

Add a tRPC server and client to your Robo automatically. This plugin sets up a tRPC router with automatic registration, type-safe procedure calls, and support for both React Query hooks and standalone clients.

End-to-end type safety means your client knows exactly what the server expects and returns — no manual type definitions, no runtime surprises.

Features

End-to-end Types

Full type safety from server procedures to client calls

Auto Registration

Router captured automatically via custom initTRPC wrapper

React Query

Built-in hooks with caching, loading states, and invalidation

Standalone Client

Direct procedure calls without React dependency

Zod Validation

Schema-based input validation for every procedure

Seed Files

Working server, client, and start hook out of the box

Installation

This plugin requires @robojs/server for HTTP routing.

npx robo add @robojs/server@next @robojs/trpc@next

Or create a new project with both plugins pre-installed:

npx create-robo@next my-project -p @robojs/server@next @robojs/trpc@next

We also recommend installing zod for input validation:

npm install zod

Quick start

When you install the plugin, it seeds three files into your project:

trpc.tsRegisters router on startup
client.tsReact Query hooks
server.tsRouter + procedures

These give you a working tRPC setup out of the box. Define procedures on the server, call them from the client — fully typed.

Define a procedure

src/trpc/server.ts
import { initTRPC } from '@robojs/trpc/server.js'
import { z } from 'zod'

const t = initTRPC.create()

export const appRouter = t.router({
	hello: t.procedure
		.input(z.object({ text: z.string() }))
		.query(({ input }) => {
			return { message: `Hello ${input.text}` }
		})
})

export type AppRouter = typeof appRouter
src/trpc/server.js
import { initTRPC } from '@robojs/trpc/server.js'
import { z } from 'zod'

const t = initTRPC.create()

export const appRouter = t.router({
	hello: t.procedure
		.input(z.object({ text: z.string() }))
		.query(({ input }) => {
			return { message: `Hello ${input.text}` }
		})
})

Import initTRPC from @robojs/trpc/server.js, not from @trpc/server. The plugin wraps tRPC's initializer to automatically register your router.

Call it from the client

Use the standalone client for direct calls:

import { trpcClient } from '../trpc/client'

const result = await trpcClient.hello.query({ text: 'World' })
console.log(result.message) // "Hello World"
import { trpcClient } from '../trpc/client'

const result = await trpcClient.hello.query({ text: 'World' })
console.log(result.message) // "Hello World"

Or use React Query hooks for automatic caching and loading states:

import { trpc } from '../trpc/client'

function Greeting() {
	const { data, isLoading } = trpc.hello.useQuery({ text: 'World' })

	if (isLoading) return <span>Loading...</span>
	return <span>{data?.message}</span>
}
import { trpc } from '../trpc/client'

function Greeting() {
	const { data, isLoading } = trpc.hello.useQuery({ text: 'World' })

	if (isLoading) return <span>Loading...</span>
	return <span>{data?.message}</span>
}

React Query hooks require wrapping your app in TRPCProvider. See the client guide for setup.

How it works

The plugin handles tRPC integration through three mechanisms:

  1. Router registration. The custom initTRPC from @robojs/trpc/server.js wraps tRPC's router method to automatically capture your router instance. No manual registration needed.

  2. API routing. The plugin registers a catch-all API route at /api/trpc/* through @robojs/server. All tRPC procedure calls are handled by this endpoint.

  3. Start hook. A seeded _start event handler imports your server file at startup, triggering router registration before any requests arrive.

The result is a tRPC setup that works with zero configuration — install the plugin, define procedures, and start calling them.

Next Steps

On this page