Next.js Discord

Discord Forum

Should the sidebar be client or server side

Unanswered
Briard posted this in #help-forum
Open in Discord
BriardOP
I’m using a single sidebar component for both the admin dashboard and user layout by passing isAdmin as a prop. My question is:

🛠 Should the sidebar be rendered on the client side or server side?

If I pass isAdmin as a prop (<AppSidebar isAdmin={true} />), would it be better to handle it on the client side?
If I access isAdmin through the session, should it be fetched on the server side?
📌 Which approach is better: passing isAdmin as a prop or accessing it through the session?

for example

admin dashboard
<AppSidebar isAdmin={true} />


project dashboard
<AppSidebar isAdmin={false} />


the part where im using the permissions and isAdmin property from the layout instead of session
 <Sidebar {...props}>
      <SidebarHeader>
        {isAdmin ? (
          <SidebarMenuItem className="mt-4 list-none">
            // showing the logo here
          </SidebarMenuItem>
        ) : (
          <SidebarMenuItem className="list-none space-x-2">
            <ProjectSwitcher projects={projects} />
// we are using admin property
            <Link
              href={userIsAdmin ? "/admin" : "/dashboard"}
              className="text-sm"
            >
              Go Back
            </Link>
          </SidebarMenuItem>
        )}
      </SidebarHeader>
      <SidebarContent>
        <SidebarNavigation
          sidebarItems={isAdmin ? sidebarItemsAdmin : sidebarItemsProject}
        />
      </SidebarContent>
      <SidebarRail />
    </Sidebar>

34 Replies

