Skip to content

Set up tRPC with Nuxt

We recommend a file structure like this one, although it is not enforced by tRPC.

  • Directoryserver
    • Directoryapi
      • Directorytrpc
        • [trpc].ts tRPC HTTP handler
    • Directorytrpc
      • Directoryrouters
        • index.ts main app router
        • todo.ts sub routers
      • init.ts procedure helpers
  • Directoryplugins
    • trpc.ts your typesafe tRPC composables
  • Directorypages/
  • nuxt.config.ts
  • package.json

Add tRPC Nuxt to existing Nuxt project

  1. Install dependencies

    Terminal window
    npm install trpc-nuxt @trpc/server @trpc/client

    Add trpc-nuxt to your nuxt.config.ts’s build.transpile:

    nuxt.config.ts
    export default defineNuxtConfig({
    build: {
    transpile: ['trpc-nuxt']
    }
    })
  2. Create a tRPC router

    Initialize your tRPC backend in server/trpc/init.ts using the initTRPC function, and create your first router. We’re going to make a simple “hello world” router and procedure here - but for deeper information on creating your tRPC API you should refer to the Quickstart guide and Backend usage docs for tRPC information.

    View sample backend
    server/trpc/init.ts
    import { initTRPC } from '@trpc/server';
    import type { H3Event } from 'h3';
    export const createTRPCContext = async (event: H3Event) => {
    /**
    * @see: https://trpc.io/docs/server/context
    */
    return { auth: event.context.auth };
    }
    // Avoid exporting the entire t-object
    // since it's not very descriptive.
    // For instance, the use of a t variable
    // is common in i18n libraries.
    const t = initTRPC.create({
    /**
    * @see https://trpc.io/docs/server/data-transformers
    */
    // transformer: superjson,
    });
    // Base router and procedure helpers
    export const createTRPCRouter = t.router;
    export const createCallerFactory = t.createCallerFactory;
    export const baseProcedure = t.procedure;
    server/trpc/routers/index.ts
    import { baseProcedure, createTRPCRouter } from '~/server/trpc/init'
    import { z } from 'zod'
    export const appRouter = createTRPCRouter({
    hello: baseProcedure
    .input(
    z.object({
    text: z.string(),
    }),
    )
    .query((opts) => {
    return {
    greeting: `hello ${opts.input.text}`,
    };
    }),
    });
    // export type definition of API
    export type AppRouter = typeof appRouter;
    server/api/trpc/[trpc].ts
    import { createTRPCNuxtHandler } from 'trpc-nuxt/server'
    import { createTRPCContext } from '~/server/trpc/init'
    import { appRouter } from '~/server/trpc/routers'
    export default createTRPCNuxtHandler({
    endpoint: '/api/trpc',
    router: appRouter,
    createContext: createTRPCContext,
    })
  3. Create a client plugin

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

    plugins/trpc.ts
    import { createTRPCNuxtClient, httpBatchLink } from 'trpc-nuxt/client'
    import type { AppRouter } from '~/server/trpc/routers'
    export default defineNuxtPlugin(() => {
    const trpc = createTRPCNuxtClient<AppRouter>({
    links: [httpBatchLink({ url: '/api/trpc' })],
    })
    return {
    provide: {
    trpc,
    },
    }
    })
  4. Call the procedures in your pages:

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