# Common expressions

An **expression** is the concept a theme serves — the *reason* it exists, and it *is* the theme's address: a theme's **record key**. A theme saved at `…/theme/dark` serves `dark`. The name is just a string, compared for exact equality and never fetched. This page shows **how expressions are named** and lists a handful of common ones **as examples**. Nothing here is required or official — they're illustrations of the convention — save for **one reserved word, `default`** ([below](#the-one-reserved-word-default)).

## How expressions are named

There's really one rule, and you can read it at a glance:

- **A bare, lowercase word** — `dark`, `critical` — is a **common** concept: the obvious shared spelling that anyone might use.
- **A dotted, reverse-DNS string** — `com.homedepot.easter`, `com.alice.midnight` — is **your own** concept, rooted in a domain or handle you control, yours to define however you like.

The presence of a dot tells you which kind you're looking at — no lookup required. An expression is **both the theme's record key and the `data-mode` value** an app writes into the page (`<main data-mode="dark">`), so it must be a valid record key — case-sensitive (keep it lowercase by convention), with dashes within a word (`high-contrast`). Any valid record key is automatically a safe `data-mode` token: the delimiters that `data-mode` parsing relies on — the **slash** (the aspect delimiter, as in `dark/color`) and **whitespace** (which separates aspect fragments) — are deliberately characters that can't appear in a record key at all, so there is nothing to avoid and no word is off-limits as an expression.

Making the expression the record key is what gives the standard **free uniqueness**: a repo is a key→record map, so you can hold at most one theme per expression — a second `dark` overwrites the first. Two of your themes can never ambiguously both claim `dark` (or `default`); the collision is impossible, not merely resolved.

:::note[Why does the spelling matter?]
Two looks line up only when their **record keys** are **identical**. So for a concept lots of people have — light, dark — it pays to reach for the same obvious word. That's all "common" means here: the spelling everyone would naturally pick, not a list anyone blessed. Use it, ignore it, or coin your own.
:::

## Some common expressions

Illustrative only — reach for these where they fit, or don't.

| Expression | Commonly conveys |
|---|---|
| `light` | A light appearance, for content on a light background. |
| `dark` | A dark appearance, for content on a dark background. |
| `critical` | A state that should give someone pause — an error, a destructive or dangerous action. |
| `selected` | Content the person has actively chosen — a picked row or card. |
| `compact` | A denser treatment: closer spacing, tighter type, more in view. |
| `hero` | A roomy, spacious treatment: larger type, generous space. |
| `promo` | A promotional treatment that pulls focus to a feature or campaign. |

## Coining your own

When a concept is yours — a brand moment, a personal look, something niche — name it in a namespace you control:

```
com.homedepot.easter      a brand's seasonal look
com.alice.midnight        a personal look
```

