Subscribing to real time events in nextjs
If:
1. my component is rendered on the client-side
2. AND I'm using either:
import { createClient } from '@supabase/supabase-js';
OR
import { createBrowserClient } from '@supabase/ssr'
to create a supabase client within that component
3. AND I have a column in my table (app_request_logs) called
user_id with foreign key to auth.uid
4. AND I have enabled realtime & RLS
5. AND I've added (through the ui) the canned policy: Enable users to view their own data only
6. AND i've implemented subscription to real time events within useEffect hook
Should the authenticated user expect to see events, written to my table app_request_logs, by that same authenticated user?
My current logic does work when RLS is disabled...it does not work when RLS is enabled with those two policies.
I've used supabase realtime before but in js not nextjs and not sure if I'm missing something? Note my working version outside of nextjs parsed the supa_token on the server side for the user. I'm not sure if I need to specifically do something with user jwt in nextjs (which btw is not in the user payload) from supabase.auth.getUser();62 Replies
if i add this canned policy from the UI:
I pick up events again...
š
You probably don't have a user session when you connect in your useEffect. The supabase client making the realtime call has to have a user session AND keep getting refreshed sessions.
If you are using SSR all clients have to use SSR (browser client in this case) except for service_role.
Many here have used next.js with subscriptions in the browser client and in useEffect. The main issue is if you use the same channel name in 2 useEffects then when you change pages they conflict and you lose connection. But you are not losing connection, just don't have a session.
hmm
so my
page.tsx
fetches the authenticated user via:
import { createServerClient } from '@supabase/ssr'
the page renders 2 client-side components:
but only one of these components instantiates a supabase client
which is instantiated with:
import { createBrowserClient } from '@supabase/ssr'
that is the component where i :
You'll have to see if a next.js user comes along. But you could do auth.getSession() maybe in the useEffect to see if you have a session. I really don't know how SSR would update the session from the cookie in a useEffect. It may just work.
would you recommend another pattern inside nextjs? like supabase-js or auth helpers?
No. Supabase-js would not exchange with serverside and auth-helpers is really deprecated. People are using realtime on the browser client with SSR and next.js. And they have code in the useEffect in some cases. There are discussions here... finding them though with Discord search is tough. Might check github discussions also. Sorry not much more help.
ok looking...thanks
just to confirm, you're saying i should not be using
supabase/auth-helpers-nextjsthx looking
Auth Helpers | Supabase Docs
Server-Side Auth guides and utilities for working with Supabase.
Note the deprecated comment. That has been for over a year.
there must be a pattern that works for ssr, and if there is there's no documented way to do it without resorting to helpers
every solution i've found 6months+ old on reddit, etc is helpers
@silentworks (when you get up in the morning) can you comment on your knowledge of SSR working with realtime... I don't see any reports of issues and have had several users using next.js and realtime in the past year... but I can't find anything in searches that makes it clear SSR versus old auth-helpers. Sort of would be shocked if the realtime useeffects questions here the past year are auth-helpers original...
i'm assuming i'm wrong...though i'm not finding a working example of ssr and rls...though i am finding the answer to ssr and rls issues is supabase-js and auth helpers
still looking...
It really is only a matter of the session getting to the browser client. That client has to be updated on refresh of the token even you signin server side. And SSR does that as you can make API calls from the browser even if signed in from the server. So I would expect it to work. I just don't know about useEffect and how the client gets updated later.
There are no issues that I know of and ssr and auth-helpers are virtually the same except in the way they handle cookies.
@zerofactorial do you know if the subscription succeeds? Like if you do something like
Do you get "SUBSCRIBED" in the browser console?
Also in the same useEffect what does logging
auth.getSession() give you?
If the component mounts before the user logs in you'll have to revalidate the router cache@Marcus on page load:
this returns:
and
supabase is created with createBrowserClient from supabase/ssr?
what happens if you hard refresh the page in the browser, what's logged then?
Depending on how you log in, the client router cache might not get revalidatedsupabase is created from:
hard refresh on the page console logs:
So still no session, but it works fine server side right? Or? I mean the session not realtime obviously..
What does your login flow look like?
let me check on the server side
login:
signup:
these use:
which is from supbase docs:
server side rendering on the page returns:
š
no idea why
meanwhile i'm able to reach this pag
Okay but then it has nothing to do with realtime I guess? Because if you're not getting a session either server side or clientside then the login isnt even working? Unless you have verified elsewhere that logging in actually works?
meanwhile i'm able to reach this pagYou didnt share anything that would block a unauthed page visit, like a middleware
My suggestion on this from the start was there was not a session as realtime worked with RLS off.
@Marcus here's my
utils/supabase/middleware.ts which is from supa docs:
root middleware.ts:
i believe the supabase middleware forces redirect with no userYes I just thought the question about getSession was never answered, that's why I asked again.
I'm glad someone using Next.js had some suggestions.
@zerofactorial when you log in, and you're redirected to
/ what if you log getSession and getUser in your root page.tsx?
Also check if you have any cookies at all in the browserchecking...
here's what i did:
1. logout
2. login
3. redirects to /reviews/page.tsx that renders on server
4. that render console logs:
my session:
my cookies:
so i'm auth'd, i have a cookie and no session
@Marcus is there supabase/nextjs docs that you use to implement this that you can point to where auth and session works as expected?
i'm seeing multiple examples from supabase docs and supabase youtube
https://supabase.com/docs/guides/auth/server-side/nextjs?queryGroups=router&router=app
this one should work fine without any issues.
yeah that's what i'm using
ugh
Btw I assume your login and signup methods are server actions with 'use server' directive
checking...
yeah they're in actions.ts with
"use server";
see any issues with this:
I dont know the only thing I have left, is if the supabase client you're using to retrieve the session is not the right, but I think we went over this.
No lgtm, i'm on ssr 0.4 and react 19 next 15.0.3 if you want to test but seems highly unlikely
Are you running against a hosted sb instance or local?
hosted sb
what does the auth logs say on it when you log in?
I wonder if a user without confirmed email address will give you the user but not give you a session, I have no idea but worth a check
interesting...i'm not requiring confirmed email
let me flip that on and try
Then it's unlikely I guess, but if that doesn't work, check the logs, if that doesnt give you anything I'd spin up a barebones next app do the tutorial on it, make it work with the session, and then move things over and see where it breaks
yeah that didn't work...i'll create a new app and check
ok clean project created with:
npx create-next-app --example with-supabase with-supabase-app
and realtime still doesn't work
pretty sure i haven't misconfigured this
even on the supabase hosted side
now i'm going to spin up a new supabase project
and try thatThere is a realtime test UI in the dashboard that can test your setup including the RLS for users.
checking...
wow this a great feature...had no idea it was there
also something i've never seen before is two categories under
Publications
supabase_realtime
supabase_realtime_messages_publication
my older projects don't include the latter
yep, the UI in the dashboard is showing messages for my authenticated user
i don't get itThe new publication is for the ability to send messages thru broadcast RLS from the DB.
Have you tried putting a select call to a table before your subscription to at least see if select RLS is working for an authenticated users. Not sure if you resolved the getSession returning null which is a no go on either.
let me try the select call...
this is a brand new nextjs app so i'm just using the boilerplate...i assumed it all should work the way it's supposed to using ssr
yep confirmed that select works...it also worked in the prior nextjs app
it only returns the authenticated user's logs
It works in the useEffect?
no
server side
yeah let me try useEffect
Right but we are worried about the realtime client which is different that the serverside client, but SSR should keep them in sync.
yep select works in useEffect
That is progress at least as I assume getSession would now too.
What is your current RLS call and are you still logging subscribe?
Does realtime work with RLS off still?
yeah it works with rls off
re:
What is your current RLS call and are you still logging subscribe?
are you asking for my code?Just the realtime call. Although RLS select would be useful too.
i'm at the point where i don't think it's me anymore
it's:
documentation
or
nextjs+supabase
this is crazy
And your working select was right before const channel...
yep...working select is just above the subscription useEffect:
No I mean in the useEffect.
And a I mean supabase.select(*).from('table').
right working select withing useEffect is above:
well, i'm calling from an api within app/api/../route.ts
let me try using that client directly
That is the client I'm worried about not another one.
yeah
nothing
and getSession there has a session?
using that client within useEffect doesnt work on select
checking..
useEffect doesn't fire
turning off rls...rechecking
Adding this without your response as I've got to go for awhile:
We are back to I'm of no help. You have to have a session in the client. Maybe your useEffect is not in the right place to do this. Happening before cookies are ready for the browser?
People use useEffect with next.js and realtime here and many posts with it. But I hate next.js and bailed 3 years ago to SvelteKit so just don't know what it might be.
yeah no session
ok thanks for you help...curious what @Marcus thinks when he's on
@garyaustin I switched to svelte...which i don't know (but chatgpt knows)
and it works
is there documentation on using:
with useEffect?
I'm not finding a single example
@zerofactorial i dont quite understand, the "select" you shared in useEffect calls an api endpoint so that should be a server client fetching the data on the server right, client fetch() -> server -> createServerClient -> response. So that would not prove a session is available on the client.
You mention that the useEffect isnt firing, I dont know if you mean at all or just the realtime. But if you can't even log to the browser console then it's not mounted at all
This one if you can log a static console log message but cannot log
.getSession() with the same client as for the realtime channel, then the problem is elsewhere, in the login flow or you're losing the session somewhere
Happy to take a look at the new repo if you push it