I've always found Authentication with Single Page Apps to be incredibly confusing, I always try to make use of a starter package that does most of the work for me.
You didn't mention what backend you're using, I'm going to assume Laravel.
Have you seen the official Breeze/Next Starter Kit that Laravel provides?
https://laravel.com/docs/9.x/starter-kits#breeze-and-next
https://github.com/laravel/breeze-next
It assumes you're using the Breeze auth scaffolding for Laravel on the backend and Next.js on the frontend (as separate repos/projects).
On the Next.js side, it's making use of a package called "SWR" to constantly ping an endpoint to check if the user is authenticated. If not, it redirects the user back to the login page. Check out the auth.js hook to see all of the auth logic.
Now, for any pages that you want to be behind a login you can use the auth hook. Check out the AppLayout.js page, specifically const { user } = useAuth({ middleware: 'auth' }).
Give it a try locally, try running both projects and see if you can get logins working correctly.