A look that means two things at once is a **single** concept with its own name — `com.acme.critical-dark`, not `critical` and `dark` blended together. Matching stays one rule: exact string equality. The reasoning is in the [Mode Contract](https://standard.mode.place/contract/) and the [FAQ](https://standard.mode.place/faq/#how-do-our-looks-even-line-up--how-does-it-know-theyre-the-same).

:::note[Why: a convention, not a registry]
Common concepts converge by everyone reaching for the obvious word, not by anyone blessing a list. A few registry-shaped alternatives were tried and dropped, each because it read as *authoritative* or added a lookup the plain string never needs: a canonical `/expressions.json` endpoint and a lexicon `knownValues` enum (both imply a blessed set and re-couple "adding a word" to a publish), and an `expression` record referenced by AT-URI (which would anchor the whole vocabulary to one personal PDS — a needless dependency and single point of failure). What's left is the lightest thing that works: an opaque string compared for equality, so good ids spread by network effect the way hashtags do. It mirrors AT Protocol **label values** — bare, kebab-case, meaning defined externally — rather than the resolvable token/NSID style. The dot rule (no dot = common, dotted = yours) is the only structure, and it's a reading convention, not a lookup.
:::

There's a practical reason to namespace, too: **two authors on one page can't share a bare word for different looks.** An app targets a look by its expression (`[data-mode="dark"]`), and that matches *every* `dark` on the page — so if two independent authors each ship their own distinct dark under bare `dark`, the two would collide. Give each its own name (`com.alice.dark`, `com.bob.dark`) and they coexist cleanly, each applying only where its own marker sits. Bare `dark` is for the *one shared* dark everyone agrees on — the one a viewer's `dark` can override across the whole page.

## One look, many names — a tooling job, not a protocol one

One look can absolutely serve several concepts — a `dark` that is also your `default`, or that also overrides `com.homedepot.dark`. But because the expression *is* the record key, a theme serves exactly one. So a look with several names is several **self-contained records**, one per key, each carrying **the same values**:

```
…/theme/dark                # my dark
…/theme/default             # same values — also my baseline
…/theme/com.homedepot.dark  # same values — also overrides that brand's dark
```

Keeping those copies identical is a job for **your authoring tooling**, not the protocol. Your design tokens are the single source of truth; a build step compiles them to one record per key and writes each. The network stores independent, self-contained artifacts — like compiled CSS, not a live-linked database. The protocol has **no** notion of aliasing: no `expresses` list, no reference from one theme to another. That's deliberate — with nothing pointing anywhere, nothing can dangle, and if a build drops an intent, your tooling's *pre-publish schema check catches it* (on your side, loudly — see [Publish a theme](https://standard.mode.place/guides/publish-a-theme/); most hosts won't validate a third-party record for you) rather than silently breaking every app downstream.

This is also the easy way to override a specific concept: have your tooling emit a copy at that concept's key (see [Generic invites](#generic-invites-specific-reserves)).

None of this is a *blend*. Saving the same values at `dark` and `default` says "these values are *both* my dark and my baseline." A look that genuinely **combines** concepts is a single **composite** name (`com.homedepot.easter-dark`), saved as its own theme at that one key. One record is always one complete set of values.

## The one reserved word: `default`

Everything else on this page is illustrative — but the standard reserves **one** name, because apps rely on its meaning: **`default`**.

`default` names the viewer's **baseline** look — the one that fills the page root and any scope no specific concept has claimed. It works like any other concept, by string-matching — it's just a reserved record key:

- An app marks its baseline scopes `data-mode="default"`.
- A viewer makes a look their default by saving it at record key **`default`** (`…/theme/default`) — usually their tooling writes a look they already have to that key too.
- An app's *own* default look lives at its `default` key, so it fills the baseline (in the `app` layer) when there's no viewer.

Because it resolves by ordinary key-matching, `default` needs no special field — it's what a look designates instead of the (removed) `profile.defaultTheme` pointer. Adopting *someone else's* look as your default is fork-and-copy: your tooling writes their values into your own `…/theme/default`.

So don't use `default` as the name of your *own* distinct concept — it carries this baseline meaning everywhere.

## Generic invites, specific reserves

Choosing a bare word or a namespaced one isn't only about avoiding collisions — it's a statement about **how open a slot is to your own look**.

When an app marks a region with a **bare** word like `dark`, it opens that region to the *shared* concept: *"this is dark in the common sense — if you have a `dark`, yours goes here, and yours takes precedence."* The obvious spelling is an invitation.

When it uses a **namespaced** word like `com.homedepot.easter`, it reserves the region for *its own* concept: your generic `dark` won't match it, so the brand look holds for anyone who didn't specifically ask for something else.

But **reserved isn't locked.** Because looks line up by *exact record key*, you can always make **your own version of someone else's concept** — save a theme at their key (e.g. `…/theme/com.homedepot.easter`, carrying the values you want there; your tooling can copy them from a look you already have). Then wherever they placed that concept, your take on it applies instead (a conforming app honors the viewer). The brand owns *where* the concept lands; you own *how your* version of it looks.

So there's a spectrum, and it runs on how generic the string is:

- **The more generic the string, the more it expects to adopt your expression.** Bare `dark` is maximally open — almost everyone has a `dark`, so it readily gives way to yours.
- **The more specific the string, the more deliberate an override has to be.** `com.homedepot.easter` won't budge for a generic preference, but it still yields to someone who *deliberately* curated that exact concept.

Nobody is ever truly locked out — the only difference is whether your look slots in *automatically* (you already have the shared word) or *on purpose* (you adopt the specific one). That guaranteed-but-deliberate override is the [Mode Contract](https://standard.mode.place/contract/)'s accountability valve.

## Where to next

- **[What is a mode?](https://standard.mode.place/what-is-a-mode/#why-an-expression-and-not-just-a-name)** — why an expression, and not just a name.
- **[The Mode Contract](https://standard.mode.place/contract/)** — how matching and precedence actually work.
- **[Schema reference](https://standard.mode.place/reference/schema/#placemodestandardtheme)** — the theme record, keyed by its expression.