Hobbs
Hobbs3mo ago

Questions around trpc with next.js app router

I have a few questions in wrapping my head around how to get it to work. Is withTRPC<AppRouter> still required? The docs show it: https://trpc.io/docs/v9/nextjs#5-configure-_apptsx but it looks like the example is around the pages router and not app router. I am using createTRPCNext<AppRouter> am I meant to use both createTRPCNext as well as withTRPC ? Below is some of my code for reference
Usage with Next.js | tRPC
If you're using tRPC in a new project, consider using one of the example projects as a starting point or for reference: tRPC Example Projects
1 Reply
Hobbs
Hobbs3mo ago
./utils/trpc.ts
import {
createWSClient,
httpBatchLink,
loggerLink,
wsLink,
type TRPCLink,
} from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import type { AppRouter } from "@/server";
import { ssrPrepass } from "@trpc/next/ssrPrepass";
import type { NextPageContext } from "next";
import superjson from "superjson";

function getEndingLink(ctx: NextPageContext | undefined): TRPCLink<AppRouter> {
if (typeof window === "undefined") {
return httpBatchLink({
transformer: superjson,
url: `${process.env.NEXT_PUBLIC_APP_URL}/api/trpc`,
headers() {
if (!ctx?.req?.headers) {
return {};
}
return {
...ctx.req.headers,
"x-ssr": "1",
};
},
});
}
const client = createWSClient({
url: process.env.NEXT_PUBLIC_WS_URL!,
});
return wsLink({
client,

transformer: superjson,
});
}

export function getBaseUrl() {
if (typeof window !== "undefined") return "";

if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;

return `http://localhost:${process.env.PORT ?? 3000}`;
}

export const trpc = createTRPCNext<AppRouter>({
ssr: true,
ssrPrepass,
config({ ctx }) {
return {
links: [
loggerLink({
enabled: (opts) =>
(process.env.NODE_ENV === "development" &&
typeof window !== "undefined") ||
(opts.direction === "down" && opts.result instanceof Error),
}),
getEndingLink(ctx),
],

queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
};
},

transformer: superjson,
});
import {
createWSClient,
httpBatchLink,
loggerLink,
wsLink,
type TRPCLink,
} from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import type { AppRouter } from "@/server";
import { ssrPrepass } from "@trpc/next/ssrPrepass";
import type { NextPageContext } from "next";
import superjson from "superjson";

function getEndingLink(ctx: NextPageContext | undefined): TRPCLink<AppRouter> {
if (typeof window === "undefined") {
return httpBatchLink({
transformer: superjson,
url: `${process.env.NEXT_PUBLIC_APP_URL}/api/trpc`,
headers() {
if (!ctx?.req?.headers) {
return {};
}
return {
...ctx.req.headers,
"x-ssr": "1",
};
},
});
}
const client = createWSClient({
url: process.env.NEXT_PUBLIC_WS_URL!,
});
return wsLink({
client,

transformer: superjson,
});
}

export function getBaseUrl() {
if (typeof window !== "undefined") return "";

if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;

return `http://localhost:${process.env.PORT ?? 3000}`;
}

export const trpc = createTRPCNext<AppRouter>({
ssr: true,
ssrPrepass,
config({ ctx }) {
return {
links: [
loggerLink({
enabled: (opts) =>
(process.env.NODE_ENV === "development" &&
typeof window !== "undefined") ||
(opts.direction === "down" && opts.result instanceof Error),
}),
getEndingLink(ctx),
],

queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
};
},

transformer: superjson,
});
./server/client.ts
import { createTRPCReact } from "@trpc/react-query";
import type { AppRouter } from ".";

export const trpc = createTRPCReact<AppRouter>({});
import { createTRPCReact } from "@trpc/react-query";
import type { AppRouter } from ".";

export const trpc = createTRPCReact<AppRouter>({});
./server/trpc.ts
import { initTRPC } from "@trpc/server";
import type { Context } from "./context";
import SuperJSON from "superjson";

const trpc = initTRPC.context<Context>().create({
transformer: SuperJSON,
});

export const router = trpc.router;
export const publicProcedure = trpc.procedure;

export const { createCallerFactory } = trpc;
import { initTRPC } from "@trpc/server";
import type { Context } from "./context";
import SuperJSON from "superjson";

const trpc = initTRPC.context<Context>().create({
transformer: SuperJSON,
});

export const router = trpc.router;
export const publicProcedure = trpc.procedure;

export const { createCallerFactory } = trpc;
./server/index.ts
import { router } from "./trpc";
import { userRouter } from "./routers/user";
import { networksRouter } from "./routers/networks";
import { articlesRouter } from "./routers/perigon-articles";

export const appRouter = router({
userRouter,
networksRouter,
articlesRouter,
});

export type AppRouter = typeof appRouter;
import { router } from "./trpc";
import { userRouter } from "./routers/user";
import { networksRouter } from "./routers/networks";
import { articlesRouter } from "./routers/perigon-articles";

export const appRouter = router({
userRouter,
networksRouter,
articlesRouter,
});

export type AppRouter = typeof appRouter;
// example router (routers are located in ./server/routers/* ./server/routers/articles.ts
import { z } from "zod";
import { router, publicProcedure } from "../trpc";
import { fetchPerigonArticles } from "@/server/actions/fetch-perigon-articles";

export const articlesRouter = router({
fetch: publicProcedure.input(z.string()).query(async ({ input }) => {
try {
console.log("fetchArticles input:", input);
const result = await fetchPerigonArticles(input);
console.log("fetchArticles result:", result);
return result;
} catch (error) {
console.error("Error in fetchArticles procedure:", error);
throw new Error("Failed to fetch articles");
}
}),
});
import { z } from "zod";
import { router, publicProcedure } from "../trpc";
import { fetchPerigonArticles } from "@/server/actions/fetch-perigon-articles";

export const articlesRouter = router({
fetch: publicProcedure.input(z.string()).query(async ({ input }) => {
try {
console.log("fetchArticles input:", input);
const result = await fetchPerigonArticles(input);
console.log("fetchArticles result:", result);
return result;
} catch (error) {
console.error("Error in fetchArticles procedure:", error);
throw new Error("Failed to fetch articles");
}
}),
});