[@layout]: ../docs.layout.md

# Layouts

A `.layout.md` Source defines the HTML around a page. Place one `<x-source-content />`
outlet where its Blocks should appear.

```md
[@nav.primary]: ../navigation/site.navigation.md

<header>
  <x-navigation-nav name="primary" />
</header>
<main>
  <x-breadcrumbs-trail />
  <x-source-content />
</main>
```

Relative links in a layout resolve beside the layout file. Styles and component
imports belong there when they support the shared page structure.

---

## Select a layout

Put site-wide defaults in the root `index.md` (or typed root index):

```md
[@layout.default]: ./layouts/site.layout.md
[@layout.lesson]: ./layouts/lesson.layout.md
```

A `color.lesson.md` Source uses the lesson layout. Other types fall back to the
site default. A page can select its own layout:

```md
[@layout]: ./layouts/special.layout.md
```

| Selection | Scope and precedence |
| --- | --- |
| URL parameter `layout=false` | Omits the authored layout for this visit. |
| Frontmatter `layout: false` | Disables an authored layout for this page. |
| `[@layout]: ./file.layout.md` | Page-local choice overrides defaults. |
| `[@layout.lesson]: ./file.layout.md` | Nearest folder index default for type `lesson`. |
| `[@layout.default]: ./file.layout.md` | Nearest folder index fallback. |
| No selection | Uses the built-in minimal article wrapper. |

A folder's canonical index (including a typed index such as `index.path.md`)
can declare its own defaults:

```md
<!-- paths/work/index.md -->
[@layout.default]: ../layouts/work.layout.md
[@layout.lesson]: ../layouts/work-lesson.layout.md

# Work
```

`paths/work/notes.page.md` now uses the work layout without a local layout link.
Resolution visits indexes from the page's storage folder toward the root. At each
index, its type-specific selection wins over its `default`; a nearer `default`
wins over a more distant type-specific selection. A deeper index may override
these defaults. Each relative link resolves beside the index that declares it.

The index itself uses its own defaults unless it has an explicit local selection.
Layout Sources only compose through explicit `[@layout]` links; they do not inherit
folder defaults. Included content and named instances keep the host Source's
storage scope. Titles, scripts, and component imports are not inherited.

To link to content without its site layout, add `?layout=false`:

```md
[Read the lesson without navigation](./color.lesson.md?layout=false)
```

The rendered link targets `/color.lesson?layout=false`. The same Source at
`/color.lesson` still uses its authored layout. Source properties, content,
components, and access rules are unchanged. Only the exact value `false` opts
out; other values use the normal layout selection. A raw `.md` URL still returns
Markdown.

