Nested Layouts

Furin uses _route.tsx files for directory-level layouts and route config. Each _route.tsx can point at a parent route, declare loaders, and wrap child pages.

Basic Layout

src/pages/blog/_route.tsx
import { createRoute } from "@teyik0/furin/client"
import { route as rootRoute } from "../root"

export const route = createRoute({
  parent: rootRoute,
  layout: ({ children }) => (
    <div className="mx-auto max-w-5xl px-4 py-10">
      <BlogSidebar />
      <main>{children}</main>
    </div>
  ),
})

Pages inside that directory use the same route object:

src/pages/blog/index.tsx
import { route } from "./_route"

export default route.page({
  component: () => <BlogList />,
})

Root Layout

src/pages/root.tsx is required. It is the top-level route and should render <html>, <head>, and <body>.

src/pages/root.tsx
import { createRoute } from "@teyik0/furin/client"

export const route = createRoute({
  layout: ({ children }) => (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta content="width=device-width, initial-scale=1" name="viewport" />
      </head>
      <body>{children}</body>
    </html>
  ),
})

Multi-Level Nesting

text
src/pages/
├── root.tsx
├── docs/
│   ├── _route.tsx
│   └── advanced/
│       ├── _route.tsx
│       └── plugins.tsx
src/pages/docs/advanced/_route.tsx
import { createRoute } from "@teyik0/furin/client"
import { route as docsRoute } from "../_route"

export const route = createRoute({
  parent: docsRoute,
  layout: ({ children }) => <section className="advanced-layout">{children}</section>,
})

Layout Loaders

Layout data flows into the layout itself and all child pages.

src/pages/dashboard/_route.tsx
import { createRoute } from "@teyik0/furin/client"
import { route as rootRoute } from "../root"

export const route = createRoute({
  parent: rootRoute,
  loader: async ({ request }) => {
    const user = await getSession(request)
    return { user }
  },
  layout: ({ children, user }) => (
    <div>
      <DashboardNav user={user} />
      {children}
    </div>
  ),
})

The page below does not need to repeat the auth/session work:

src/pages/dashboard/index.tsx
import { route } from "./_route"

export default route.page({
  component: ({ user }) => <DashboardHome user={user} />,
})

Comments