
# Reusable Components

The same UI pattern usually appears on several pages — a feature badge, a section header, a call-to-action block. Copying its component tree into each page means every future change has to be made in every copy.

`app.components` is a library of named templates. Define the pattern once, with `$variable` placeholders where the content differs:

```yaml
components:
  - name: section-header
    type: container
    props: { className: 'text-center mb-12' }
    children:
      - { type: text, props: { level: h2 }, content: '$title' }
      - { type: text, props: { level: p }, content: '$subtitle' }
```

Then instantiate it from any page with `$ref`, passing the values:

```yaml
pages:
  - name: Home
    path: /
    components:
      - $ref: section-header
        vars:
          title: Own your software
          subtitle: One config file. A complete app.
```

## Template Properties

| Property   | Description                                                                      |
| ---------- | -------------------------------------------------------------------------------- |
| `name`     | Unique kebab-case identifier used by `$ref`. Must start with a lowercase letter. |
| `type`     | The component type the template renders — any type a page can use.               |
| `props`    | Component properties. Values may contain `$variable` placeholders.               |
| `content`  | Text content. May contain `$variable` placeholders.                              |
| `children` | Nested child components, which may themselves carry placeholders.                |

## Variables

A placeholder is a `$` followed by an alphanumeric name (`$title`, `$iconName`). At instantiation, `vars` supplies the values:

| Rule               | Detail                                                                       |
| ------------------ | ---------------------------------------------------------------------------- |
| Key format         | Starts with a letter, alphanumeric only — `$titleColor`, not `$title-color`. |
| Value types        | String, number, or boolean.                                                  |
| Where they resolve | In `props` values, in `content`, and at any depth inside `children`.         |

The same template with different vars produces different instances:

```yaml
components:
  - name: icon-badge
    type: badge
    props: { color: '$color' }
    children:
      - { type: icon, props: { name: '$icon' } }
      - { type: text, content: '$label' }

pages:
  - name: Features
    path: /features
    components:
      - $ref: icon-badge
        vars: { color: orange, icon: users, label: 'Team ready' }
      - $ref: icon-badge
        vars: { color: green, icon: lock, label: 'Self-hosted' }
```

## Validation

Component names must be unique across the library — a duplicate would make a `$ref` ambiguous, and it is rejected when the config is decoded.

:::callout
**Templates versus page components.** `app.components` holds patterns you instantiate. Anything used exactly once belongs inline in the page that uses it — a template referenced from a single place adds indirection without removing duplication.
:::

## Related Pages

- [Pages Overview](/en/docs/pages-overview) — the component tree a template plugs into.
- [Layout Components](/en/docs/layout-components) — the structural types templates most often wrap.
- [Configuration Files](/en/docs/configuration-files) — splitting a large library across files.
- [Languages](/en/docs/languages) — `$t:` translation tokens, which compose with template vars.
