Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by PlanetaryCommander382

How can I implement separate public and authenticated navbars in a Next.js 15 app?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I'm working on a Next.js 15 project using the new app folder structure (without a src directory) and need to create two distinct navigation bars:

  • Public Navbar: Visible on landing, login, and signup pages.
  • Authenticated Navbar: Displayed only after the user logs in, such as on dashboard pages.

Should I handle this logic in the global layout (layout.tsx) or create separate, nested layouts for public and authenticated routes? Any code examples or best practices would be appreciated.

I’ve attached a diagram for reference here:
WorkFlow Diagram

1

Comments 0

Answers 3

Views 56

3 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

Below is one common and recommended approach: use nested layouts to separate your public and authenticated UIs. You can create a root layout (app/layout.tsx) that wraps your entire application. Then, for sections that have different navigation (like your dashboard), create a nested layout that renders a different navbar.

For example:

  1. Root Layout (Public Wrapper):
    In your root layout (app/layout.tsx), you could add the public navbar that you want on the landing, login, and signup pages.
TSX
// app/layout.tsx export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body> {/* Public Navbar */} <PublicNavbar /> {children} </body> </html> ) } // You can define PublicNavbar as a Client Component if it has interactive logic.
  1. Authenticated Layout for Dashboard:
    In your authenticated section (e.g., the dashboard), create a nested layout file that overrides the public navbar with the authenticated version. For instance, if your dashboard pages live under the /dashboard route, create a layout inside that folder:
TSX
// app/dashboard/layout.tsx import AuthenticatedNavbar from './AuthenticatedNavbar' export default function DashboardLayout({ children, }: { children: React.ReactNode }) { return ( <> {/* Override nav with authenticated navbar */} <AuthenticatedNavbar /> <main>{children}</main> </> ) }
  1. Routing Behavior:
    • Pages outside of /dashboard (e.g., /, /login, /signup) will fall back to the Root Layout and display the PublicNavbar.
    • Pages inside /dashboard will inherit from the DashboardLayout, which displays the AuthenticatedNavbar instead.

Best Practices

  • Keep Shared UI in Layouts: By leveraging nested layouts, you ensure that only the portion of the UI that changes gets re-rendered on navigation.
  • Client vs Server Components: If your navbars require client-side interactivity (like toggling or state), mark them with the 'use client' directive at the top.
  • Separation of Concerns: Maintain a clear separation between public and authenticated UIs by organizing routes accordingly using the app folder structure.

This approach helps you maintain clear boundaries and ensures that navigation state is preserved during route transitions.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by PlanetaryGuardian775 1 month ago

0

Seems a very simple change can fix this. Dependeing on your global state just use the existence of auth token to check if the user is logged it in the layout file.

If token exists, show logged in users' nav
else show default nav

No comments yet.

Answer by AsteroidEngineer913 1 month ago

0

To show different layouts depending on an arbitrary state or context, you can create a Layout component such as:

Layout.tsx

JAVASCRIPT
import React from "react"; import { useAuth } from "../hooks/useAuth"; import AnonLayout from "./AnonLayout"; import AuthLayout from "./AuthLayout"; const Layout = ({ children }) => { const { isAuthenticated } = useAuth(); return isAuthenticated ? <AuthLayout>{children}</AuthLayout> : <AnonLayout>{children}</AnonLayout>; }; export default Layout;

Then in your main page, you wrap your content with <Layout>.

No comments yet.

Discussion

No comments yet.