DEV Community

Cover image for Configuring Clerk.io on t3 with tRPC
The Sword Breaker
The Sword Breaker

Posted on

1

Configuring Clerk.io on t3 with tRPC

Writing because I did not find doc for setting clerk on the app router



Hey there! I was building an app using the T3 stack and decided to integrate the new auth provider clerk.io with t3 instead of nextAuth (which turned out to be a big mistake).

Clrek

Unfortunately, it wasn't as developer-friendly as they claimed. (Only a few devs were harmed during the process.)




I encountered an issue when trying to add a clerk to trpc. I was following a clerk offical guide. The code provided works for a page router with trcp and not the app router.

/* server/context.ts */  

import * as trpc from '@trpc/server'
import * as trpcNext from '@trpc/server/adapters/next'
import { getAuth } from '@clerk/nextjs/server'

export const createContext = async (opts: trpcNext.CreateNextContextOptions) => {
  return { auth: getAuth(opts.req) }
}

export type Context = trpc.inferAsyncReturnType<typeof createContext>
Enter fullscreen mode Exit fullscreen mode

In createContext definition,

CreateNextContextOptions is used to obtain the req, which is a pattern in the page router. At that time I did not know that. I tried to find different solutions but none worked



After a few thrilling adventures of TS Debugs of ...

  • ๐Ÿคธโ€โ™‚๏ธ Type Gymnastics

  • ๐Ÿ” Issue Hunting
  • ๐Ÿ’ป Blog Screening



and searching several Discord threads, I found something that works.







I'm using a completely new method from their updated API, which is not present in any older blogs. I hope they point out the correct way for the app router in the guides soon. Until then, try the following code.

/* server/trpc.ts */  

import { currentUser } from "@clerk/nextjs";
import { initTRPC, TRPCError } from "@trpc/server";
import superjson from "superjson";
import { ZodError } from "zod";

import { db } from "~/server/db";

export const createTRPCContext = async (opts: { headers: Headers }) => {
  const user = await currentUser();

  return {
    db,
    user,
    ...opts,
  };
};
Enter fullscreen mode Exit fullscreen mode

// check if the user is signed in, otherwise throw an UNAUTHORIZED code
const isAuthed = t.middleware(({ next, ctx }) => {
  if (!ctx.user?.id) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({
    ctx: {
      user: ctx.user,
    },
  });
});

export const protectedProcedure = publicProcedure.use(isAuthed);

Enter fullscreen mode Exit fullscreen mode

It's taken from this the very long hybrid discord thread but it works.

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how theyโ€™re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (4)

Collapse
 
pieralukasz profile image
Lucas Piera โ€ข

<3

Collapse
 
2probro profile image
2ProBro โ€ข

I also spend 3 days trying to figure this out, but I didnt.

Until I found this, thank you so much.

Hopefully Clerk gets added to the T3 Stack setup

Collapse
 
enam_solaimani_ef3018592e profile image
Enam Solaimani โ€ข

Just pass the User instead of the auth object, genius. Thanks!

Collapse
 
posivibez profile image
Tyler Gumb โ€ข

omg thank you so much ๐Ÿ™
was struggling getting this up to date for app router with this for a couple hours now
appreciate it!

Retry later