# Layouts

> What stays around the pages, by directory.

A layout is the part of the page that stays the same from one page to the next: a header, a sidebar, a footer. It
stays mounted while visits move between the pages it wraps, so its state (a scroll position, an open menu) is kept.

## `_layout.tsx`

A `_layout.tsx` in a directory of `app/pages/` wraps every page below it. Its default export is a component that
renders the page as `children`:

```tsx
// app/pages/_layout.tsx: around every page
import type { ReactNode } from 'react'

export default function Layout({ children }: { children: ReactNode }) {
  return (
    <>
      <header>…</header>
      <main>{children}</main>
    </>
  )
}
```

Layouts nest with the directories, outermost first:

```
app/pages/
├─ _layout.tsx           # around every page
├─ index.tsx
└─ docs/
   ├─ _layout.tsx        # around the docs pages, inside the one above
   ├─ intro.mdx
   └─ routes.mdx
```

`docs/intro` is rendered inside `_layout.tsx`, then `docs/_layout.tsx`. Pages written in [MDX](https://fondu.dev/docs/mdx.md) get their
layouts the same way. Read the page and its props in a layout with Inertia's `usePage()`.

## Different layouts for different parts

A page's name is where its file is, and its URL is the route's: the two are independent. So the directories of
`app/pages/` can follow the layouts rather than the URLs:

```
app/pages/
├─ marketing/
│  ├─ _layout.tsx        # the site's header and footer
│  ├─ index.tsx          # rendered by routes/index.ts at /
│  └─ legal/
│     ├─ _layout.tsx     # a narrow column, inside the marketing layout
│     ├─ terms.tsx       # rendered by routes/terms.ts at /terms
│     └─ privacy.tsx
└─ admin/
   ├─ _layout.tsx        # the dashboard's sidebar
   └─ users.tsx
```

A part that should replace a layout rather than sit inside it goes in a directory beside it: `pages/legal/` instead of
`pages/marketing/legal/`.

## Code-split with their pages

A layout is in the JavaScript of its pages only: a visitor of the home page doesn't download the docs' sidebar. Fondu
does it at build time: each page imports the `_layout.tsx` files above it and gives them to Inertia as the page's
layout.

## The app's default layout

`createInertiaApp({ layout })` in `app/app.tsx` is Inertia's default layout: Fondu leaves it to the pages with no
`_layout.tsx` above them. With an `app/pages/_layout.tsx`, every page has one, so the default is not needed.

A page can still set its own, as Inertia allows: `Page.layout = OtherLayout` replaces its directories' layouts.

## Files that are not pages

A file in `app/pages/` whose name starts with `_` is not a page: `render()` can't name it, and it is not in the
generated types. Besides `_layout.tsx`, a component used by the pages of one directory can live there too, as
`_toc.tsx`.
