A deep dive into T3-Turbo and Clerk
Aug 15, 2023
A deep dive into T3-Turbo and Clerk
In this video, we’re going to take a deep dive into T3-Turbo and Clerk, which will help you create a better mobile experience for your users. T3-Turbo is a powerful template that lets you create dynamic user experiences on your mobile apps and Next.js but it was missing one thing, Mobile Auth. T3-TURBO-CLERK: https://github.com/clerkinc/t3-turbo- … Create-t3-app: https://github.com/t3-oss/create-t3-app Create-t3-turbo: https://github.com/t3-oss/create-t3-t … Julius’s Twitter: https://twitter.com/jullerino Theos original video: • The BEST Starting Point For Your Next… #t3stack #fullstack #webdevelopment Join this channel to get access to perks: / @james-perkins Follow me on: 📃 Website/Blog: https://jamesperkins.dev 👉 Twitter: https://twitter.com/james_r_perkins 👉 Linkedin: https://www.linkedin.com/in/james-per … 👉 Github: https://github.com/perkinsjr 👉 Discord: https://discord.gg/dqYP9Mc 👉 Twitch: https://twitch.tv/jamesperkins
Content
0.17 -> You may have seen the Create T Three
Turbo and Clerk Starter that
3.892 -> Theo made a video on a very short
video.
7.38 -> He barely showed you any of the code
or how it works. And as
11.172 -> the creator of that repo, I'm aiming
to fix that. So let's
14.538 -> take a deep dive into the T three.
Turbo and Clerk starter.
18.282 -> We're going to break this down into
three different sections. First NextJS,
22.53 -> then we're going to talk about TRPC.
And finally,
25.58 -> we're going to finish with Expo. So
the next JS code is found under Apps
29.826 -> and NextJS, once you click it inside
the source, is where you're going
33.228 -> to find all the important information.
Let's start with the middleware.
37.666 -> This middleware is for Clerk. This
allows us to run Auth
41.568 -> checks in API routes, or on the server
side if you're
44.944 -> using SSR or anything like that. What
we're doing here is
48.128 -> making sure that it doesn't run on
static files, but does
51.616 -> run on images and requests for TRBC,
because those are
55.108 -> obviously important. Next up, we need
to talk about EMV files.
59.338 -> So when you use a EMV, we have this
server
62.698 -> check here to make sure you're not
exposing keys to
65.828 -> the public. So if you're using a
server key, like a client secret,
69.31 -> we don't want to put that out into the
world. Again, with our client
72.702 -> here, we want to make sure that we
have the correct kind of keys.
76.43 -> It should be next underscore public.
If it doesn't have that, it will
79.708 -> also throw an error message. And
finally, in our schema here,
83.228 -> this is where we set the keys that we
require. So we do require
87.138 -> a Next Public Clerk Publishable key
and a client secret.
91.106 -> If those aren't included, you cannot
run this application, and it will
94.448 -> throw an error message that makes sure
that you are set up for success.
98.464 -> Moving on from environments, we need
to now talk about pages.
102.294 -> So, in the pages, we have this sign in
and sign up section.
106.186 -> Both of these are just mounted
components here from Clerk, and it
109.588 -> tells us what the path is. And the
sign up URL.
113.498 -> Same for the sign up here. We make it
really easy to just add in
117.028 -> these components, and whatever you put
in the dashboard will show up on the
120.184 -> screen. So if you add Google Auth, it
will just show up. If you require
123.598 -> a username or you require passwords or
phone numbers, whatever it
126.904 -> might be, it just automatically will
be updated to the correct version.
130.866 -> That is our two mounted components.
And then we have our app,
135.004 -> TSX. What we're doing here is wrapping
the whole application in
138.652 -> the clock provider. This clock
provider allows us to access Auth
142.464 -> anywhere in our application alongside
the middleware. So if you
146.048 -> need to check on the client side, if
the user is authenticated,
149.798 -> you can do that. Or you need to check
in the TRPC routes. You can
153.488 -> also do that when it's wrapped up in
this clip provider.
156.97 -> Talking of client side code, let's
talk about the page that
160.148 -> a user sees. So by default it is the
section here. This is
163.988 -> where we grab all the post data and
show it as a card.
167.576 -> And then we have this Auth showcase
which is what handles whether to show
171.272 -> the sign in or to show the user button
and secret message. So let's
174.958 -> look at this Auth showcase. What this
Auth showcase
178.642 -> is doing is checking to see if the
user is signed in.
181.836 -> So, if they're signed in and then
grabbing this data
185.324 -> if they are indeed signed in.
188.33 -> On top of that we then say if they're
signed in, go ahead and show
192 -> this secret message plus click the
user button.
195.328 -> And underneath that we then show the
user button component,
198.694 -> which is very common in things like
Google. When you click it, you can add
201.808 -> more accounts or manage your account.
That's what we show here. And if
205.428 -> they're not signed in, we ask them to
click the sign in button which is
209.188 -> just the next link that directs them
right back to the sign in.
212.532 -> Just our API route here, which is just
using the standard TRPC create NextJS
216.708 -> handler with the router from our API
here,
220.456 -> which is in a separate package and
then making sure that we're using it as
224.152 -> expected. If you need cause, you need
to enable it down here. That's next
227.932 -> JS. Now let's talk about how TRPC is
working.
231.292 -> Behind the scenes packages contains
three folders. The most important are
235.292 -> your DB and your API. The DB holds
Prisma.
238.722 -> If you need to update your Schema,
just go ahead and go to DB prisma,
241.878 -> schema prisma and update the models as
you require. The API is
246.048 -> holds all of TRPC. So we need to talk
about really two
250.112 -> things here. First context and then
secondly the middleware.
253.818 -> So, what context is doing is checking
for a user using
257.876 -> this Get user function. We're using
the Get auth helper
261.242 -> from Clerk which allows you to access
specific parts of
265 -> the Auth state. Then what we're doing
is asking for the
268.248 -> user from our users API and then we're
272.078 -> returning the full user object. And
then obviously we're awaiting
275.71 -> this function here and then we're
returning that to the create inner
279.058 -> context. What's great about this is
when you move to middleware,
283.106 -> it gives you access to check to see if
they have a user object.
286.86 -> If not, they are unauthorized
protecting your routes.
290.438 -> And you can extend this even further
because we have access to the
294.288 -> full user object. You actually have
access to all these different things.
298.448 -> For example, unsafe metadata. You
could store a custom role
301.862 -> in there. And if they have that custom
role, maybe they're allowed to do admin
305.706 -> type thing. Inside our router we have
Auth. So here
309.412 -> we have just two routes. One is Get
sessioned which returns the full user
313.178 -> object in a public procedure and then
we have this Get secret message
316.92 -> which is a protected procedure. Then
in our posts here,
320.52 -> which is our other router, we have
all,
323.976 -> which is a public procedure that gets
all the posts by ID,
327.608 -> get a specific post and finally this
Create and we'll talk about how that all
331.308 -> works in a minute. Finally we just
export all of these out so
334.588 -> that you can add an extendable routers
as you need. And that is TRPC.
339.474 -> So the final piece to this puzzle and
the deep dive is
342.96 -> Expo. Now Expo was the trickiest part
and why this
346.624 -> template even came about. So first we
need to talk about this app TSX.
350.95 -> What you'll notice here is that we're
actually providing the publishable
354.202 -> key to the clerk provider, unlike
NextJS. And we
357.988 -> also have this thing called a Token
cache. What a token cache does is make
361.828 -> sure that the valid JWT is always
available. You can see
365.528 -> the token cache under Utils Cache, but
it's a very basic using Secure
369.854 -> Store from Expo. Secure Store we just
save or
373.112 -> get the token as required. Outside of
that, this looks pretty familiar.
377.134 -> Signed in means that the user has to
be signed in to see these pages
381.09 -> and signed out. This is what they'll
get, which is the sign in and
384.652 -> sign up screen. This is where the true
magic happens.
389.47 -> This component called Sign in with
Auth,
392.528 -> holds the key to how mobile
authentication
395.75 -> work. What we have here is a
completely custom flow. Instead of
399.168 -> using the components that you saw with
NextJS, you get a different
402.724 -> screen that looks like this. Just a
single button that
406.628 -> has sign in. When you click this sign
in with Discord and
411.188 -> you click Continue here you are
presented with this discord button.
415.08 -> You click Authorize and then you'll
redirect it into here.
418.568 -> And then you can publish posts as you
see fit. So if I say
422.408 -> hello, welcome and hit Publish, you'll
see
426.488 -> that this appears up here. So let's
talk about how that sign in
430.252 -> flow works. First we should talk about
these helpers here we have one
433.948 -> called Use Sign in which allows you to
sign in and
437.916 -> set sessions. And of course, Sign up
is the opposite
441.398 -> of this flow. It also contains set
session and is
444.832 -> loaded. But because of the way that
we're handling this and we're using
448.416 -> something called transfer, we only
need to use Sign up
451.536 -> and then one is loaded and set
session.
455.002 -> The first thing we do is check to make
sure that clerk is loaded.
457.466 -> If it's not, we return null. Then once
that
460.692 -> has loaded, we give you this giant
handle sign in with
464.228 -> Discord press. And this is quite
complicated, so I'm going
467.624 -> to break it down piece by piece. First
we create a redirect URL
471.246 -> using Auth session from Expo and we
set it to OAuth native
474.766 -> Callback so that we can grab any
information that we need. So then we create
478.312 -> this promise which is a sign in
resource. We tell it what kind of strategy
481.858 -> we're using. In our case, we're using
discord and we set the
485.564 -> redirect URL to the one we created
here. We then
489.312 -> look for this external verification
redirect URL
493.238 -> from the sign in object. And if we
don't have
496.688 -> one of those, we immediately throw an
error that there's something wrong with
500.432 -> this OAuth flow and this is probably a
misconfiguration
504.554 -> or something else. Then we create this
constant called Auth result.
508.244 -> What we do here is we start an async
Auth session which basically
511.652 -> only allows you to create one Auth
session at a time. We set the Auth
515.256 -> URL to the external verification
redirect URL
518.91 -> and the redirect URL that we have.
Then we check to
522.488 -> see what the Auth result is. So the
user is going through and they're clicking
526.174 -> all the buttons. They click continue
all they sign into their account. If it's
529.55 -> not successful, we throw an error
message immediately. Now I want to point
533.132 -> out here we have a bunch of different
type error messages here that you could
536.588 -> be handling things like dismiss or
canceled. You could
540.076 -> prompt the user to try again because
for some reason they've decided not
543.728 -> to sign in. But we wanted to keep this
as simple as possible. So we're
547.424 -> just saying if it's not successful,
clearly there's an error. Once we have this,
551.328 -> we go and get this rotating nonce from
the redirect URL
555.49 -> and then we reload the sign in
request.
559.33 -> And if there's a created session ID
here so if we manage to create
563.108 -> a session ID, we can then have the
user sign in
566.664 -> immediately. That means they've
already had an account, everything went as
570.456 -> expected, otherwise, if there isn't
574.23 -> a session ID, maybe they are a first
time user.
577.922 -> So then we do this quick check here
and if the status here
581.212 -> is not transferable, we just tell them
that there's an error
584.738 -> message. Otherwise we transfer the
account to sign
588.476 -> up. This means that we're going to
create the user versus trying
591.872 -> to have them log in. What we do here
is set transfer to True.
596.4 -> Now Transfer to True essentially says
we already know everything
600.048 -> about this user, don't send them back
through the flow.
603.062 -> Here is all their information, go
ahead and just create the account.
606.484 -> Then we do the same thing that we did
up here,
609.492 -> which is sign in reload with that
rotating token and
613.188 -> we just get it from the Auth result
versus the original one
617.096 -> because we've created this new sign up
flow. Then we set the session
621.214 -> to the newly created session ID from
the sign up request and
625.192 -> the user is signed in. Then from there
we should talk
628.652 -> about the home screen. When the user
is signed in,
631.564 -> they are allowed to create posts, as
you saw. And what we're doing
635.196 -> here is using this TRPC create use
mutation. And then
638.924 -> we invalidate the posts so that we can
fetch new ones. And that
642.512 -> works just on a standard form. But
what's happening here
646.144 -> is slightly different than NextJS.
Now, if you remember from NextJS,
649.856 -> if we quickly take a look again, we
didn't have to do anything with the
653.264 -> batch link here. We just sent the
request down, and we were smart enough to
656.804 -> be able to go and get off from TRPC
APIs.
660.394 -> But because the expo doesn't have the
same helpers, what we're doing here is
664.372 -> actually sending down, as part of
TRPC, this Auth token.
668.43 -> So what I'm doing here is getting the
token use Auth,
671.88 -> and then I'm sending that down as a
header. And then our
675.848 -> helpers in the TRPC API layer are
smart enough to
679.388 -> say, hey, this is a JWT token that we
own.
682.3 -> We should use that to get the user
from the context,
685.826 -> and then we can use the same flow so
we don't have to write
689.452 -> any additional code. All we have to do
is send down this token.
692.898 -> And this token will always be fresh
because of our token cache, as well
696.732 -> as the way that use Auth works, which
is to grab a token if it's
700.314 -> expired. I hope this really helped you
understand how the T three
703.492 -> turbo and Clark repo works. If you
made it all the way to the end
706.708 -> of the video, YouTube is going to
recommend you something here. Go ahead and
709.748 -> click it. It's algorithm driven. I bet
it'll be a banger. And of course,
713.252 -> if you're not subscribed, click
subscribe right here. I'll see you in the next
Source: https://www.youtube.com/watch?v=G53U1cYxmbo