# Badges and heads

> The badge that cuts through the GT monograms after the Brand title, and the book head every hub page opens with, live at two widths.

URL: https://www.prototemplate.com/docs/components/heads

Every page of the hub that reads as a book opens with the same head: the title, a lead of one to three lines, a panel of facts, and one hatch band. DESIGN.md section 4 sets the standard and `pnpm lint:heads` holds it. /brand alone sets a badge after its title, which cuts through the GT monograms one frame at a time.

## The head badge [#the-head-badge]

The plate sets the Brand title with its badge as `BookHead` sets it: the badge follows the title's last word and never breaks away from it. Count sets how many monograms the strip holds, and Size sets the title at the page and section steps. Still applies the rule reduced motion applies.

<BadgeCycleDemo />

Every frame sits side by side in one strip, each exactly one box wide, and a CSS animation steps the strip one box to the left every 1.4 seconds with `steps(n)`, so each change is a hard cut. A hidden sizer stacks every frame in one cell, so the box takes the widest frame's width and never changes size. `BookHead` hides the badge from the accessible name, so the h1 a crawler reads holds the title alone.

### Import and props [#import-and-props]

```tsx
import { BadgeCycle, badgeMark } from '@/components/viewer/BadgeCycle';

<BookHead badge={<BadgeCycle frames={files.map((file) => badgeMark(file))} />} />;
```

| Export           | Props                          | What it does                                                       |
| ---------------- | ------------------------------ | ------------------------------------------------------------------ |
| `BadgeCycle`     | `frames`: `{ key, content }[]` | The strip of frames. With no frames it renders nothing.            |
| `badgeMark(src)` | a public file path             | One frame that draws the file as an alpha mask in the title's ink. |

The rules live in `src/components/viewer/BookView.css`, so a host outside a book head imports that sheet, as this plate does.

### When to use it [#when-to-use-it]

Only /brand's head carries a badge (Kevin, 2026-10-21): the GT monogram, then the register's monograms. Every other book head sets its title alone, and `pnpm lint:heads` fails a badge outside `src/app/brand`.

### Reduced motion and themes [#reduced-motion-and-themes]

Under reduced motion the strip stops on the first frame and the box takes that frame's width. The frames draw in the title's ink, so the badge follows the theme.

## The book head [#the-book-head]

A page keeps one h1, so the plate shows the head in its own document: a live hub page in a frame, scaled to the plate. Page picks the route, and Width lays it out at 1440 or 390 pixels. The head is a container, so at the phone width the panel drops under the lead. The page inside stays live.

<HeadFrameDemo />

The frame follows the docs theme through the root layout's theme script, and it loads only when the plate comes near the viewport.

### Import and props [#import-and-props-1]

```tsx
import { BookHead } from '@/components/viewer/BookView';

<BookHead
  title={PAGE_NAMES.marks.name}
  lead='The speed set is seven General Translation marks in one register.'
  updated={updated}
  facts={[
    { icon: 'swatch', key: 'Marks', value: 9 },
    { icon: 'speed', key: 'Speed set', value: 7 },
    { icon: 'archive', key: 'Earlier round', value: 2 },
  ]}
/>;
```

| Prop       | Type                                    | What it does                                                                               |
| ---------- | --------------------------------------- | ------------------------------------------------------------------------------------------ |
| `title`    | string                                  | The page's plain name from `PAGE_NAMES`, or a record's own title. It is the page's one h1. |
| `badge`    | node                                    | /brand only: the badge after the title's last word, hidden from the accessible name.       |
| `lead`     | node                                    | One to three lines at the lead measure, 200 characters at most.                            |
| `updated`  | `PageUpdated`                           | The page's entry in `src/lib/updated.ts`, passed down from its server page.                |
| `facts`    | three facts, or one fact with `install` | The panel's rows after Updated, each `{ icon, key, value }`.                               |
| `install`  | string                                  | An install command in a copy field, in place of the second and third facts.                |
| `note`     | node                                    | The rest of the introduction, under the mast's rule.                                       |
| `contents` | node                                    | The page's contents nav, left out on a page of fewer than two sections.                    |

The server page calls `requireUpdated('<route>')` and passes the entry down, because a client module may not import `src/lib/updated.ts`. A new route also needs its paths in `scripts/build/updated.mjs`.

### When to use it [#when-to-use-it-1]

Use `BookHead` on every hub page with a book head; a page differs from another only in its words and its facts. Pages outside the shell, such as these docs, the deck and the `/d/` directions, have heads of their own.

### Reduced motion and themes [#reduced-motion-and-themes-1]

The head itself does not move; its badge holds its first frame under reduced motion. Every value is a `--pt-` token, so the head follows the theme.

## The head's numbers [#the-heads-numbers]

The panel's column is 304 px (`--pt-head-panel` in `src/components/viewer/tokens.css`), sized for its longest value: a date with its hint, such as "Sep 10, 2026 4 weeks ago", which measures 168 px. The panel's rows sit on the lead's line pitch, 26.35 px, so a fact lines up with a line of the lead beside it. [Pages and the viewer shell](https://www.prototemplate.com/docs/pages) holds every number of the book page with what it measures.

---

The index of every page on this site, for agents: https://www.prototemplate.com/llms.txt