A PathMX server omits the layout and its assets while rendering the response.
Folder styles and the effective theme still apply; see [Stylesheet scope](./styles.reference.md#stylesheet-scope).
Plain static exports apply the option in the browser: JavaScript removes the
layout after the ordinary document loads, so its assets may still download.
For a static page that must omit its layout without JavaScript, author
`layout: false` in that page's frontmatter.

---

## Nest a type layout in a site layout

In a Quickstart project, replace the root `paths/index.md` with:

```md
[@layout.default]: ./site.layout.md
[@layout.artist]: ./artist.layout.md

# Workshop artists

[Meet Ada](./ada.artist.md).
```

Create `paths/site.layout.md`:

```md
<header><a href="/">Workshop artists</a></header>
<main><x-source-content /></main>
```

Create `paths/artist.components.md`. This component reads the represented artist:

````md
<!-- componentName: artist-summary -->

# Artist summary

```html
<p>{{ source.category }} · Booth {{ source.booth }}</p>
```
````

Create `paths/artist.layout.md`. Its parent is the site layout:

```md
[@layout]: ./site.layout.md
[@artists]: ./artist.components.md

<article>
  <artist-summary />
  <x-source-content />
</article>
```

Create `paths/ada.artist.md`:

```md
---
category: Printmaking
booth: 12
---

# Ada's prints

Ada makes small prints of everyday places. Visit booth 12 to see her latest work.
```

Run `bun run dev` and open `/ada.artist`. The outer header links home; the inner
layout shows **Printmaking · Booth 12** above Ada's authored biography. Changing
`booth` to `14` updates that same layout region. Other page types still use only
the site layout. Each layout has one content outlet.

---

## Style a kind of page

A layout's stylesheet accompanies only the pages that use that layout. Continue
the artist example by linking styles from `paths/artist.layout.md`:

```md
[@layout]: ./site.layout.md
[@artists]: ./artist.components.md
[@styles]: ./artist.css
```

Every `.artist.md` page now loads `artist.css`; other pages do not. A folder's
landing page can take a type the same way. `paths/studios/ada/index.artist.md`
is the `/studios/ada` page and uses the artist layout, while
`paths/studios/ada/prints.page.md` keeps the site layout. One root declaration
covers every artist folder added later.

For type styles that should also apply in layout-free openings and included
Sources, select the type in a global or folder stylesheet instead; see
[Page types](./styles.reference.md#page-types).

---

## Keep represented Source data in the component

The artist layout imports `artist.components.md` and uses `<artist-summary />`.
Inside that component, `source` means Ada's artist Source. The layout and component
files do not replace her as the represented Source. Keep metadata interpolation
in the literate component; raw `{{ source.category }}` text in layout HTML is not
a template expression.

Change the component's markup to change every artist summary together. Put
artist-specific assets beside the artist Source and shared layout assets beside
the layout that declares them. [Component data](../authoring/components.reference.md#component-data)
explains Block scope and explicit attributes for more specialized presentations.

---

## Wrap the page body in a component

A layout may place `<x-source-content />` inside a component, so the component can
frame or enhance the page's own content:

```html
<x-reading-frame>
  <x-source-content />
</x-reading-frame>
```

The component receives the rendered page as its default slot. Render it with
`fragment(slots.default)` inside your root element. The page body stays
server-owned: live edits, Actions and Block features keep updating it. To add
behavior, give the component a client that enhances that server HTML without
returning `clientData`.

A component that returns `clientData` owns its children, so its client would
replace the page body. That page fails with an error naming the component. Place
such a component beside the outlet instead.

---

## Present with the same layout

Install Player with `bun run pmx plugins add player` and add `<x-player-app />`
once to `paths/site.layout.md`. Open Ada's page in Focus and Slides, advance,
then return to reading. The content outlet remains the artist's content.
Use your layout stylesheet to hide optional site chrome while presenting:

```css
html[data-pmx-play-active] header { display: none; }
```

Scope that selector to a site-header class when other headers must stay visible.
Do not hide the content outlet or Player controls. For a sticky reading header,
use the viewport contract below and check heading links before and after Play.

---

## Content and shared controls

Use semantic HTML such as `header`, `main`, and `aside` to organize the layout.
`<x-source-content />` renders the represented page's Blocks, rather than the
layout Source itself. Each layout needs exactly one empty content component. It
can sit inside a literate component that receives children through `<slot />`.

The standard plugin composition includes `SourcesPlugin`. Custom plugin lists
using authored layouts must include it alongside `LayoutPlugin`; both are exported
from `@pathmx/core/plugins`.

Core supplies navigation, breadcrumbs, `<x-navigation-toc />` for a table
of contents, and the color-scheme toggle. Package components need their owning Plugin installed. For example,
`<x-player-app />` requires Player and `<x-search-trigger />` requires Search.

`pmx lint` checks layout declarations and outlets. Review the layout on every
page type that uses it and at narrow widths.

---

## Sticky chrome and viewport space

Use `data-pmx-sticky-header` on authored sticky chrome to participate in the shared
viewport contract. The runtime measures its inset; the header stays visible
while scrolling. A [sticky opening Block](../authoring/blocks.reference.md#sticky-opening-block)
sits beneath it and reserves additional anchor clearance within its Source.

Fragment navigation and viewport-bounded components share
`--pmx-scroll-offset-block-start`, `--pmx-sticky-block-start`,
`--pmx-sticky-block-end`, and `--pmx-sticky-max-block-size`.
Customize safe gutters with `--pmx-viewport-gutter-block-start` and
`--pmx-viewport-gutter-block-end` in layout CSS. The shared control dock uses the
same bottom clearance. Reserve a fixed footer's height on the document root:

```css
:root {
  --pmx-viewport-inset-block-end: 4rem;
}
```

The gutter and safe-area clearance are added to that height. Keep the inset in
sync with your footer when its height changes.

---

## Related

- [Build a workshop site](../start/build-a-site.guide.md)
- [Navigation](./navigation.reference.md) · [Stylesheets](./styles.reference.md)
