/typography
Standalone skill. Takes a completed section (or the full site/index.html) and enforces print typography rules on all English text. Callable anytime — before /audit, after copy edits, whenever the source text changed.
Also the single source of truth for the short-word list that /build (pre-save pass) and /audit (post-build check) both reference.
Language scope: English only. Do not run on any other language.
When to use
- After
/buildwrites a new section —/buildcalls this automatically as its pass 4b. - After any copy edit in
inbox/texts/that triggered a rebuild of a section. - Standalone: user says "fix the typography on the hero" or "re-run typography on the whole site".
- Before
/auditas a safety pass.
Requirements
site/index.htmlexists (or a specific section HTML file was provided).- Content is English. If the copy is in another language, refuse and report which language was detected.
The rules
Rule 1 — Hanging short words at line end
A rendered line MUST NOT end on any of these words. Tie the word to the following word using so they wrap together.
Canonical short-word list (English):
# Articles
a, an, the
# Coordinating conjunctions
and, or, but, nor, for, so, yet
# Subordinating conjunctions & connectors
if, as, at, by, in, on, of, to, up, via, with, into, onto, from, than, then, when, where, while, before, after
# Auxiliary and short verbs
is, am, are, was, were, be, do, does, did, has, have, had, can, will, would, could, should
# Pronouns (short)
I, we, he, she, it, you, they, my, our, his, her, its, your, their, this, that
# Negations & quantifiers (short)
no, not, all, any
Case-insensitive matching, but preserve the original case when rewriting.
Rule 2 — Dashes never end a line
-, –, — must attach to the following word: text — word (nbsp before the dash, regular space after). This is opposite direction from Rule 1 — dash pulls the next word up.
Rule 3 — No orphans
Last line of a heading or a paragraph must contain at least 2 words. If the natural break would leave a single word on the last line, tie the last two words together: ... together with us.
Detection heuristic: for each <h1>, <h2>, <h3>, <p>, <li>, take the last 2-3 words and tie the last two with regardless of length. Cheap, prevents 95% of orphans.
Rule 4 — No widows (advisory)
If a <p> or <blockquote> spans a column break (rare on landing pages, but happens in multi-column footer or blog-style sections), the first line on the new column must contain ≥ 2 lines of the paragraph. This is difficult to detect statically — flag rather than fix.
Process
Step 1. Read input.
- If a file path was provided, load it.
- Otherwise load
site/index.htmland every section CSS to know which classes are text vs decorative.
Step 2. Detect language.
Sample ~200 chars from the largest <p> and the first <h1>. If the character set is not predominantly ASCII English, stop and report. Example refusal: Detected language: Russian. This skill runs on English only. Aborting.
Step 3. Walk text nodes.
For each text node inside a semantic text element (<h1>-<h6>, <p>, <li>, <blockquote>, <figcaption>, <button>, <a> if the anchor's text is a full phrase, <label>):
- Tokenize into words + whitespace runs.
- Rule 1 pass. Scan word-by-word. If word W is in the short-word list AND the following whitespace is a regular space AND the next word W+1 exists — replace the space with
. - Rule 2 pass. Scan for standalone
-,–,—surrounded by spaces. Replace the space before the dash with . - Rule 3 pass. Take the last two words of the text node. Ensure they are joined by
, not a regular space.
Step 4. Skip zones.
Do NOT rewrite text inside:
<code>,<pre>,<kbd>,<samp>,<var>— verbatim by contract.<script>,<style>— not text content.- Any element with
class="no-typo"— user escape hatch. - Attributes (
alt=,title=,placeholder=,aria-label=) — these do not line-wrap in visible layout in the same way.
Step 5. Idempotency check.
Before writing, diff the file. Existing from prior passes must not be duplicated (a the — bug). Collapse {2,} to a single .
Step 6. Save + report.
Save the file. Print a compact report:
typography pass — site/index.html
ties inserted: 47
dashes rewritten: 3
orphans prevented: 12
skipped (code/pre): 5 nodes
no-typo opt-outs: 1 node
If run inside /build, no report — silent success. If run standalone, always report.
Escape hatch
class="no-typo" on any element skips it entirely. Use for stylized headings where the designer wants specific manual breaks (e.g. <h1 class="no-typo">Ship<br>fast.</h1>).
Rules of behavior
- English only. Do not attempt to guess other languages' rules.
- Rewrite text nodes only. Never touch attributes, script, style, or verbatim elements.
- Idempotent. Running twice produces the same output as running once.
- No visual changes beyond typography. Never move elements, never add wrappers, never touch CSS.
What NOT to do
- Do not attempt to detect actual rendered line breaks (would require a headless browser; too expensive per pass). Use the word-level heuristics defined above.
- Do not modify the short-word list per project. It's the canonical English list. If the user wants a variant, they can override in a project-local
typography-overrides.md(not currently supported — flag as an enhancement request). - Do not run on non-English copy. Refuse.
Next
/audit— will grep for violations (hanging words, unfixed dashes) as part of category A./build— calls this automatically after each section HTML is written.