<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: coCo🙊</title>
    <description>The latest articles on DEV Community by coCo🙊 (@kachi33).</description>
    <link>https://dev.to/kachi33</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1845443%2F71842918-d49a-473b-b32c-4cbb9bce5ffb.jpeg</url>
      <title>DEV Community: coCo🙊</title>
      <link>https://dev.to/kachi33</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kachi33"/>
    <language>en</language>
    <item>
      <title>Your Navbar Should Know Where It Is</title>
      <dc:creator>coCo🙊</dc:creator>
      <pubDate>Wed, 16 Jul 2025 10:34:53 +0000</pubDate>
      <link>https://dev.to/kachi33/your-navbar-should-know-where-it-is-1446</link>
      <guid>https://dev.to/kachi33/your-navbar-should-know-where-it-is-1446</guid>
      <description>&lt;p&gt;Most websites treat the navbar like a billboard. Same logo. Same links. Same everywhere. But what if your site tells a story? Shouldn't the navbar know which chapter we're in?&lt;/p&gt;

&lt;p&gt;I've been building with Nuxt for a while now, and this pattern has become one of my go-to solutions for better UX. Figured it was worth sharing (and hey, what better way to start blogging than with something I actually use in production?).&lt;/p&gt;

&lt;p&gt;If you've worked with React or vanilla projects, you know the pain: building different navigation states usually means either cramming tons of conditional logic into one component or creating separate navbar components and trying to keep them in sync. Route-based detection gets messy, auth state management becomes a nightmare, and you end up with navigation logic scattered everywhere.&lt;/p&gt;

&lt;p&gt;Nuxt's layout system changes the game entirely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxqdrtvvw77z18sj2i1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxqdrtvvw77z18sj2i1f.png" alt="Three different navbar states showing public marketing navbar with login button, minimal auth flow navbar, and full private dashboard navbar with user tools" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Nuxt Makes This Pattern Shine
&lt;/h2&gt;

&lt;p&gt;Here's where Nuxt really shines compared to other frameworks. In a typical React app, you'd probably:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Route-based detection&lt;/strong&gt;: Check &lt;code&gt;useLocation()&lt;/code&gt; and conditionally render different navbars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth state juggling&lt;/strong&gt;: Subscribe to auth changes and update navigation accordingly
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component duplication&lt;/strong&gt;: Or worse, create separate navbar components that drift apart over time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of that complexity disappears with Nuxt layouts. Instead of detecting context, you &lt;strong&gt;declare&lt;/strong&gt; it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/default.vue - Public pages --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"public"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- layouts/auth.vue - Auth flow --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"auth"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- layouts/dashboard.vue - Private app --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"private"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No route detection. No auth state subscriptions. No complex conditional logic. Each layout simply tells the navbar what context it's in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkpm6k93v46j8l1k20oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkpm6k93v46j8l1k20oh.png" alt="Code comparison showing complex React navbar logic with useLocation and useAuth hooks versus simple Nuxt layout approach with type props" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Framework Does the Heavy Lifting
&lt;/h3&gt;

&lt;p&gt;When you navigate from &lt;code&gt;/pricing&lt;/code&gt; (using &lt;code&gt;default.vue&lt;/code&gt;) to &lt;code&gt;/login&lt;/code&gt; (using &lt;code&gt;auth.vue&lt;/code&gt;), Nuxt automatically switches layouts. Your navbar component doesn't need to know anything about routing or authentication - it just responds to the &lt;code&gt;type&lt;/code&gt; prop that each layout provides.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;declarative UI design&lt;/strong&gt; at its finest. Instead of "figure out where you are and show the right thing," it becomes "each layout declares what it needs."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyoca81xgi6kpu27iqq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyoca81xgi6kpu27iqq6.png" alt="Three Nuxt layout files showing default.vue for public pages, auth.vue for login flows, and dashboard.vue for private app pages" width="800" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Context-Aware Navigation Matters
&lt;/h2&gt;

&lt;p&gt;Before we dive into the implementation, let's talk about why this pattern matters for UX:&lt;/p&gt;

&lt;h3&gt;
  
  
  Cognitive Load Reduction
&lt;/h3&gt;

&lt;p&gt;Users shouldn't see dashboard buttons when they're not logged in. They shouldn't see marketing CTAs when they're already paying customers. Every irrelevant link is mental noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clearer Mental Models
&lt;/h3&gt;

&lt;p&gt;When the navbar adapts to context, it reinforces where users are in your app's journey. Public navbar = marketing mode. Auth navbar = focused mode. Private navbar = work mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Conversion
&lt;/h3&gt;

&lt;p&gt;A marketing-focused navbar on public pages can improve sign-ups. A task-focused navbar in the app can improve feature adoption. One size doesn't fit all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The navbar isn't just a static header — it's a narrator that changes tone depending on the scene.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0lxa9379qk1xsmjc4lx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0lxa9379qk1xsmjc4lx.png" alt="User journey diagram showing progression from public pages with marketing focus, through auth flow with minimal distractions, to private app with full navigation" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Design: One Component, Many Faces
&lt;/h2&gt;

