> ## Documentation Index
> Fetch the complete documentation index at: https://developer.dittowords.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ditto Spec Files

> Format and structure of .ditto.md Ditto spec files for workspaces and components

## Overview

Ditto spec files use YAML frontmatter in `.ditto.md` files. Everything lives between the `---` delimiters; the markdown body below the closing `---` is unused. There are two types: **workspace specs** and **component specs**.

## Workspace spec

A repo has a single `workspace.ditto.md` somewhere under the CLI's configured `roots`. It holds universal style guide rules that carry no tags — these apply to every surface in every component. It also carries an inventory of all tags available on the platform.

```yaml theme={null}
---
workspace: true
# Managed by Ditto — do not edit below
tags: [body, button, call-to-action, dialog-title, heading, nav]
rules:
  - name: Write in active voice
    description: Lead with verbs, avoid passive constructions
    section: Voice & Tone
locales:
  de-DE:
    - name: Use informal address
      description: Use "Du" instead of "Sie" for all user-facing copy
      section: Formality
---
```

| Key         | Managed by   | Description                                                                       |
| ----------- | ------------ | --------------------------------------------------------------------------------- |
| `workspace` | Developer    | Must be `true`. Marks this as the workspace spec.                                 |
| `tags`      | CLI (`pull`) | All tags that exist on the platform. Used as a reference when tagging surfaces.   |
| `rules`     | CLI (`pull`) | Universal style guide rules with no tag scope — apply to all surfaces everywhere. |
| `locales`   | CLI (`pull`) | Locale-scoped style guide rules, keyed by locale code.                            |

## Component spec

Each component that renders user-facing text gets an `index.ditto.md` Ditto spec file in its directory.

```yaml theme={null}
---
component: DialogueModal
tags: [dialog, confirmation]
surfaces:
  headline:
    tags: [heading, dialog-title]
    maxLength: 60
  content:
    tags: [body, dialog-body]
    maxLength: 240
  actionText:
    tags: [call-to-action]
    maxLength: 25
  cancelText:
    tags: [button]
    maxLength: 25
# Managed by Ditto — do not edit below
rules:
  - name: Confirmation dialogs should be direct
    description: Keep confirmation copy terse and unambiguous
    section: Voice & Tone
  - surface: actionText
    name: Calls to action should use active voice
    description: Always lead with a verb
    examples:
      - from: "Your settings"
        to: "Open settings"
    section: Voice & Tone
  - term: sign up
    disallowed:
      - signup
      - sign-up
    description: Always use as two words (verb form)
    section: Terminology
locales:
  de-DE:
    - name: Use informal address
      description: Use "Du" instead of "Sie" for all user-facing copy
      section: Formality
---
```

### component

The component name (string). Set when you run `ditto-spec scaffold`.

### tags

Component-level tags (array of strings) that describe what the component **is** in your design system — e.g. `[dialog, confirmation]` for a confirmation modal, `[card, product]` for a product card. Style guide rules matching any of these tags apply to **all** surfaces in the component, cascading content governance to every piece of text it renders. Edit these freely.

This is the primary mechanism for integrating Ditto specs into a design system. A component's tags capture its role as a design system element, pulling in rules about how that type of component should read — tone, voice, constraints. The individual surfaces then carry their own tags for more specific rules (see below).

### surfaces

Each key is a surface — a distinct piece of user-facing text the component renders.

