Remix Layouts — Shared UI Across Routes
In this tutorial, you will learn about Remix Layouts. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Remix layouts: create shared layouts for groups of routes, use the root layout for the HTML shell, and combine nested layouts for complex page structures.
In this lesson, you'll create layout routes that wrap groups of pages, configure the root layout for global HTML structure, and nest layouts for multi-level shells.
What You'll Learn
How the root layout works, create layout routes with _layout.tsx, use <Outlet /> for nesting, and apply layouts to route groups.
Why It Matters
Layouts prevent code duplication. A header, footer, or sidebar defined once in a layout is shared across all routes that need it.
Real-World Use
DodaZIP's app uses a root layout for the HTML shell and meta tags, an auth layout for login/register pages, and an app layout for authenticated pages.
flowchart TD
A[root.tsx] --> B[Auth Layout]
A --> C[App Layout]
B --> D[Login Route]
B --> E[Register Route]
C --> F[Dashboard Route]
C --> G[Profile Route]
style A fill:#121212,color:#fff
Root Layout
app/root.tsx is the top-level layout:
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
export default function Root() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
Every page on your site renders inside this root layout.
Layout Routes with Underscore
Create a layout that applies to a group of routes:
app/routes/_auth.tsx:
import { Outlet } from "@remix-run/react";
export default function AuthLayout() {
return (
<div className="auth-layout">
<div className="auth-container">
<Outlet />
</div>
</div>
);
}
Routes in the same directory inherit this layout:
app/routes/_auth.login.tsx → /login
app/routes/_auth.register.tsx → /register
Both routes render inside the _auth.tsx layout's container.
Layout with Loaders
Layouts can have their own loaders:
import { json } from "@remix-run/node";
import { useLoaderData, Outlet } from "@remix-run/react";
export const loader = async () => {
return json({ siteName: "My App" });
};
export default function AppLayout() {
const { siteName } = useLoaderData<typeof loader>();
return (
<div>
<header>{siteName}</header>
<Outlet />
<footer>Built by DodaTech</footer>
</div>
);
}
Combining Layouts
Nest layouts for complex shells. The root layout wraps everything, the app layout adds header/footer, and individual route layouts add sidebars.
Common Mistakes
- Not exporting a default component from a layout: Layouts must export a default function component that includes
<Outlet />. - Using layouts for single routes: If only one route needs a wrapper, add the wrapper directly in the route component instead of creating a layout.
- Forgetting
<Scripts />: Without<Scripts />in the root layout, Remix's client-side JavaScript won't load. - Hardcoding meta tags in layouts: Each route should contribute its own meta tags. Use the
metaexport for per-route SEO.
Practice Questions
What is the purpose of
root.tsx? Answer: It's the top-most layout that renders the HTML document shell, including<html>,<head>,<body>, and Remix's client-side scripts.How do you create a layout for a group of routes? Answer: Create a file with an underscore prefix, like
_auth.tsx. Routes sharing that prefix render inside it.What must every layout component include? Answer:
<Outlet />to render child route content.Can layouts have loaders? Answer: Yes. Layout loaders fetch data needed by the layout, like site metadata or user information.
Challenge
Create three layouts: a root layout with HTML shell, a marketing layout for the homepage and about page, and an app layout for authenticated pages with header and footer.
Mini Project
Build a site with separate layouts for public pages (landing, about, contact) and authenticated pages (dashboard, profile, settings). The authenticated layout should include a sidebar with navigation.
FAQ
What's Next
Learn about Remix Loaders for server-side data fetching in routes.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro