--- title: Usage description: tRPC-Nuxt provides first class integration with tRPC. --- # Usage ## Recommended file structure Recommended but not enforced file structure. This is what you get when starting from [the examples](../main/example-apps.md). ```graphql . ├── 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 as a plugin └── [..] ``` ## 1. Create a tRPC router Initialize your tRPC backend using the `initTRPC` function and create your first router. ::code-group ```ts [server/trpc/trpc.ts] import { initTRPC } from '@trpc/server' import { Context } from '@/server/trpc/context' // Avoid exporting the entire t-object since it's not very // descriptive and can be confusing to newcomers used to t // meaning translation in i18n libraries. const t = initTRPC.context().create() // Base router and procedure helpers export const router = t.router export const publicProcedure = t.procedure ``` ```ts [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 API export type AppRouter = typeof appRouter ``` ```ts [server/api/trpc/[trpc].ts] import { createNuxtApiHandler } from 'trpc-nuxt' import { appRouter } from '@/server/trpc/routers' import { createContext } from '@/server/trpc/context' // export API handler export default createNuxtApiHandler({ router: appRouter, createContext, }) ``` ```ts [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; ``` :: ::alert{type=info} 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](https://trpc.io/docs/v10/merging-routers) to a single root `appRouter`. :: ## 2. Create tRPC client plugin Create a strongly-typed plugin using your API's type signature. ```ts [plugins/client.ts] import { httpBatchLink, createTRPCProxyClient } from '@trpc/client' import type { AppRouter } from '@/server/trpc/routers' import { FetchError } from 'ofetch' export default defineNuxtPlugin(() => { const client = createTRPCProxyClient({ links: [ httpBatchLink({ url: '/api/trpc', /** * Replace regular `fetch` with a `$fetch` from nuxt * * During server-side rendering, calling $fetch to fetch your internal API routes * will directly call the relevant function (emulating the request), * saving an additional API call. * * @see https://nuxt.com/docs/api/utils/dollarfetch */ fetch: (input, options) => globalThis.$fetch.raw(input.toString(), options) .catch((e) => { if (e instanceof FetchError && e.response) return e.response throw e }) .then(response => ({ ...response, json: () => Promise.resolve(response._data), })), }), ], }) return { provide: { client, }, } }) ``` ## 3. Make API requests ```vue [pages/index.vue] ```