Conditional Footer in Next.js: Keep the Client Small
Hiding the footer on a chat route without giving up server rendering, using the composition pattern from the Next.js docs.
TL;DR
Hiding a site footer on a full-height chat page, the author rejected CSS display hacks and demoting the whole layout to a Client Component. Instead, a tiny ConditionalFooter client wrapper uses usePathname to return null on /ai routes while the server-rendered Footer passes through as children. Lesson: keep client conditions in small leaves and slot Server Components in as children.
My /ai chat page is full-height, borderless, and flush to the viewport. It finally felt like a proper workspace. Then I scrolled down and met the long site footer hanging below it, like a tailored suit worn with flip-flops. A workspace wants a clean canvas, not a credits column.
My first two ideas were shortcuts. Hide the footer with CSS on that route, or turn the layout into a Client Component so it can read the route anywhere. Both work, and both pay rent I refuse to cover. CSS only closes my eyes: the footer still ships in the HTML, rendered and delivered, just pretending not to exist. Demoting the whole layout to a client component wastes the architecture for one small conditional: the entire server-rendered tree pays so a single if can run.
The right pattern: a small client, the server as children
The fix was already written down in the Next.js docs. You can pass Server Components as a prop to a Client Component, and the common pattern is to use children as a slot; the Server Component is rendered on the server ahead of time, even when passed as a prop [10]. So I made ConditionalFooter: a leaf client component, about 13 lines, with one job, cutting the render on chat routes:
'use client';
import { usePathname } from "@/i18n/navigation";
export default function ConditionalFooter({{ children }}: {{ children: React.ReactNode }}) {{
const pathname = usePathname();
if (pathname === "/ai" || pathname.startsWith("/ai/")) return null;
return <>{{children}}</>;
}}
And the wiring stays in a server layout:
<ConditionalFooter>
<Footer />
</ConditionalFooter>
The Footer remains a full Server Component, server-rendered on every other page. The "we are on the chat page" condition lives only in the small wrapper, through usePathname, a Client Component hook that reads the current URL pathname [8]. My commit message says it exactly: ConditionalFooter wraps the server Footer as children and returns null on /ai routes, every other page keeps the footer [9].
Why this makes sense
The rule of thumb is in the docs too: add 'use client' to specific interactive components instead of marking large parts of your UI as Client Components [10]. ConditionalFooter satisfies that from both directions. It is the smallest client component possible, and it carries the server component as a child instead of dragging the parent down to the client.
One research footnote with teeth: many tutorials still link the old composition-patterns URL, which now redirects to the server-and-client-components page. This is not an exotic trick; it is the documented, recommended way, the address just moved. The reusable lesson from an hour of UI tidying: client-side conditions belong in a small leaf, and an expensive Server Component should always slip in through a slot as children, never get demoted to a client for the sake of one conditional.
Sources
- [10] Next.js Docs: Server and Client Components, accessed 2026-09-07 (wayback snapshot 2026-08-30)
- [8] Next.js Docs: usePathname, accessed 2026-09-07
- [9] Commit 2070723: hide footer on the /ai chat page, accessed 2026-09-07