Skip to content
Back to skills

Interface Text

ASecurity

Rules for every string rendered inside the app, plus the sweep that removes in-app prose. Use when writing or changing a label, hint, description, tooltip, empty state or KPI tile in a .tsx file, or when running Pattern Patrol P14 or asked to find or fix long UI text.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 3, 2026
developmentgonodefrontendbackend

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned October 3, 2026

npx -y skills add armanisadeghi/ai-matrx --skill interface-text --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Interface Text?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Interface Text
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/armanisadeghi-interface-text/badge)](https://www.skillsdirectory.com/skills/armanisadeghi-interface-text)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: interface-text
type: Skill
title: "interface-text — in-app text is layout: labels, not prose"
description: "Rules for every string rendered inside the app, plus the sweep that removes in-app prose. Use when writing or changing a label, hint, description, tooltip, empty state or KPI tile in a .tsx file, or when running Pattern Patrol P14 or asked to find or fix long UI text."
tags: [ui, copy, microcopy, patrol, design-system]
timestamp: 2026-09-30T00:00:00Z
---

<!-- SYNCED COPY — do not edit here.
     Canonical: common-docs/skills/interface-text/SKILL.md
     This file is distributed to every consuming repo by
     common-docs/meta/scripts/sync_skills.py. Edit the canonical, run the
     sync, and commit each repo. Edits made here are overwritten and lost. -->

# interface-text — in-app text is layout

Doctrine (read once): `common-docs/policies/interface-text-is-layout.md`.

You are writing **interface text**, not prose. Every string the app renders sits in a **slot**
owned by a component, has a **character budget**, and has **siblings** that must match. The
screen is not where you explain, justify, or prove anything — that is what the commit message,
the code comment and `FEATURE.md` are for.

## The card — apply to every string you write or touch

1. **Who is this sentence for?** If it helps someone reading the diff — a formula, a function or
   table name, where the number comes from, what changed, what is not built yet, which other
   page agrees with it — it is **author-facing**. Put it in a code comment or the commit. It
   never renders.
2. **Label first.** Make the label carry the meaning (`Batch savings (7d)`). A number that needs
   a paragraph gets a better label; a definition that is still needed gets **one sentence in the
   tooltip slot**: `title=` on `KpiTile`, `components/official/InfoHint` everywhere else (hover,
   keyboard and touch — a native `title=` attribute on text is unreachable on phones).
3. **Fit the slot.** Secondary text ≤ **60** chars, one line, never two sentences. Tooltip ≤
   **140**, one sentence. Placeholder ≤ **60**, an example value. Dialog description / empty /
   error state ≤ **140**, at most two sentences: what happened, what to do. No sentence under
   a page or section title — ever.
4. **Look at the row and the column.** Your text sets the height of every tile in its row and
   the width of every cell in its column. Fill a **visible** slot on **all siblings, at similar
   length and in the same shape, or on none**. Tooltips are hidden and per need — never add one
   to a sibling just to match.
5. **Use the primitive that enforces the budget.** `components/official/kpi/KpiTile` +
   `KpiGrid` for KPI rows (one-line `hint`, `title` tooltip). If the official primitive "cuts
   off" your text, your text is too long — shorten it; never hand-roll a component to escape
   the limit. A local component that renders unbounded secondary text is itself a finding.
6. **A tooltip states only what you verified in the code or the data contract.** Cannot prove
   the definition ("since midnight", "today's budget")? Write no tooltip — a wrong definition
   is worse than none.
7. **Honesty is state, not prose.** Unmeasured → `—` with the reason in the tooltip. Partial
   feature → the Coming Soon registry. Never "not yet reported by the backend", never "Backfill
   brings this up to 100%".
8. **See it rendered, then check it.** In matrx-frontend run
   `pnpm check:interface-text --changed` before committing; any other repo:
   `node ../matrx-frontend/scripts/interface-text/check-interface-text.mjs --root=. --changed`.
   Every `NOVEL` line on your diff is fixed before commit.

## Rationalizations

From the 2026-09-30 baseline runs (`evals.md`) — each one produced a defect.

| Excuse (verbatim) | Reality |
|---|---|
| "the shared tile cuts off long hints" | That is the budget working. Shorten the text; keep the primitive. |
| "swapping only this row would make one page look two ways… should be its own change" | Adopt the primitive for the whole page in this change; it is a few lines. |
| "the rule that every number names its window and item count" | The label `(7d)` names the window; a count fits a 60-char hint. A sentence is not required. |
| "Both are a screen lying." → adds a sentence | Honesty is `—` + tooltip, a badge, or a registry entry. |
| "in the same words the Platform Spend 'Saved by batching' headline uses" | Consistency means the same **label**, not the same paragraph copied to two pages. |
| (with the skill) tooltips added to all six tiles "so the row matches" — two invented "since midnight" / "today's budget" | Parity is for visible slots. An unverified definition is fabrication; leave the tooltip out. |

## Red flags — stop and re-read the card

- You are about to paste words from your commit message, `FEATURE.md` or a code comment into JSX.
- Your string contains a dot-separated or snake_case name, a backtick, "backend", "server", or "not yet".
- One sibling gets a hint and the others do not.
- You are writing a second sentence in a hint or description.
- You are choosing a local component over `components/official/*` because of text length.
- You are writing a tooltip definition you did not read in the code or the data contract.

## The sweep — Discover → Review → Fix → Confirm (Pattern Patrol P14)

Each phase is its own agent. Read **only the file for the phase you were given**:

| Phase | Lane | Read |
|---|---|---|
| Discover — build units for a slice, classify each, propose the exact fix; the validator must pass | `quick` with **sonnet** (haiku mapped rules to verdicts without reading and cut rewrites mid-sentence — 2026-09-30) | `discover.md` |
| Review — accept or correct the classifications, find primitive-level fixes, batch the work, pick what goes to Arman | `standard` (opus) | `review.md` |
| Fix — apply a reviewed batch in its files | `quick` (sonnet) for mechanical batches, `standard` otherwise | `fix.md` |
| Confirm — independent check of a fixed batch | `standard` (opus), never the fixer | `confirm.md` |

The proof record and regression scenario for this skill is `evals.md`; the next editor reruns it.

Files in this skill

  • SKILL.md6.1 KB
  • confirm.md2.6 KB
  • discover.md5 KB
  • evals.md6.3 KB
  • fix.md6.5 KB
  • review.md4.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…