| Property    | Required | Description                                                                                                                                                        |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tags`      | Yes      | Per-surface tags that describe the text's role — e.g. `[heading, dialog-title]`, `[call-to-action]`. Used for matching style guide rules to this specific surface. |
| `maxLength` | No       | Maximum character length. A hard layout constraint, not a stylistic preference.                                                                                    |

### rules

Populated by `ditto-spec pull`. Style guide rules come in two shapes:

| Shape             | Fields                                                                     | Scope                                                                        |
| ----------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Style rule        | `name`, `description`, `examples` (optional `{from, to}` pairs), `section` | Without `surface`: all surfaces. With `surface: "<key>"`: that surface only. |
| Terminology entry | `term`, `disallowed`, `description`, `section`                             | Without `surface`: all surfaces. With `surface: "<key>"`: that surface only. |

### locales

Populated by `ditto-spec pull`. Keyed by locale code (e.g. `de-DE`). Contains the same style guide rule shapes as `rules`, scoped to a specific locale. Locale-scoped rules apply **in addition to** base rules when writing copy for that locale.

## Style guide rule hierarchy

| Scope               | Where                                          | Applies to                                                          |
| ------------------- | ---------------------------------------------- | ------------------------------------------------------------------- |
| **Workspace**       | `workspace.ditto.md` `rules[]`                 | Every surface in every component                                    |
| **Component-level** | Component's `rules[]`, no `surface` field      | Every surface in this component                                     |
| **Per-surface**     | Component's `rules[]`, with `surface: "<key>"` | That one surface                                                    |
| **Locale-scoped**   | `locales.<code>[]` (workspace or component)    | Same hierarchy as above, but only when writing copy for that locale |

Base style guide rules always apply. Locale-scoped rules apply only when writing copy for the matching locale — they never conflict because each locale is a separate scope.

## Developer-owned vs CLI-managed keys

| Keys                                 | Owner        | Edit by hand?                         |
| ------------------------------------ | ------------ | ------------------------------------- |
| `component`, `tags`, `surfaces`      | Developer    | Yes — add, remove, and modify freely. |
| `rules`, `locales`, workspace `tags` | CLI (`pull`) | No — overwritten on every pull.       |

<Info>
  Never edit `rules` or `locales` by hand. Run `ditto-spec pull` to update them from the platform.
</Info>

## Surface naming conventions

| Scenario                  | Key to use            | Example                               |
| ------------------------- | --------------------- | ------------------------------------- |
| String prop               | The prop name         | `title`, `description`                |
| Nested prop               | Dot notation          | `primaryAction.label`                 |
| Children prop             | `$children`           | `$children`                           |
| Hardcoded/internal string | Descriptive role name | `headline`, `bodyText`, `submitLabel` |

Check the `tags` key in `workspace.ditto.md` for tags available on the platform. Prefer reusing an existing tag over creating a new one — only tags that exist on the platform will match style guide rules.

## Tagging in a design system

Ditto specs support two levels of tagging that mirror how design systems organize components:

* **Component-level tags** describe the component itself — its role in the design system. A `DialogueModal` tagged `[dialog, confirmation]` pulls in style guide rules about how confirmation dialogs should read. These rules apply to every surface in the component.
* **Surface-level tags** describe each individual piece of text — its function within the component. An `actionText` surface tagged `[call-to-action]` pulls in rules specific to CTAs (e.g. "lead with a verb"). These rules apply only to that surface.

Both levels work together. For a `DialogueModal`:

```yaml theme={null}
tags: [dialog, confirmation]        # rules about dialogs apply to ALL surfaces
surfaces:
  headline:
    tags: [heading, dialog-title]    # + rules about headings apply here
  actionText:
    tags: [call-to-action]           # + rules about CTAs apply here
  cancelText:
    tags: [button]                   # + rules about buttons apply here
```

The `headline` surface inherits style guide rules matched by `dialog`, `confirmation` (from the component), plus rules matched by `heading`, `dialog-title` (from the surface). If a rule matches both levels, it appears once at component level — broader scope wins.

This means you can create style guide rules on the Ditto platform scoped to design system concepts (`dialog`, `card`, `form`, `navigation`) and have them automatically cascade to every component tagged with that concept, while surface-level tags layer on more specific guidance.

## File discovery

The CLI searches directories listed in the `roots` config for any `*.ditto.md` files. `workspace.ditto.md` is identified by its `workspace: true` key; all other `.ditto.md` files are treated as component Ditto specs.