&lt;p&gt;Instead of building separate navbars for each context, I use a single component with a &lt;code&gt;type&lt;/code&gt; prop. In my Nuxt app, this gets embedded across different layouts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/default.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"public"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- layouts/auth.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"auth"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- layouts/dashboard.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"private"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic happens inside the component. Same structure, different content based on which layout is calling it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"hydrated"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-base"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Logo adapts to context --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"type === 'public' || type === 'private'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Logo&lt;/span&gt; &lt;span class="na"&gt;:darkMode=&lt;/span&gt;&lt;span class="s"&gt;"isDarkMode"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"type === 'auth'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;CustomLogo&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Navigation content changes completely --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-actions"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Public: Login button + language switcher --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"type === 'public'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;LanguageSwitcher&lt;/span&gt; &lt;span class="na"&gt;variant=&lt;/span&gt;&lt;span class="s"&gt;"secondary-2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;NuxtLink&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;BaseButton&lt;/span&gt; &lt;span class="na"&gt;variant=&lt;/span&gt;&lt;span class="s"&gt;"secondary-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/BaseButton&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/NuxtLink&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="c"&gt;&amp;lt;!-- Auth: Minimal, focused --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"type === 'auth'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;LanguageSwitcher&lt;/span&gt; &lt;span class="na"&gt;variant=&lt;/span&gt;&lt;span class="s"&gt;"primary-2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;BaseButton&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"authStore.isAuthenticated"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"handleLogout"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Logout
        &lt;span class="nt"&gt;&amp;lt;/BaseButton&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="c"&gt;&amp;lt;!-- Private: Full dashboard navigation --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"type === 'private'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;DashboardToggle&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;DashboardNav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hidden lg:block"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;LanguageSwitcher&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;BaseButton&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"handleLogout"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hidden lg:block"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Logout
        &lt;span class="nt"&gt;&amp;lt;/BaseButton&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Profile&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Mobile hamburger menu --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;MobileNavDropdown&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Technical Reality
&lt;/h2&gt;

&lt;p&gt;This isn't just a nice design pattern - it comes with real technical considerations, especially in Nuxt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hydration Mismatch Protection
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;v-if="hydrated"&lt;/code&gt; guard prevents that flash of wrong content during SSR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hydrated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;hydrated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, you might see the server-rendered navbar flicker into the client-rendered version. Not a great first impression.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conditional Styling
&lt;/h3&gt;

&lt;p&gt;Notice how the logo component gets different variants based on context. The auth flow uses &lt;code&gt;CustomLogo&lt;/code&gt; while public/private use the regular &lt;code&gt;Logo&lt;/code&gt; with dark mode detection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;const darkBackgroundRoutes = ['/', '/userType'];
const isDarkMode = computed(() =&amp;gt; darkBackgroundRoutes.includes(route.path));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Beyond the Code: Why This Matters
&lt;/h2&gt;

&lt;p&gt;This pattern taught me something important about component design: &lt;strong&gt;smart UI doesn't just show what the user can do — it reflects where they are and where they're going.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you build context-aware components, you're not just reducing code duplication. You're creating interfaces that feel more intuitive because they mirror the user's mental model of your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintainability
&lt;/h3&gt;

&lt;p&gt;Want to add a new user role? Just extend the &lt;code&gt;type&lt;/code&gt; prop and update the relevant layouts. Need to change the logo across all contexts? Edit one component. The navbar becomes a single source of truth instead of having separate navbar components scattered across your layouts folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layout-Driven Context
&lt;/h3&gt;

&lt;p&gt;Since each layout explicitly passes the &lt;code&gt;type&lt;/code&gt; prop, you get perfect context awareness without complex routing logic. Your &lt;code&gt;default.vue&lt;/code&gt; layout handles public pages, &lt;code&gt;auth.vue&lt;/code&gt; handles authentication flows, and &lt;code&gt;dashboard.vue&lt;/code&gt; handles the private app experience. The navbar just needs to know which layout is calling it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74o7cuk4spztf86e2e7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74o7cuk4spztf86e2e7m.png" alt="Three benefit cards highlighting reduced cognitive load, better user experience, and easier maintenance of context-aware navigation" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extensibility
&lt;/h3&gt;

&lt;p&gt;This pattern scales beautifully. I've extended it to handle admin panels, different user roles, and even A/B testing different navigation structures. The component grows with your app's complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;Your navbar might seem like a small detail, but it's one of the few elements users see on every page. Making it context-aware sends a subtle but powerful message: "This app knows where you are and what you need."&lt;/p&gt;

&lt;p&gt;Most users won't consciously notice a well-adapted navbar. But they'll definitely feel the difference between an interface that feels smart and one that feels like it's stuck in one gear.&lt;/p&gt;

&lt;p&gt;What would your navbar say if it could talk? Mine would say: "Welcome" on the homepage, "Focus" during login, and "Let's work" in the dashboard.&lt;/p&gt;

&lt;p&gt;What story is your navbar telling?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you implemented context-aware navigation in your apps? What challenges did you face? I'd love to hear about your approach in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ux</category>
      <category>nuxt</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