@Briard I’m using a single sidebar component for both the admin dashboard and user layout by passing isAdmin as a prop. My question is: 🛠 Should the sidebar be rendered on the client side or server side? If I pass isAdmin as a prop (<AppSidebar isAdmin={true} />), would it be better to handle it on the client side? If I access isAdmin through the session, should it be fetched on the server side? 📌 Which approach is better: passing isAdmin as a prop or accessing it through the session? for example admin dashboard tsx <AppSidebar isAdmin={true} /> project dashboard tsx <AppSidebar isAdmin={false} /> the part where im using the permissions and isAdmin property from the layout instead of session tsx <Sidebar {...props}> <SidebarHeader> {isAdmin ? ( <SidebarMenuItem className="mt-4 list-none"> // showing the logo here </SidebarMenuItem> ) : ( <SidebarMenuItem className="list-none space-x-2"> <ProjectSwitcher projects={projects} /> // we are using admin property <Link href={userIsAdmin ? "/admin" : "/dashboard"} className="text-sm" > Go Back </Link> </SidebarMenuItem> )} </SidebarHeader> <SidebarContent> <SidebarNavigation sidebarItems={isAdmin ? sidebarItemsAdmin : sidebarItemsProject} /> </SidebarContent> <SidebarRail /> </Sidebar>
🛠 Should the sidebar be rendered on the client side or server side?

If you plan for the sidebar to dynamically change on runtime, then your sidebar can utilize the "use client" directive. This will make it so that under the right condition, it can render your <AppSidebar> component in the server and hydrated again in the client.

Making it just render on the client-side is suboptimal due to potential flash of no-js
Making it just render on the server-side is also suboptimal due to the need to request server again to change the state of the sidebar.

📌 Which approach is better: passing isAdmin as a prop or accessing it through the session?

Passing isAdmin as a prop.

Your AppSidebar component is one that just "react" to props and have it decoupled with your data fetchings. Use "use client" here.

Then your appSidebar component will receive props that either fetched through client, and/or also have initial state from the server. This way your AppSidebar component can be prerendered in the client, while also reactive to changes in the client side.
They will! it will then be passed into a client component and you are not losing any SSR benefit (if you need any)
BriardOP
actually its just a system so im not sure if i even need any SSR benefits or not
well thats not fun right? for the spirit of the quiz if that is the model you prefer, then its 100% aligned with what i said
but yes. sometimes we dont need SSR
but that still doesn't change my answer
the idea is to have your rendering decoupled from the source of the data.
the idea is to have composable component regardless where the prop came from
BriardOP
actually for managing authentication and authorization
i have done this approach , using middleware
it may look stupid

export async function middleware(request: NextRequest) {
  const path = request.nextUrl.pathname;

  const { data: session } = await betterFetch(
    "/api/auth/get-session",
    {
      baseURL: request.nextUrl.origin,
      headers: {
        cookie: request.headers.get("cookie") || "", // Forward the cookies from the request
      },
    }
  );

  const isOnAdminPage = path.startsWith("/admin");
  const isOnDashboardPage = path.startsWith("/dashboard");
  const isOnSignInPage = path.startsWith("/sign-in");
  const isAdmin = session?.user?.role === "admin";


  // If no session, redirect to sign-in
  if (!session && !isOnSignInPage) {
    console.log("No session found. Redirecting to /sign-in...");
    return NextResponse.redirect(new URL("/sign-in", request.url));
  }
  if (session) {
    //   If authenticated and on sign-in page, redirect based on role
    if (isOnSignInPage) {
      const redirectTo = isAdmin ? "/admin" : "/dashboard";
      console.log(
        `Authenticated user detected. Redirecting to ${redirectTo}...`
      );
      return NextResponse.redirect(new URL(redirectTo, request.url));
    }
    // If non-admin tries to access /admin, redirect to /dashboard
    if (isOnAdminPage && !isAdmin) {
      console.log("User is not an admin. Redirecting to /dashboard...");
      return NextResponse.redirect(new URL("/dashboard", request.url));
    }
    // If admin tries to access /dashboard, redirect to /admin
    if (isOnDashboardPage && isAdmin) {
      console.log(
        "Admin trying to access /dashboard. Redirecting to /admin..."
      );
      return NextResponse.redirect(new URL("/admin", request.url));
    }
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/admin/:path*", "/sign-in", "/projects/:path*", "/dashboard"], // Middleware applies to all /admin routes & sign-in page
};
thats irrelevant to the rendering :D
BriardOP
i know this is different question ,
but it's kinda the way i dont need ssr
what about your way of not needing ssr?
BriardOP
maybe i understood wrong but we just need ssr for managing the session for authorization and since i managed this using middleware, hence i dont need any ssr components
ideally
you shouldnt do fetches in middleware
next's middleware isn't designed for that (i know its stupid)
best to leave middleware as a front-line naive defense (only check for token's presence)
then you do the fetching part or getserversession part in page.tsx
then you can just pass the result into a client component, which is, lucky for you, or not, is also pre-rendered in the server for convenience :D
const session = getAuth() 
// read cookie in server, fetch to external if required
return (
  <MyApp session={session} /> {/* your app, not RSC. *}
)
BriardOP
its weird that betterauth did the fetch in the middleware
@Briard its weird that betterauth did the fetch in the middleware
"if you need the full session object"
props for completeness
@alfonsus tsx const session = getAuth() // read cookie in server, fetch to external if required return ( <MyApp session={session} /> {/* your app, not RSC. *} )
BriardOP
thanks for answering btw, should i do this on my layout.tsx in my root folder ? but it will get passed to all components which i think is not a good thing
No, you shouldnt do auth check in layouts due to partial rendering in soft navigations
layouts should consists only layout related stuff like UI and slots, while critical datas should be fetched at page.tsx
BriardOP
so since i have 4 layout , login , employe dashboard, admin dashboard , projects dashboard (for admin and employee)
it can be in those 4 places and run redirecting there
btw thanks for those valuable information
yes i hope you see the reasoning why instead of blindly trusting me (not assuming you are), that way i can learn too
@Briard so since i have 4 layout , login , employe dashboard, admin dashboard , projects dashboard (for admin and employee) it can be in those 4 places and run redirecting there
Ideally in every page.tsx. But then again, you can still get away by putting Client Auth checks in layout.tsx. Those are fine
@alfonsus Ideally in every page.tsx. But then again, you can still get away by putting Client Auth checks in layout.tsx. Those are fine
BriardOP
actually i just saw that putting auth logic in layout.tsx is worst too cause in some cases layout.tsx get rendered once https://www.youtube.com/watch?t=195&v=kbCzZzXTjuw&feature=youtu.be
i will close this thread and open another one