<!-- Generated from src/docs/page-types.mdx by scripts/build-docs.ts. Do not edit. -->

# Page types

The vocabulary for naming the kinds of pages Ghost Admin has. When a new feature shows up, the first question is "what page type is this?" — then reach for the matching pattern instead of inventing chrome.

## List page

Browsing or scanning a collection of items.

**Live examples**: Members, Tags, Comments, Automations, ActivityPub.

**Chrome shape**: `PageHeader` (title + count + search/filter/actions) → table or list → empty state → pagination.

**Page template**: `ListPage` (composes [`PageHeader`](./components/patterns/page-header.md)). Heavy filter UI uses `Filters`.

## Detail page

Working with a single item — viewing, editing, or both.

**Live examples**: Post editor, member details, tag details.

**Chrome shape**: `PageHeader` with breadcrumb + title + meta, a primary action area (save/cancel), and a content area dedicated to the item itself.

**Page template**: `DetailPage`. `DetailPage.Header` holds a `PageHeader` with the breadcrumb and actions; `DetailPage.Body` grows to fill the page and scrolls. Lay out the body from primitives and components. Named here so new product surfaces can identify the page type and avoid forcing detail flows into modals or Settings.

## Not in the taxonomy

- **Settings** — out of scope for this milestone. The page types above exist partly to give new features somewhere else to live. Don't force a settings screen into `ListPage` or `DetailPage`.
- **Workflow / multi-step flows** — too few live examples to standardise. Assemble them from primitives and components. Add the page type when there are 2+ concrete examples.

If a screen resists `ListPage`, check whether it is a detail page, settings or a flow before bending the template to fit.

## Composing a page

- **Header controls** follow the [PageHeader design contract](./components/patterns/page-header.md): action order, the single primary, search, filters and tooltips.
- **Pass `sticky={false}` and `blurredBackground={false}` to a `PageHeader` nested in a template header.** `ListPage.Header` owns stickiness and blur; a sticky `PageHeader` inside it stacks two sticky containers and breaks scrolling. `DetailPage.Header` is a non-sticky band and takes the same two props.
- **Show `FilterBar` only while filters are active.** It hides itself only when it has no children, so a page that always passes its filter controls would show an empty row. Mount it when the page has active filters, as Comments does (`hasFilters && <FilterBar>…</FilterBar>`).
- **Keep data and state in the page.** Templates and patterns are layout contracts: fetching, routing and permissions belong to the feature. See [Patterns](./patterns-guide.md).

## Example

```tsx
import {ListPage} from '@tryghost/shade/page-templates';
import {FilterBar, PageHeader, ViewBar} from '@tryghost/shade/patterns';
import {EmptyIndicator, Table} from '@tryghost/shade/components';
import {LucideIcon} from '@tryghost/shade/utils';

<ListPage>
  <ListPage.Header>
    {/* sticky={false} — ListPage.Header owns stickiness and blur */}
    <PageHeader sticky={false} blurredBackground={false}>
      <PageHeader.Left>
        <PageHeader.Title>Members<PageHeader.Count>{count}</PageHeader.Count></PageHeader.Title>
      </PageHeader.Left>
      <PageHeader.Actions>
        <PageHeader.ActionGroup>
          <PageHeader.ActionGroup.Primary>
            <PageHeader.Action label="Add member"><LucideIcon.Plus />Add member</PageHeader.Action>
          </PageHeader.ActionGroup.Primary>
        </PageHeader.ActionGroup>
      </PageHeader.Actions>
    </PageHeader>
    <ViewBar>{/* optional */}</ViewBar>
    {hasFilters && <FilterBar>{/* active filters and their actions */}</FilterBar>}
  </ListPage.Header>
  <ListPage.Body>
    {items.length === 0 ? <EmptyIndicator title='No members yet' /> : <Table>...</Table>}
  </ListPage.Body>
</ListPage>
```
