🔥Next-Firebase

Server Side Authentication

In this project, a session based server side authentication using firebase/auth is demonstrated. Visit the github repo or the blog post for details.

You may clone the repo and start your own project ready to handle firebase auth.

> git clone https://github.com/donis3/next-firebase-starter.git

🔸 Route '/' (homepage) Unprotected

This is the homepage. It renders the rootLayout. Suspense is used so server components that needs time to render doesn't block the root layout render.

/* layout.tsx */

<html lang="en">
	<body className="min-w-[300px]">
		<Suspense fallback={<NavigationLoading />}>
			<Navigation />
		</Suspense>
		<main className="container mx-auto">
			<Suspense fallback={<Loading />}>{children}</Suspense>
		</main>
		<Notifications />
	</body>
</html>
					

🔸 Navbar Component (app/_components/Navigation.tsx)

This is a server component that will call a server action to get current auth user if available. It'll display profile and logout links if authenticated and a login link otherwise.

Because of the backend calls, it may take a while to load. If it's not wrapped with a suspense boundary, it'll block the whole root layout and the user will stare at a blank screen. Thats why we provide a suspense and a fallback component that looks like the same navbar but without the auth links.

This is how we fetch the currently authenticated user in a server component. Note that we use getAuthAction() instead of directly importing getCurrentUser from lib/firebase-auth-api.ts.

If the backend code is not called via a server action in a component, revalidatePath may not remove the cache and we might get a stale version of the component. For example, we logout but navbar still shows a profile button like we are still logged in. Fetching data using a server action makes sure the component is revalidated when revalidatePath('/') is called

/* Navigation.tsx > */

export default async function Navigation() {
	const user = (await getAuthAction()) as UserRecord | undefined;

	// ...render component according to user state
	// ...
}