Recommended Usage

Recommended but not enforced file structure.

.
├── server
│   ├── api
│   │   └── trpc
│   │       └── [trpc].ts  # <-- tRPC HTTP handler
│   │   └── [..]
│   ├── trpc
│   │   ├── routers
│   │   │   ├── index.ts  # <-- main app router
│   │   │   ├── todo.ts  # <-- sub routers
│   │   │   └── [..]
│   │   ├── context.ts   # <-- create app context
│   │   └── trpc.ts      # <-- procedure helpers
├── plugins
│   ├── client.ts  # <-- tRPC client plugin
└── [..]

1. Create a tRPC router

Initialize your tRPC backend using the initTRPC function and create your first router.

server/trpc/trpc.ts
/** * This is your entry point to setup the root configuration for tRPC on the server. * - `initTRPC` should only be used once per app. * - We export only the functionality that we use so we can enforce which base procedures should be used * * Learn how to create protected base procedures and other things below: * @see https://trpc.io/docs/v10/router * @see https://trpc.io/docs/v10/procedures */import { initTRPC } from '@trpc/server'import { Context } from '~/server/trpc/context'const t = initTRPC.context<Context>().create()/** * Unprotected procedure **/export const publicProcedure = t.procedure;export const router = t.router;export const middleware = t.middleware;
server/trpc/routers/index.ts
import { z } from 'zod'import { publicProcedure, router } from '../trpc'export const appRouter = router({  hello: publicProcedure    .input(      z.object({        text: z.string().nullish(),      }),    )    .query(({ input }) => {      return {        greeting: `hello ${input?.text ?? 'world'}`,      }    }),})// export type definition of APIexport type AppRouter = typeof appRouter
server/api/trpc/[trpc].ts
import { createNuxtApiHandler } from 'trpc-nuxt'import { appRouter } from '~/server/trpc/routers'import { createContext } from '~/server/trpc/context'// export API handlerexport default createNuxtApiHandler({  router: appRouter,  createContext,})
server/trpc/context.ts
import { inferAsyncReturnType } from '@trpc/server'/** * Creates context for an incoming request * @link https://trpc.io/docs/context */export const createContext = () => {}export type Context = inferAsyncReturnType<typeof createContext>;
If you need to split your router into several subrouters, you can implement them in the server/trpc/routers directory and import and merge them to a single root appRouter.

2. Create tRPC client plugin

Create a strongly-typed plugin using your API's type signature.

plugins/client.ts
import { createTRPCNuxtClient, httpBatchLink } from 'trpc-nuxt/client'import type { AppRouter } from '~/server/trpc/routers'export default defineNuxtPlugin(() => {  /**   * createTRPCNuxtClient adds a `useQuery` composable   * built on top of `useAsyncData`.   */  const client = createTRPCNuxtClient<AppRouter>({    links: [      httpBatchLink({        url: '/api/trpc',      }),    ],  })  return {    provide: {      client,    },  }})

3. Make an API request

pages/index.vue
<script setup lang="ts">const { $client } = useNuxtApp()const hello = await $client.hello.useQuery({ text: 'client' })</script><template>  <div>    <p>{{ hello.data?.greeting }}</p>  </div></template>