Thanks a lot. I am already using the ssr package but didn‘t know if i am right with my implementation. Now it‘s much more clear for me. Thanks a lot! :-)
You're a lifesaver! I am just starting out with Supabase and Next and you were the only one who could make me understand. Does authentication happen the way it was done before?
This is great! Thank you! Quick question: When do we want to use the server client / not the component one? For instance, assume you have a fetchUserData function that takes in an id. While loading a server side page, we should use server component client. When exactly the server client comes in picture? Only the server actions and route handlers?
With NextJS 14, everything runs on the server by default. So only if you explicitly use 'use client'; it will run on the client. So, only then you want to use the createFrontendSupabaseClient. Yes, onlly in Route Handlers and Server Actions you would use the non-serverComponent version - the createSupabaseAppServerClient(); On the server component you'd use createSupabaseAppServerClient(true); or as we simplified createSupabaseServerComponentClient(); Does that help?
@@activenodeSo for realtime Supabase updates where one subscribes to a channel in useEffect hook on a client page/component, I would use createBrowserClient? It seems like I must be missing something since the auth user + channel returns absolutely nothing [] but as soon as I switch to server it works fine (but I need client for realtime) - am I missing some caching or do I just use createBrowserClient?
@@HarisHussain Yes, for realtime you'd be using createBrowserClient when you want to listen to Realtime updates in your UI (you can theoretically work with RT also on the server but it doesn't sound like that's what you want) . Hope that helps!
Should I use supabase/ssr just for Auth related stuff? Clients created by that use cookies so it opts out of caching for every request. What If I want to fetch todos and cache them? Should I use normal "supabase-js" ?
In theory, the same principles apply: For frontend: createBrowserClient, for backend you need to pass the way Svelte handles cookies. You might wanna compare the code here: supabase.com/docs/guides/auth/server-side/creating-a-client?environment=hooks&framework=sveltekit
Hi there!! Thank you for the video it qas really nice.. I’ve setup supabase/srr on my Remix js app. The createBroswerClient and createServerClient works!! But I still not understand the concept between when to use the Broswer one or the Server one.. I know that when it’s for front-end is the Broswer client but I think I would need a real life example to understand both. Anyone can help me?
Yes if it's about the Service Key, definitely! I am using the anon key in my .env.local being NEXT_PUBLIC_SUPABASE_KEY. If you use the admin client, you don't need any of that special stuff I'm showing. In that case make sure it's not prefixed with NEXT_PUBLIC_ - as you said it would be a massive security hole - and just use createClient to create it.
Hey, thanks for this amazing tutorial! I keep getting this error when building my project after following this setup: Static generation failed due to dynamic usage on /orders, reason: cookies I'm exclusively using the app router. My /orders page is a SSR page and calls a function "fetchOrders" before returning its components. This fetchOrders function lives in a server actions file with the "use server" file heading. It queries a pg database using Drizzle, and uses the "createSupabaseServerClient" function to fetch the user id for the database query. I'm unsure how to reliably get the user id of the logged in user for my database queries with this error throwing. Has anyone ran into something like this?
Can you try one thing to troubleshoot? This video shows calling `cookies()` in each function. However, I'm about to make an updated video where I'll be using `const cookieStore = cookies()` in the top of the utils function and then only `cookieStore.get`, `cookieStore.set` etc. So calling `cookies()` immediately will mark the file as "using cookies". Can you try if that helps?
Good question. Well, you can. But the problem is: They won't maintain it anymore in the future. But feature-wise, it's the same thing. Knowing that all of the NextJS Auth Helpers literally do the same thing I found it very confusing to have a different name for each context so once I understood the new package, I found it more convenient. Maintenance-wise I'd say: The sooner you switch, the better. But yes, you probably can stay on the old one for quite some time without any issues. Just saying the dependencies could get old etc
Thanks for the reply. I didn't even see that it's deprecated. I also found it a bit confusing having like 6 ways to create a supabase client. I will refactor it asap.
All of that extra crap was because of nextjs and their hatred for request response model making it hard , other vite frameworks have the request and response accessible in their SSR side nextjs doesn't in server components
Hi Can you please explain what you just mentioned, I'm learning Next js through UA-cam and didn't come across something that you said maybe I did but can't remember.
@@Shashanksoni98 the way you get headers and cookies in nextjs varies significantly from how other SSR frameworks do it causing a lot of pain to anyone building integrations that work on the server and client in nextjs
Hey, thanks for that info. In theory NextJS is on the right track by already using the standardized Response and Request instances with a lil bit of extensions (developer.mozilla.org/en-US/docs/Web/API/Response). But across frameworks, not just NextJS, there is no common standardized way yet to access those. It would be easier if they'd all agree on having req/res globally available in such contexts, then one client would fit it all. Not a NextJS specific problem though :)
@@activenode there's winter CG which is what other frameworks are relying on as a standard , Guillermo recently talked shit about it , the biggest thing I find odd is how it's not possible to access the request context in server component page , you can only access headers and cookies with special functions that rely on async context , you don't get the URL which is funny given how hard they're pushing relying on the URL for state . They're confused and in turn confusing everyone at this point they've even refused to take feedback and add the request object in server components + router events
@@hakuna_matata_hakuna Sorry about the features you are missing, I'm sure collective community feedback will sooner or later lead the path. Thanks for hinting WinterCG, didn't know that one :)
Hi man! Thanks a lot for this tutorial! Which client from the options that we created should we be using for Stripe webhook? eg for the NextJS 14 path: app/api/webhooks/route.ts
Hey! Awesome question: A stripe webhook firing a route handler, doesn’t need RLS usually as it isn’t a person and hence also cookies don’t matter. Usually, with a webhook, you want an admin client. So you need none of the clients really that I show in this video but you would create some like: import {createClient} from ‘@supabase/supbase-js’; function getAdminClient() { return createClient(URL, SERVICE_KEY); }
Thanks for the explanation, excellent. I wanted to ask you in the last part to make client of the middleware, what should I do with the constant "supabase" that we create there, since we return "res" right away, wouldn't a line like: await supabase.auth.getSession() be missing there? Thanks
Ha, good catch. Yeah, it wasn't a mistake, even though it's common to have that, yes. There are certainly use-cases with and without auth that's why I didn't add it there and left it open for anyone to decide what to do with it, you can even just NOT use it in the middleware. But yes, if you do use auth you should be using the line you posted await supabase.auth.getSession() to ensure token freshness :) Cheers!
So, the password reset flow, is nothing but a magic link with type "recovery". That's the short answer. The fully server-based variant works differently than the one with frontend. I'll cover this in my upcoming book (still takes some time) but if you don't NEED the fully server I'd recommend you go with the frontend variant. That goes like this: await supabase.auth.resetPasswordForEmail('hello@example.xyz, { redirectTo: 'example.com/account/update-password', }) This will send an e-mail to hello[at]example.xyz containing something like auth-service-url/?token=...&redirectTo=example.com/account/update-password which, when clicked, will verify the token and immediately redirect to the redirectTo URL but add a small code to it (you don't see that because the process is too fast but if you make your network connection really slow, you can watch it). And on THAT page there must be a frontend client (browser client) instantiated. The pure existence of that authenticates the user - so, obviously it must be a URL that is reachable without a valid login. Then, you want to redirect/refresh the page when the authentication is done. And for that you don't have to do much but listen for the event in the frontend client: supabase.onAuthStateChange(event => { if (event==='SIGNED_IN') refreshOrRedirectPage(); }) Hope that helps.
when the video starts with "It's not you. The problem isn't you.", you know you're in the right place
That was the most important part to highlight
there was no other tutorial so clear and to the point about the supabase/ssr lib (definitely including the own docs lol), thanks a lot
Finally a super clear and helpful tutorial about this! It's better than the docs.
Thanks for sharing 🙌
glad to hear that!
Thanks, most tutorials are outdated, you filled in the gap between the transition form the auth lib to ssr.
Thanks!
Thanks for this one, was confused with the doc and was not that happy to migrate again :) Now that's easy :)
Happy to help!
Thanks a lot. I am already using the ssr package but didn‘t know if i am right with my implementation. Now it‘s much more clear for me.
Thanks a lot! :-)
cant express how helpful this was, thank you very much!
Happy to hear!
Thank you so much for this! It was needed since the auth has changed so many times
Still struggling with dynamic routing. Returning null on my side
You're a lifesaver! I am just starting out with Supabase and Next and you were the only one who could make me understand. Does authentication happen the way it was done before?
Great explanation your tutorials are really EPIC , I love your style in explain concepts , keep going please
perfect one, straight to the point 🎯
Perfect timing and well explained!
Thanks so much
thanks, this helped a lot. I would love a video on how to use these different functions in the app like getting user session etc
So more like a "how to deal with authentication" tutorial?
@@activenode yes!
Immediately subscribed
Great video, keep it up. You just earned yourself a sub :D
Lovely! Have a great week!
This is great! Thank you! Quick question: When do we want to use the server client / not the component one? For instance, assume you have a fetchUserData function that takes in an id. While loading a server side page, we should use server component client. When exactly the server client comes in picture? Only the server actions and route handlers?
With NextJS 14, everything runs on the server by default. So only if you explicitly use 'use client'; it will run on the client. So, only then you want to use the createFrontendSupabaseClient.
Yes, onlly in Route Handlers and Server Actions you would use the non-serverComponent version - the createSupabaseAppServerClient();
On the server component you'd use createSupabaseAppServerClient(true); or as we simplified createSupabaseServerComponentClient();
Does that help?
@@activenodeSo for realtime Supabase updates where one subscribes to a channel in useEffect hook on a client page/component, I would use createBrowserClient? It seems like I must be missing something since the auth user + channel returns absolutely nothing [] but as soon as I switch to server it works fine (but I need client for realtime) - am I missing some caching or do I just use createBrowserClient?
@@HarisHussain Yes, for realtime you'd be using createBrowserClient when you want to listen to Realtime updates in your UI (you can theoretically work with RT also on the server but it doesn't sound like that's what you want) .
Hope that helps!
"If you're not using middleware with app router, then you're dumb" I died haha
OK that is evil subbing there :D
Great video! What theme are you using and font in VS Code? Happy Holidays! 🎄
Hey there! That is: Beautiful Dracula Normal. Same to you 🎊
waay too good video
nicely done!thanks
Great explanation. Supabase documentation for Nextjs keeps getting confusing
Indeed!
Should I use supabase/ssr just for Auth related stuff? Clients created by that use cookies so it opts out of caching for every request.
What If I want to fetch todos and cache them? Should I use normal "supabase-js" ?
Could not understand how to access serverClient in getServerSideProps, can you share an example ?
❤
Which should I use for SvelteKit?
In theory, the same principles apply: For frontend: createBrowserClient, for backend you need to pass the way Svelte handles cookies. You might wanna compare the code here: supabase.com/docs/guides/auth/server-side/creating-a-client?environment=hooks&framework=sveltekit
@@activenodeThanks!
great,thx.
Hi there!! Thank you for the video it qas really nice.. I’ve setup supabase/srr on my Remix js app. The createBroswerClient and createServerClient works!!
But I still not understand the concept between when to use the Broswer one or the Server one.. I know that when it’s for front-end is the Broswer client but I think I would need a real life example to understand both. Anyone can help me?
Isn`t it a security problem to store the supabase keys in the NEXT_PUBLIC env variables? As far as I know those can be read by client side js scripts.
Yes if it's about the Service Key, definitely! I am using the anon key in my .env.local being NEXT_PUBLIC_SUPABASE_KEY. If you use the admin client, you don't need any of that special stuff I'm showing. In that case make sure it's not prefixed with NEXT_PUBLIC_ - as you said it would be a massive security hole - and just use createClient to create it.
👍
Hey, thanks for this amazing tutorial! I keep getting this error when building my project after following this setup:
Static generation failed due to dynamic usage on /orders, reason: cookies
I'm exclusively using the app router. My /orders page is a SSR page and calls a function "fetchOrders" before returning its components. This fetchOrders function lives in a server actions file with the "use server" file heading. It queries a pg database using Drizzle, and uses the "createSupabaseServerClient" function to fetch the user id for the database query.
I'm unsure how to reliably get the user id of the logged in user for my database queries with this error throwing.
Has anyone ran into something like this?
Can you try one thing to troubleshoot? This video shows calling `cookies()` in each function. However, I'm about to make an updated video where I'll be using `const cookieStore = cookies()` in the top of the utils function and then only `cookieStore.get`, `cookieStore.set` etc. So calling `cookies()` immediately will mark the file as "using cookies". Can you try if that helps?
How are you auto importing the imports. Is there browser extension for this?
Steg+space in vscode
I am getting an error that cookies can set in server action or route handler only
When exactly do you get it? What are you doing?
you are beautiful. thank you.
Can you make a video on self-hosting a Next.js app using SST, OpenNext, PM2 and MinIO?
That's actually a cool idea, I'll write it down in the ideation list.
I‘m still a bit confused why shouldn’t I use the nextjs auth helper library
Good question. Well, you can. But the problem is: They won't maintain it anymore in the future. But feature-wise, it's the same thing. Knowing that all of the NextJS Auth Helpers literally do the same thing I found it very confusing to have a different name for each context so once I understood the new package, I found it more convenient.
Maintenance-wise I'd say: The sooner you switch, the better. But yes, you probably can stay on the old one for quite some time without any issues. Just saying the dependencies could get old etc
Thanks for the reply. I didn't even see that it's deprecated. I also found it a bit confusing having like 6 ways to create a supabase client. I will refactor it asap.
@@imbjarne795 awesome
Do you have a repo when I can get the code?
Yes :) github.com/activenode-edu/supabase-plants-migration-demo
a link to a github repo would be nice ;)
github.com/activenode-edu/supabase-plants-migration-demo
hope u did put the source code
github.com/activenode-edu/supabase-plants-migration-demo
supabase docs sucked, code samples sucked. thank you so much
Justin Trudeau????
His lost brother
All of that extra crap was because of nextjs and their hatred for request response model making it hard , other vite frameworks have the request and response accessible in their SSR side nextjs doesn't in server components
Hi
Can you please explain what you just mentioned, I'm learning Next js through UA-cam and didn't come across something that you said maybe I did but can't remember.
@@Shashanksoni98 the way you get headers and cookies in nextjs varies significantly from how other SSR frameworks do it causing a lot of pain to anyone building integrations that work on the server and client in nextjs
Hey, thanks for that info. In theory NextJS is on the right track by already using the standardized Response and Request instances with a lil bit of extensions (developer.mozilla.org/en-US/docs/Web/API/Response). But across frameworks, not just NextJS, there is no common standardized way yet to access those. It would be easier if they'd all agree on having req/res globally available in such contexts, then one client would fit it all. Not a NextJS specific problem though :)
@@activenode there's winter CG which is what other frameworks are relying on as a standard , Guillermo recently talked shit about it , the biggest thing I find odd is how it's not possible to access the request context in server component page , you can only access headers and cookies with special functions that rely on async context , you don't get the URL which is funny given how hard they're pushing relying on the URL for state . They're confused and in turn confusing everyone at this point they've even refused to take feedback and add the request object in server components + router events
@@hakuna_matata_hakuna Sorry about the features you are missing, I'm sure collective community feedback will sooner or later lead the path. Thanks for hinting WinterCG, didn't know that one :)
Hi man! Thanks a lot for this tutorial!
Which client from the options that we created should we be using for Stripe webhook? eg for the NextJS 14 path: app/api/webhooks/route.ts
Hey! Awesome question:
A stripe webhook firing a route handler, doesn’t need RLS usually as it isn’t a person and hence also cookies don’t matter. Usually, with a webhook, you want an admin client. So you need none of the clients really that I show in this video but you would create some like:
import {createClient} from ‘@supabase/supbase-js’;
function getAdminClient() {
return createClient(URL, SERVICE_KEY);
}
@@activenode Thanks a lot! Appreciate your reply :)
Thanks for the explanation, excellent. I wanted to ask you in the last part to make client of the middleware, what should I do with the constant "supabase" that we create there, since we return "res" right away, wouldn't a line like: await supabase.auth.getSession() be missing there? Thanks
Ha, good catch. Yeah, it wasn't a mistake, even though it's common to have that, yes. There are certainly use-cases with and without auth that's why I didn't add it there and left it open for anyone to decide what to do with it, you can even just NOT use it in the middleware. But yes, if you do use auth you should be using the line you posted await supabase.auth.getSession() to ensure token freshness :) Cheers!
Do you happen to have an example of the password reset flow using @supabase/ssr? It would be extremely helpful. Thanks for the content!
I second this
So, the password reset flow, is nothing but a magic link with type "recovery". That's the short answer.
The fully server-based variant works differently than the one with frontend. I'll cover this in my upcoming book (still takes some time) but if you don't NEED the fully server I'd recommend you go with the frontend variant.
That goes like this:
await supabase.auth.resetPasswordForEmail('hello@example.xyz, {
redirectTo: 'example.com/account/update-password',
})
This will send an e-mail to hello[at]example.xyz containing something like auth-service-url/?token=...&redirectTo=example.com/account/update-password which, when clicked, will verify the token and immediately redirect to the redirectTo URL but add a small code to it (you don't see that because the process is too fast but if you make your network connection really slow, you can watch it). And on THAT page there must be a frontend client (browser client) instantiated. The pure existence of that authenticates the user - so, obviously it must be a URL that is reachable without a valid login. Then, you want to redirect/refresh the page when the authentication is done. And for that you don't have to do much but listen for the event in the frontend client:
supabase.onAuthStateChange(event => {
if (event==='SIGNED_IN') refreshOrRedirectPage();
})
Hope that helps.
see my comment for @austingebauer4532
love next but who came up with a cookie api like that one 'cookie().get'? 🤣