# Checking whether a theme is a stock look

> `osy design check` reads the app's `theme` — its accent's hue, the page's lightness, the corner radius, the shadow and the display face — and names the stock look it falls into, if any: tape-yellow/black poster, dark neon dashboard, premium dark, earthy serif editorial, SaaS indigo on white, soft pastel rounded. Each verdict says what put the theme there and what would move it out. Before the theme it checks the concept in `DESIGN.md`: an idea in one sentence, who it is for, a grid with its numbers, a type pairing with its reason, the budgets (type scale, colours, motion, what is forbidden) held against the app's own source, and a signature no generated page already has.

<!-- id: local-checking-a-look · area: local · stability: stable · html: https://osysharp.com/reference/local/checking-a-look/ -->

## Summary        {#summary}

A design built quickly converges on one of a few looks a hundred sites already share — even when the builder looked at
real references. The theme says which: the same accent family, the same page, the same corners and face. `osy design
check` reads the theme the app declares and names the look it sits in, so the moment to change direction is the moment
the theme is written, not after every screen is built on it.

## Signature      {#signature}

```console
osy design check [<path>] [--json]
```

## Description    {#description}

### The concept, first    {#concept}

Before the theme, it reads the concept: the `## Concept` section of `DESIGN.md` (in the project's root or `design/`),
one labelled line per constraint ([[ui-design#concept]]). Each line is checked for what can be checked:

| line | warned when |
|---|---|
| `Audience:` | it names no one ("everyone", "users", "customers"), or fewer than five words |
| `Idea:` | more than one sentence, more than 35 words, or fewer than five |
| `Grid:` | it has no number: no columns, measure or ratio |
| `Type:` | no `because`; a reason that would fit any brand ("clean", "modern", "elegant"); or none of the faces the theme sets is named |
| `Scale:` | fewer than three sizes and no ratio; or a `FontSize` token the app's theme sets in `px`/`rem` is not one of them |
| `Palette:` | no number; or the app's theme sets more hue families in `Colors` than the number (neutrals, status colours and chart series are not counted) |
| `Motion:` | no number ("none but hover" counts as 0); or the app declares more `animation` blocks than the number |
| `Forbidden:` | fewer than two moves, separated by `;` or `,` |
| `Signature:` | it is a signature generated pages already have (a gradient hero, frosted cards, a bento grid, a logo strip, big statistics, cards that lift, an oversized footer wordmark…) |

The budgets are read off the app's own `.osy` files, never a kit's, and test files are left out. With no
`DESIGN.md`, or none with a concept, it prints the nine lines to fill in. `--json` carries the concept beside
the themes.

### What it reads    {#features}

The app's own `theme` blocks ([theme tokens](https://osysharp.com/reference/ui/theming/)), in light mode where a token differs by mode:

| feature | from |
|---|---|
| accent hue, saturation, lightness | `Colors.Primary` (else `Accent`, `Brand`, `Highlight`), a hex or `Palette.From("#…")` |
| page lightness | `Colors.Bg` (else `Background`, `Page`, `Paper`, `Surface`) |
| ink lightness | the darkest of `OnBg`/`Text`/`Ink` and `Border` |
| corners | `Radius.Card`, else `Md`, `Control`, `Lg`, `Sm` (never `Pill`) |
| shadow | `Shadow` tokens: none, soft, or hard (an offset with no blur) |
| display face | `Font.Display` (else `Heading`, `Serif`, `Sans`): serif, sans, mono or display, from the stack's own generic family and the face's name |

### The looks    {#families}

| look | what puts a theme there |
|---|---|
| tape-yellow/black poster | a saturated yellow accent, black ink, corners of 3px or less |
| dark neon dashboard | a page under 15% lightness and an electric accent (saturation ≥ 70%, lightness ≥ 50%) |
| premium dark | a page under 15% lightness |
| earthy serif editorial | a serif display face, with cream paper or a clay accent |
| SaaS indigo on white | an indigo or blue accent of weight on a white page, in a plain sans |
| soft pastel rounded | a pale page, a pale accent and corners of 16px or more |

They are tried in that order, and the first that fits is named. Each was measured, not imagined: across this
repository's apps the editorial look holds 18 themes and the indigo one 10, two are premium dark, and of the kept
workspaces of one recent build brief, four of five landed on the poster.

```console
$ osy design check
theme Poster — accent hsl(50, 100%, 50%), page 95% light, corners 0px, shadow hard, display sans (Bricolage Grotesque)
  ⚠ tape-yellow/black poster — a saturated yellow accent on black ink with square corners — the look of every hardware-store and "bold" startup poster; references in the category converge here
  what puts it there: accent yellow (hue 50°, 100% saturation); black ink (7% lightness); corners 0px
  what moves it out: take the accent from a reference outside the category, give corners a rule other than none, or let the ink be a colour rather than black
```

"✓ no stock look" is the answer a decided theme gets — and it is not a verdict on the design, only that it is not one
of these. Look at the pages anyway (`osy test --pixels`). An app with no `theme` wears the kit's own look, and the
verb says so. `--json` prints the features and the verdict for a tool.

## See also       {#see-also}
- [Designing an app that looks designed — direction, type, colour, composition and motion](https://osysharp.com/reference/ui/design/) — choosing a direction, and the defaults to avoid
- [theme tokens](https://osysharp.com/reference/ui/theming/) — the tokens a theme declares
- [Finding licence-clear photographs past the stock picks](https://osysharp.com/reference/local/finding-photographs/) — `osy photo find`
- [Looking at a reference site before you design](https://osysharp.com/reference/local/looking-at-a-reference/) — `osy design look`
