Study · emit portable design.md from diagnosis (opt-in)

After a study diagnosis, the user can now say "lock the DNA" to write
a portable design.md from the extracted DNA — same format as the
default verb's lock-the-system flow, seeded from the studied source.

URL mode populates exact tokens + fonts; image mode populates
estimated bands + candidate fonts. URL-mode emission asks the user
to attest the source is theirs or a public reference for their own
brand — third-party URLs are refused at the emission step even when
the diagnosis itself was allowed. Image mode emits without asking.

Updates skill protocol, design-md trigger list, public verb table,
README comparison, and the site's Study row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Youssef
2026-05-15 14:10:35 +01:00
co-authored by Claude Opus 4.7
parent 1cfcc89a06
commit b4e454fea2
5 changed files with 121 additions and 22 deletions
+9 -8
View File
@@ -30,15 +30,16 @@ If Hallmark is wired correctly, you'll see Long Document · Linen (warm-paper ro
| | Hallmark | [frontend-design](https://github.com/anthropics/skills) (Anthropic) | [Open Design](https://github.com/nexu-io/open-design) | [Dembrandt](https://github.com/dembrandt/dembrandt) |
| --- | --- | --- | --- | --- |
| **Source of taste** | extracts DNA from a screenshot you admire (`study` verb) | art-director brief + ban list | menu of 72 brand presets (Linear, Stripe, Vercel, Notion…) | scrapes a live URL, emits computed tokens |
| **Output unit** | macrostructure + theme + custom-craft | bans + brief framing | preset application | DTCG `tokens.json` |
| **Refuses font ID** | yes — names role, never guesses | n/a | n/a | n/a (computes from CSS) |
| **Refuses pixel-clone** | yes — DNA only, never pixels | n/a | n/a | n/a (full token export) |
| **Source of taste** | extracts DNA from a screenshot OR a URL (`study` verb) — image mode names roles + candidates; URL mode names exact fonts + tokens | art-director brief + ban list | menu of 72 brand presets (Linear, Stripe, Vercel, Notion…) | scrapes a live URL, emits computed tokens |
| **Output unit** | macrostructure + theme + custom-craft, optional portable `design.md` | bans + brief framing | preset application | DTCG `tokens.json` |
| **Refuses font ID** | image mode: yes — names role only; URL mode: names what the page declares | n/a | n/a | n/a (computes from CSS) |
| **Refuses pixel-clone** | yes — DNA only, never pixels (both modes) | n/a | n/a | n/a (full token export) |
| **Refuses third-party extraction** | yes — paid templates / competitors / unrelated sites auto-refused; `design.md` emission has a tighter layer with URL-mode attestation | n/a | n/a | n/a (extracts anything) |
| **Tactile-rebellion alignment** | warm-paper, custom-craft, slopless canon | strong | medium | none — token-only |
| **Pages by archetype** | 21 named macrostructures, picked per brief | by brief | 5 deterministic directions | n/a |
| **Verbs** | 4 (default · `audit` · `redesign` · `study`) | 1 | 31 | 1 (CLI) |
Hallmark's edge is **`study`** — every other tool ships a preset menu or a scraper. Hallmark is the only one that takes a screenshot of a design you admire, names what it sees, refuses paid-template-marketplace listings, and rebuilds your content with the extracted DNA. Three worked study examples in [`docs/study-examples.md`](docs/study-examples.md).
Hallmark's edge is **`study`** — every other tool ships a preset menu or a scraper. Hallmark is the only one that takes a screenshot *or* a URL of a design you admire, names what it sees (roles in image mode, exact fonts + tokens in URL mode), refuses paid-template-marketplace listings outright, and either rebuilds your content with the extracted DNA or emits a portable `design.md` you can hand to another AI tool — with a tighter refusal layer for the portable spec than for the diagnosis itself. Three worked study examples in [`docs/study-examples.md`](docs/study-examples.md).
---
@@ -49,7 +50,7 @@ Hallmark's edge is **`study`** — every other tool ships a preset menu or a scr
| *(default)* | Build new UI. Asks for audience + use + tone (skippable — the skill states what it inferred). Picks a macrostructure, applies the rule-set, runs the slop test before handing back. |
| `hallmark audit <target>` | Score existing code against the named anti-patterns + structural sameness. Punch list, no edits. |
| `hallmark redesign <target> [--mood <name>]` | Throw out the structure, keep copy + IA + brand, rebuild with a deliberately different fingerprint. |
| **`hallmark study <screenshot>`** | The differentiator. Extract the **DNA** from a design the user admires — macrostructure, archetypes, type-pairing role, colour anchor — and produce a diagnosis report. Optionally rebuild *the user's* content using the extracted DNA. **Refuses paid templates and competitor pages. Names font roles, never font IDs. Never copies pixels.** |
| **`hallmark study <screenshot \| URL>`** | The differentiator. Extract the **DNA** from a design the user admires — macrostructure, archetypes, type-pairing, colour anchor — and produce a diagnosis report. Accepts either an attached screenshot or a URL to a live page. After the diagnosis the user can optionally rebuild *their* content using the extracted DNA, **or** lock the DNA into a portable `design.md` other AI tools (Cursor, v0, Bolt) can read directly. **URL mode** reads HTML / CSS via WebFetch — names exact fonts and exact colour values, can't judge rhythm, and falls back to asking for a screenshot if the page is auth-walled or a JS-only shell. **Refuses paid templates and competitor pages. Image mode names font roles (never font IDs); URL mode names actual fonts (the page declares them). Never copies pixels. `design.md` emission has a tighter refusal layer than the diagnosis itself — URL-mode emission asks the user to attest the source is theirs or a public reference for their own brand.** |
---
@@ -113,8 +114,8 @@ Each page is its own self-contained HTML + CSS — no shared theme, no shared la
- **Microinteractions default-on for SaaS-shaped archetypes.** Bento Grid, Stat-Led, Workbench, Marquee Hero pages ship with 23 purposeful microinteractions (number reveal, pricing lift, marquee, stagger) without the user having to ask. Editorial / Manifesto / Letter / Quote-Led pages stay still.
- **SaaS page sequence.** Hero → social proof → features → testimonials → pricing → FAQ → CTA → footer. Real prices, not "contact sales for pricing." Specific testimonials with role + company.
- **Wordmark may use a different display face.** A Geist-bodied SaaS page can set its wordmark in Fraunces. Same-family collapse on Bento / Stat-Led / Workbench / Marquee Hero is the new "un-branded" tell.
- **`study` extracts DNA, not pixels.** Refusal heuristics, type-role vocabulary (no font ID guessing), confirmation step before any code. Three worked examples in [`docs/study-examples.md`](docs/study-examples.md).
- **Opt-in `design.md` lock-the-system flow.** Iterate freely on the first builds; when the system is settled, say *"lock the system"* (or *"give me a design.md"*) and Hallmark extracts the build's tokens + voice into a portable design system at the project root. From that point on every Hallmark run defers to it, the diversification rule inverts to consistency, and the file becomes the single source of truth for scaling the design across a real app. Phrase-triggered, never auto-emitted — no churn across iterations. See [`skill/references/design-md.md`](skill/references/design-md.md).
- **`study` extracts DNA, not pixels.** Refusal heuristics, type-role vocabulary (no font ID guessing in image mode), confirmation step before any code. Accepts a screenshot *or* a URL — URL mode reads HTML / CSS via WebFetch and names exact fonts + exact tokens (trades the rhythm pass for accuracy on everything else), with a graceful screenshot fallback when the URL is auth-walled or a JS-only shell. Three worked examples in [`docs/study-examples.md`](docs/study-examples.md).
- **Opt-in `design.md` lock-the-system flow — two entry points.** Iterate freely on the first builds; when the system is settled, say *"lock the system"* (or *"give me a design.md"*) and Hallmark extracts the build's tokens + voice into a portable design system at the project root. **Or**, after a `study` diagnosis, say *"lock the DNA"* and Hallmark emits the same `design.md` format seeded from the studied source — URL mode populates exact tokens + fonts; image mode populates estimated bands + candidate fonts. From that point on every Hallmark run defers to the file, the diversification rule inverts to consistency, and the file becomes the single source of truth for scaling the design across a real app. The study-mode emission carries a tighter refusal layer than the diagnosis itself — third-party URLs require user attestation (your own site / public reference for your own brand), competitors and paid templates are auto-refused. Phrase-triggered from either entry point, never auto-emitted. See [`skill/references/design-md.md`](skill/references/design-md.md).
---
+5 -3
View File
@@ -320,8 +320,10 @@
<header class="skill-row__head">
<div class="skill-row__head-body">
<h3 class="skill-row__title">Study</h3>
<p class="skill-row__lede">Paste a design you admire. Hallmark reads its structure, not its pixels — and
returns a 10-field DNA card you can build against. Never copies. Never claims to ID fonts.</p>
<p class="skill-row__lede">Paste a design you admire — a screenshot <em>or</em> a URL. Hallmark reads its
structure, not its pixels, and returns a DNA card you can build against. Or say <code>lock the
DNA</code> to write a portable <code>design.md</code> you can hand to another AI tool. Never copies
pixels. Tighter refusal layer for the portable spec than for the diagnosis.</p>
</div>
</header>
@@ -339,7 +341,7 @@
<ol class="skill-row__list">
<li class="dna__row"><span class="dna__k">Invocation</span><span
class="dna__v"><code>hallmark study &lt;screenshot&gt;</code></span></li>
class="dna__v"><code>hallmark study &lt;screenshot &#124; URL&gt;</code></span></li>
<li class="dna__row"><span class="dna__k">Macrostructure</span><span class="dna__v">Split Hero</span></li>
<li class="dna__row"><span class="dna__k">Hero archetype</span><span class="dna__v">H7 Clipped · copy-left
+ product-mock right</span></li>
+6 -3
View File
@@ -25,7 +25,7 @@ Hallmark has one default behaviour and three explicit verbs.
| *(default)* | The user asked you to design or build something new. Follow the **Design flow** below. |
| `hallmark audit <target>` | Read the target, score it against the anti-pattern list, return a ranked punch list. **Do not edit.** |
| `hallmark redesign <target> [--mood <name>]` | Take the target's content and intent, throw out the structure, and **rebuild it from scratch with a deliberately different structural fingerprint.** New section rhythm, new heading placement, new component voice. Preserve copy, brand, and information architecture; replace everything else. |
| `hallmark study <screenshot \| URL>` | The user pasted or attached an image of a design they admire, **or** pasted a URL to a live page. Extract the **DNA** — macrostructure, archetypes, type-pairing, colour anchor — and produce a diagnosis report, then optionally rebuild the user's content using the extracted DNA. Detection is automatic: a URL (`http://` / `https://` prefix) routes to URL mode; anything else routes to image mode. **URL mode** reads the page's HTML and CSS via WebFetch — it can name exact fonts and exact colour values, but can't judge rhythm. **Never copies pixels. Refuses template-marketplace URLs and competitor pages. Falls back to asking for a screenshot if the URL is auth-walled, a JS-only SPA shell, or otherwise un-readable.** Load [`references/study.md`](references/study.md) before this verb runs. |
| `hallmark study <screenshot \| URL>` | The user pasted or attached an image of a design they admire, **or** pasted a URL to a live page. Extract the **DNA** — macrostructure, archetypes, type-pairing, colour anchor — and produce a diagnosis report, then optionally rebuild the user's content using the extracted DNA **or** emit a portable `design.md` of the DNA. Detection is automatic: a URL (`http://` / `https://` prefix) routes to URL mode; anything else routes to image mode. **URL mode** reads the page's HTML and CSS via WebFetch — it can name exact fonts and exact colour values, but can't judge rhythm. After the diagnosis, the user has three follow-ups: build with the DNA (handoff to default), lock the DNA into a portable `design.md` (opt-in via "lock the DNA" / "give me a design.md"), or stop at the diagnosis. **Never copies pixels. Refuses template-marketplace URLs and competitor pages. Tighter refusal layer for `design.md` emission than for the diagnosis itself — URL-mode emission requires attestation that the source is the user's own or a public reference for their own brand. Falls back to asking for a screenshot if the URL is auth-walled, a JS-only SPA shell, or otherwise un-readable.** Load [`references/study.md`](references/study.md) before this verb runs. |
If the user types anything that does not clearly map to `audit`, `redesign`, or `study`, treat it as default. If the user attaches an image or pastes a URL without a verb prefix, ask: *"Should I `study` this (extract the DNA), or should I treat it as a reference for a fresh build?"*
@@ -536,9 +536,12 @@ If the user's input starts with `http://` or `https://` → **URL mode**. Otherw
3. **Diagnosis report.** Return a one-page "this is what you're looking at" using the matching template (image-mode template or URL-mode template) from `study.md` § The diagnosis report. Names the macrostructure, names the archetypes, points at the type pairing (with exact font names in URL mode), identifies anti-patterns the user should *not* carry over. URL-mode diagnoses must also call out the rhythm blind spot.
4. **Confirmation question.** Ask: *"Adopt this DNA wholesale, or change one axis? For example, I could keep the macrostructure but pick a theme that better matches your tone."* Wait for the user's answer before building.
4. **Confirmation question.** Ask: *"Adopt this DNA wholesale, or change one axis? For example, I could keep the macrostructure but pick a theme that better matches your tone."* The diagnosis report's last line **also** surfaces the `design.md` emission CTA — *"Or — say `lock the DNA` if you want a portable `design.md` of this DNA."* Wait for the user's answer before doing anything.
5. **Build.** Pick the closest matching theme from the catalog. Stamp the comment with the inferred macrostructure + archetypes + theme + source mode. The user's content goes in; the source's content does not.
5. **Branch on the user's response:**
- **"Build with this DNA"** → run the build step below. Pick the closest matching theme from the catalog. Stamp the comment with the inferred macrostructure + archetypes + theme + source mode. The user's content goes in; the source's content does not.
- **"Lock the DNA"** (or any other emission trigger phrase per `study.md` § Trigger phrases) → emit a portable `design.md` of the DNA per `study.md` § Emitting a `design.md` from `study`. **In URL mode, run the attestation step first** — ask whether the source is (a) user's own, (b) public reference for the user's brand, or (c) something else. (c) refuses emission; (a) and (b) write the file with a `## Provenance` block recording the answer. **Image mode emits without asking** — the user owns the screenshot. The emitted file becomes the project's locked system; subsequent runs defer to it.
- **"Just the diagnosis was enough"** / silence → stop. The diagnosis is a complete deliverable.
### Output contract for `study`
+20 -4
View File
@@ -2,18 +2,34 @@
Loaded by [`SKILL.md`](../SKILL.md) Step 6 ONLY when the user explicitly asks Hallmark to lock the current build's design system into a portable file. The default verb does NOT auto-emit `design.md`. The user iterates freely until they say the system is settled, then asks for it.
This file is **also** loaded by [`study.md`](study.md) when the user — after a successful `study` diagnosis — asks for the DNA to be emitted as a portable system. The format below is shared between the two paths; the only differences are spelled out in § Two emission paths (default vs study) and in [`study.md`](study.md) § Emitting a `design.md` from `study`.
## Triggers (phrase-only — no new verb)
Fire ONLY when the user says one of:
- *"lock the system"* / *"lock the design system"*
- *"give me a design.md"* / *"write a design.md"*
- *"extract this to a design system"* / *"extract the tokens"*
- *"make this portable"*
- *"lock the system"* / *"lock the design system"* / *"lock the DNA"* / *"lock this DNA"*
- *"give me a design.md"* / *"write a design.md"* / *"export this as a design.md"*
- *"extract this to a design system"* / *"extract the tokens"* / *"extract the DNA"*
- *"make this portable"* / *"make the DNA portable"*
- *"I want to use this in another project"*
For everything else — including the default build, the redesign verb on a single page, and free iteration on the same brief — skip. The single-page redesign and default verb stay token-portable via `tokens.css`; `design.md` is the explicit lock-in step.
## Two emission paths (default vs study)
The same `design.md` format is emitted from two different entry points. They differ in which signals seed the file and in how strict the refusal layer is.
| | **Default-verb path** (lock the system) | **Study-verb path** (lock the DNA) |
| --- | --- | --- |
| **Trigger context** | After at least one build the user has iterated on and is satisfied with | After a successful `study` diagnosis (image or URL) |
| **Source of tokens** | The build's in-memory token state | The studied DNA — exact from CSS in URL mode, estimated from bands in image mode |
| **Refusal layer** | None — the user owns the build they iterated on | Tighter — see [`study.md`](study.md) § Emission-refusal layer. URL mode requires attestation; third-party URLs are refused |
| **`## Provenance` block** | Omitted (the system is the user's own work) | Required — records source mode, URL or "image", date, attestation answer, confidence note |
| **`## Notes` block** | Optional — covers any decisions worth remembering | Required — carries the diagnosis's "anti-patterns to NOT carry over" list |
Both paths produce a `design.md` Hallmark can read on subsequent runs; the file format is uniform once written.
## Scope
- **Page-builds only.** Skip on component-scope — a single component is too small to be a system.
+81 -4
View File
@@ -271,6 +271,10 @@ If you adopt this DNA, the closest theme in the catalog is [theme name].
That's a candidate, not a requirement — your content might point elsewhere.
Want me to build with this DNA, or change one axis first?
Or — say `lock the DNA` (or `give me a design.md`) if you want a portable
`design.md` of this DNA that you can hand to another AI tool. Opt-in,
never auto.
```
### URL-mode template
@@ -299,9 +303,14 @@ If you adopt this DNA, the closest theme in the catalog is [theme name].
That's a candidate, not a requirement — your content might point elsewhere.
Want me to build with this DNA, or change one axis first?
Or — say `lock the DNA` (or `give me a design.md`) if you want a portable
`design.md` of this DNA. URL-mode emission asks you to confirm the source
is yours or a public reference for your own brand before writing — that
extra friction is intentional.
```
The last line is the **confirmation question** in either mode. Wait for the user before building.
The "Want me to build" line is the **confirmation question** for code generation. The "lock the DNA" line is the **emission CTA** for portable design system output. Both are opt-in; wait for the user before doing either. See § Emitting a `design.md` from `study` below for the emission flow.
---
@@ -388,12 +397,80 @@ If any limit is being violated, say so plainly in the diagnosis report — *"I c
---
## Emitting a `design.md` from `study`
After the diagnosis, the user has a third option alongside "build with this DNA" and "stop here": **emit a portable `design.md`** that captures the DNA as a system other AI tools (Cursor, v0, Bolt, future Hallmark runs) can read directly. This is the same `design.md` format produced by the default verb's "lock the system" flow — but seeded from the studied DNA rather than from a build the user iterated on.
### Trigger phrases
Fire ONLY when the user says one of these *after* a diagnosis:
- *"lock the DNA"* / *"lock this DNA"*
- *"give me a design.md"* / *"write a design.md"* / *"export this as a design.md"*
- *"make this portable"* / *"make the DNA portable"*
If the user just confirms the diagnosis without naming emission, **do not emit**. The CTA in the diagnosis surfaces the option; the trigger phrase confirms intent.
### The emission-refusal layer (tighter than diagnosis refusal)
Diagnosis refusal asks: *"can I read this without crossing the line into cloning a competitor or copying a paid template?"* The answer is usually yes — reading is cheap and educational.
Emission refusal asks: *"can I package this DNA as a portable system the user (or any AI tool the user hands the file to) will then use as their own design language?"* That's meaningfully more extractive than a diagnosis. The user already has the diagnosis; the file is a separate, durable artifact that travels.
The two refusal layers do not match. A reference can clear the diagnosis bar and still fail the emission bar.
**Image mode — emission is allowed by default.** The user owns the screenshot they attached. They can be trusted to have rights to extract from it (their own work, a personal moodboard, a public reference they have permission to learn from). Emit without asking.
**URL mode — emission requires explicit attestation.** Before writing the file, ask one short question and wait for the answer:
> *Before I write the file — `design.md` emission packages this DNA as a portable spec other AI tools can use, which is more extractive than a diagnosis. Is this URL:*
>
> *(a) your own site*
> *(b) a public reference for your own brand (you have permission to learn from it)*
> *(c) something else (a competitor, a designer you admire, a stranger's site you stumbled on)*
>
> *Reply (a), (b), or (c).*
Then dispatch on the answer:
| Answer | Action |
| --- | --- |
| (a) "my own site" | Emit. Note in the file's `## Provenance` block: *"Extracted from `<URL>` — user-owned source, <date>."* |
| (b) "public reference for own brand" | Emit, but include a `## Provenance` block: *"Extracted from `<URL>` as a public reference for the user's brand on <date>. The DNA is structural; specific tokens may need to be regenerated to match the user's brand identity rather than the source's."* |
| (c) "something else" | **Refuse.** *"I won't emit a `design.md` from a third-party site I'm not authorised to extract from. The diagnosis is yours — that's a learning tool. The portable spec needs a source you can attest authorship of, or a public reference for your own brand. If you want a design.md anyway, take a screenshot of your own moodboard or your own existing site, and I'll study that instead."* |
If the user has already disclosed source attribution earlier in the conversation (e.g., during the initial "is this your own work / public reference / competitor" check, they answered "my own site"), do not re-ask — carry that attestation forward. The ask is only needed when status is unknown.
The image-mode refusal table at the top of this file still applies in both modes. A source that already failed the diagnosis refusal (paid template, declared competitor, soft-refused signature work) is auto-refused at emission — do not re-ask.
### What gets written
Use the format defined in [`design-md.md`](design-md.md) § Format, with these `study`-mode adjustments:
1. **Source mode informs token values.** URL mode populates the `## Tokens` block with exact OKLCH / hex values from the source's CSS, and the `## System` block with the exact fonts named in `@font-face` / Google Fonts / `next/font`. Image mode populates the same blocks with the schema's bands rendered into best-guess OKLCH (centre of band) and 12 candidate font names from the canon — flag these as estimated.
2. **Add a `## Provenance` block.** Inserted between `## System` and `## Tokens`. Carries: the source mode, the URL (URL mode only) or "image (user-attached)" (image mode), the date of extraction, the attestation answer if any, and a one-line note about confidence:
- URL mode: *"Tokens are exact (extracted from source CSS). Fonts are exact (extracted from source font declarations). Rhythm is unknown — HTML alone can't judge density."*
- Image mode: *"Tokens are estimated from source-image colour bands. Fonts are role-based with named candidates from the Hallmark canon. Rhythm is from a vision pass on the source."*
3. **Add a `## Notes` block** at the end with the anti-patterns the diagnosis flagged as "do NOT carry over." Future Hallmark runs reading the file should see these as part of the system's identity.
4. **The stamp at the top of the file** carries `studied: yes` and `DNA-source: <mode>` plus the URL or "image" tag, mirroring the macrostructure stamp pattern.
### After the file is written
Same post-emission behaviour as the default verb's lock-the-system flow (per [`design-md.md`](design-md.md) § After the file is written):
- Subsequent Hallmark runs read `design.md` first; diversification inverts to consistency.
- If the user genuinely needs a different system for a future page, amend `design.md` with a `## Variants` section.
- One-line confirmation back to the user: *"design.md written. The system is now locked to the extracted DNA. Future runs will defer to it."*
---
## When `study` should hand off
`study` is the diagnosis verb. It is not for fresh builds and not for refining existing pages.
`study` is the diagnosis verb. It is not for fresh builds and not for refining existing pages. After the diagnosis, the user has three options — and `study` itself stops after any one of them:
- If after the diagnosis the user says *"now build me the same kind of page for my brand"*: hand off to the **default** verb with the schema filled in as inferred design-context, and build per the standard flow — but with the studied DNA stamped.
- If the user says *"now build me the same kind of page for my brand"*: hand off to the **default** verb with the schema filled in as inferred design-context, and build per the standard flow — but with the studied DNA stamped.
- If the user says *"now refactor my existing site to match this DNA"*: hand off to **`hallmark redesign`** with the schema attached. Redesign preserves the user's content; study supplied the new shape.
- If the user says *"lock the DNA"* / *"give me a design.md"*: emit the file per § Emitting a `design.md` from `study` above. The emitted file becomes the new system; subsequent runs defer to it.
- If the user only wanted the diagnosis and is satisfied: stop. The diagnosis report is a complete deliverable on its own.
Do not chain verbs without the user's explicit go-ahead. The diagnosis is the contract; the build is a separate decision.
Do not chain verbs or emit files without the user's explicit go-ahead. The diagnosis is the contract; the build and the file are separate decisions.