Engineering Lab 04
A narrow Client Component around a server-rendered navigation
Question: Can an interactive global navigation stay mostly outside the client-side React surface?
Finding: The navigation markup is rendered by a server component while a separate client enhancer owns browser-only behavior and returns no visible markup of its own.
Evidence source
What this note is grounded in
These labels identify the implementation or verification surface used for the observation. They are not a claim that the result generalizes to every website.
Client-only enhancer
Native dialog behavior
Global navigation is a useful place to examine client boundaries because it is visible everywhere and genuinely interactive.
The menu needs browser behavior.
That does not mean the entire navigation has to become a Client Component.
The split
The main navigation component renders the actual markup:
- logo
- primary links
- service links
- mega-menu structure
- mobile dialog
- buttons and labels
It does not declare "use client".
A separate NavbarEnhancer component does.
The enhancer uses the current pathname, effects, DOM events, requestAnimationFrame, timers, and native dialog methods to add interaction to markup that already exists.
The enhancer returns null.
That means its job is behavior, not document structure.
What the client layer owns
The client enhancer handles things the server cannot know or do at render time:
- current browser path state
- scroll position
- opening and closing the services menu
- pointer events outside the menu
- Escape-key behavior
- focus restoration
- mobile dialog open and close state
- body scroll locking
- viewport breakpoint changes
- active link state
- cleanup of listeners and timers
Those are legitimate browser responsibilities.
What stays server rendered
The actual links and navigation structure do not need browser state to exist.
A crawler, assistive technology, or browser receiving the initial HTML can see the primary navigation without waiting for React to create it from scratch.
The page therefore gets the semantic structure first and the enhancement layer second.
Why use native dialog behavior
The mobile navigation uses a dialog element and calls showModal() when opening.
That gives the browser native modal behavior instead of recreating every aspect of a modal from generic div elements.
The client code still manages transitions, focus targets, outside clicks, and cleanup, but the underlying element has semantics designed for the job.
This is a recurring preference in our code: use browser capabilities when they can reduce the amount of custom behavior we have to own.
Cleanup is part of the boundary
Client-side behavior creates obligations.
The enhancer adds scroll listeners, keyboard listeners, pointer listeners, media-query listeners, timeouts, and animation frames.
Its effect cleanup removes or cancels them.
That matters because a narrow client component is only useful if it also contains the lifecycle of the behavior it introduced.
What this proves and what it does not
This example proves the architecture of the boundary.
It shows that server-rendered markup and client-side interaction do not have to be the same component.
It does not prove that every website should use direct DOM event listeners instead of React state. A different interaction could be clearer with stateful components.
The broader point is that the browser-side surface can match the interaction instead of automatically swallowing the whole page.
Why this matters on a marketing site
The navigation exists on every route.
If the global shell becomes unnecessarily heavy, that cost follows every service page, article, case study, and documentation page.
Keeping the interactive layer focused helps protect the rest of the site from inheriting runtime it does not need.
See server first instead of client first for the larger architecture rule.
Related documentation
Go from the observation to the standard
Why our marketing sites are server-first instead of client-first
Why we prefer server-rendered and statically generated content for business websites, then add client-side React only around the interactions that truly need browser state.
Why we keep Client Components small
Why browser-side React stays limited to the interactions that need state or browser APIs while the rest of the page remains server rendered.
Server Components and Client Components
One of the biggest architecture decisions in a modern Next.js site is deciding what needs to run in the browser and what does not.