mirror of
https://github.com/Nutlope/hallmark.git
synced 2026-08-14 12:35:33 +02:00
The published install command in the README — npx skills add nutlope/hallmark — was failing for users because the skills CLI looks for SKILL.md at the repo root, not at skill/SKILL.md where Hallmark kept it. The clone succeeded but the CLI reported "No skills found." Manual cp was the only working install path. Flattened the layout: - skill/SKILL.md → SKILL.md - skill/references/ → references/ - (skill/ directory removed; was empty after moves) git mv preserved rename history for all 76+ files (SKILL.md + 28 reference files + 21 macrostructures + 46 components + 7 verb/genre subfolders). Updated every cross-reference (36 occurrences across 9 files): - README.md — 4 links (SKILL.md + references/ + the install snippet still reads the same) - ROADMAP.md — 4 links to reference files - package.json — "files" field + "skill" entry/references paths - site/js/main.js — 3 source comments - references/design-md.md — one broken link (was pointing skill/references/export-formats.md from inside references/ — now just export-formats.md as a sibling) - site/_tests/verbs/study/notes.md, diagnosis.md and verbs/audit/audit-report.md, custom/README.md — test-artifact relative paths shortened by one segment (e.g. ../../../skill/SKILL.md → ../../../SKILL.md) No skill content changes. After this lands, 'npx skills add nutlope/hallmark' should clone + install correctly without any manual cp fallback.
365 lines
14 KiB
Markdown
365 lines
14 KiB
Markdown
# Stop letting your agents ship ugly UIs.
|
||
|
||
How to build well-designed UIs with AI agents.
|
||
|
||
Hassan El Mghari · Together AI · AI Engineer World's Fair · 2026
|
||
|
||
---
|
||
|
||
> **About this deck** — this is a general playbook for any AI engineer, not a product pitch. Hallmark is mentioned once, on slide 15, as one open-source example our team built. The seven fixes apply to v0, Lovable, Bolt, Cursor, Claude Code, or any agent you're building yourself.
|
||
>
|
||
> **Visual style** — dark slate `#0b1117`, off-white ink `#e6edf3`, GitHub-cool-blue accent `#58a6ff`. Inter for type, Roboto Mono for code. Every slide chrome-free: no eyebrow labels, no decorative hairlines. Footer is the Together AI logo bottom-left and a page number bottom-right.
|
||
>
|
||
> **Cadence** — 17 slides, 18 minutes. ~60 seconds per slide. Section opener (S05) is a 10-second beat. S08 (wireframes), S11 (eight states), S13 (system prompt) want a moment.
|
||
|
||
---
|
||
|
||
## 01 · Cover
|
||
|
||
# Stop letting your agents ship ugly UIs.
|
||
|
||
*How to build well-designed UIs with AI agents.*
|
||
|
||
— Hassan El Mghari · Together AI · AI Engineer World's Fair · 2026
|
||
|
||
*Speaker: I'm Hassan, I lead DX at Together AI. Most of you have built an AI app this year and watched it ship a UI you'd never put on your portfolio. This talk is about why that happens, and seven concrete things that fix it — for any agent you use.*
|
||
|
||
---
|
||
|
||
## 02 · The problem
|
||
|
||
# Here's what your agent ships today.
|
||
|
||
*(Visual: the real DevForge screenshot — a generated developer-conference landing page. Purple-cyan gradient on the headline, centered hero, four-column stat row, Inter on Inter.)*
|
||
|
||
> Vanilla prompt. Same shape every time.
|
||
|
||
*Speaker: I gave the same prompt to a dozen agents — "build me a landing page for a developer conference, dark theme, in Brooklyn." This is roughly what every one of them returned. Different models, different stacks, same page.*
|
||
|
||
---
|
||
|
||
## 03 · The promise
|
||
|
||
# It could ship this instead.
|
||
|
||
*(Visual: the Hyperlane screenshot — same brief, rebuilt. Big sans-serif headline with an italic-serif accent, asymmetric layout, single warm accent, monospace meta.)*
|
||
|
||
> Same brief. One missing layer added.
|
||
|
||
*Speaker: Same brief. Same agent. The difference is the layer between the prompt and the output. We'll spend the rest of the talk on that layer.*
|
||
|
||
---
|
||
|
||
## 04 · Why
|
||
|
||
# Models ship the mean of their training set.
|
||
|
||
*Every SaaS site since 2019 trained on the same shape. Without external steering, the agent regresses to it.*
|
||
|
||
> Every part of this is fixable with prompting and a small amount of structure.
|
||
|
||
*Speaker: This isn't a model failure. Claude can render anything you describe. It's that "make me a landing page" maps to a region of the manifold where every SaaS site since 2019 lives. The good news: every fix from here is something you can do today, with any agent.*
|
||
|
||
---
|
||
|
||
## 05 · Section opener
|
||
|
||
# Seven things that fix it.
|
||
|
||
*Tool-agnostic. Works with v0, Lovable, Bolt, Cursor, Claude Code, or your own agent.*
|
||
|
||
*Speaker: Each one of these closes a class of slop. Each one works today.*
|
||
|
||
---
|
||
|
||
## 06 · Fix 01 — Use a real component library
|
||
|
||
# Use a real component library.
|
||
|
||
shadcn/ui is the lingua franca of generated UI.
|
||
Every major AI tool is trained on it. Linear, Vercel and Stripe ship it.
|
||
Adopt it and your agent's output gets 80% better on day one.
|
||
|
||
```bash
|
||
$ npx shadcn@latest add button card dialog input table
|
||
```
|
||
|
||
→ *drop the components in. Now every AI generation composes from a real system, not from invented primitives.*
|
||
|
||
*Speaker: This is the cheapest, highest-leverage move. Most AI engineers know about shadcn/ui. Fewer actually adopt it. v0 ships it natively. Cursor reads it. Claude Code reads it. The model has seen millions of examples of these components — it knows how to compose them.*
|
||
|
||
---
|
||
|
||
## 07 · Fix 02 — Pin a design system
|
||
|
||
# Pin a design system.
|
||
|
||
A single file at the root the agent reads on every render.
|
||
One palette, one type pairing, one scale. No mid-render improvisation.
|
||
|
||
```css
|
||
/* DESIGN.md or app/globals.css — Tailwind v4 @theme block */
|
||
|
||
@theme {
|
||
--color-paper: oklch(0.13 0.01 250); /* one surface, not five */
|
||
--color-ink: oklch(0.93 0.01 250); /* one ink */
|
||
--color-accent: oklch(0.65 0.18 250); /* one accent, under 5% */
|
||
--font-display: "Inter Tight", sans-serif;
|
||
--font-body: "Inter", sans-serif;
|
||
--space-1: 0.25rem; /* 4-pt scale */
|
||
--ease-out: cubic-bezier(.2,0,0,1);
|
||
}
|
||
```
|
||
|
||
*Speaker: Tailwind v4 made this easier than it used to be. One `@theme` block, OKLCH for color, semantic names. Drop a `DESIGN.md` next to it that describes the brand in plain English — what the brand sounds like, what it isn't. The agent reads both on every run.*
|
||
|
||
---
|
||
|
||
## 08 · Fix 03 — Ask for a shape
|
||
|
||
# Ask for a shape, not a list of features.
|
||
|
||
*Stop saying "hero with three features." Say marquee. bento. long-document. stat-led.*
|
||
|
||
*(Visual: four abstract wireframes drawn in Figma showing each shape.)*
|
||
|
||
- **MARQUEE** · one editorial idea, biased left
|
||
- **LONG DOCUMENT** · reads like a letter, no marketing chrome
|
||
- **BENTO** · many entries, irregular grid
|
||
- **STAT-LED** · product is the headline; numbers carry it
|
||
|
||
*Speaker: This is the move that breaks the "every page looks like a SaaS landing" attractor. Don't enumerate features. Pick a category of page. The same way Linear's home and Stripe's home don't share a shape — they share a category.*
|
||
|
||
---
|
||
|
||
## 09 · Fix 04 — Show a reference
|
||
|
||
# Paste a screenshot. Don't describe it.
|
||
|
||
AI sees more than it reads.
|
||
A reference image carries more taste than a paragraph of adjectives.
|
||
|
||
```
|
||
→ pick a real site you admire.
|
||
→ ask the agent to extract the structure, not copy the pixels.
|
||
→ name the role of the type ("italic editorial serif"), not the font.
|
||
```
|
||
|
||
*(Visual right: a real screenshot of calendly.com — the reference you'd actually paste.)*
|
||
|
||
> example · pasted calendly.com to the agent
|
||
|
||
*Speaker: Designers have always done this — "make it feel like this." Until recently your agent had no equivalent. Now it does. Don't describe taste. Show it. And ask the model to extract structure, not pixels — what you want is the rhythm, not a knock-off.*
|
||
|
||
---
|
||
|
||
## 10 · Fix 05 — Ban the tells
|
||
|
||
# Tell it what you DON'T want.
|
||
|
||
*Constraints beat instructions. Put these in your system prompt:*
|
||
|
||
- ✕ Purple → blue gradient hero
|
||
- ✕ Inter / Roboto as display AND body
|
||
- ✕ Three equal columns with icon-above-heading
|
||
- ✕ `min-height: 100vh`, everything centered
|
||
- ✕ Cards inside cards (no semantic reason)
|
||
- ✕ `background-clip` text gradients on headlines
|
||
- ✕ Pure `#000` or pure `#fff` as a surface
|
||
- ✕ Invented metrics, testimonials, or logos
|
||
|
||
*Speaker: Counterintuitive but true: telling the model what NOT to do is stronger than describing what you want. These eight tells are the fingerprints of AI-generated UI. Ban them and the model has to reach somewhere else.*
|
||
|
||
---
|
||
|
||
## 11 · Fix 06 — Eight states
|
||
|
||
# Every interactive element ships eight states.
|
||
|
||
*If the agent emits two, your UI ships broken.*
|
||
|
||
*(Visual: eight actual buttons in a 4-by-2 grid, each visibly in a different state — default, hover, focus-visible, active, disabled, loading, error, success.)*
|
||
|
||
| state | what makes it different |
|
||
| --- | --- |
|
||
| `default` | the resting style |
|
||
| `hover` | one shade lighter |
|
||
| `:focus-visible` | a 2px accent ring, instant (no fade-in) |
|
||
| `:active` | inverted ink, accent fill |
|
||
| `disabled` | 50% opacity, no pointer |
|
||
| `loading` | `· · · working` |
|
||
| `error` | red border, ⚠ retry |
|
||
| `success` | green border, ✓ saved |
|
||
|
||
*Speaker: This is the single fastest "real or vibes" test you can run on AI output. Tab into the page. Disable a field. Make something load. If three of the eight states are unstyled, the agent shipped a screenshot, not a component.*
|
||
|
||
---
|
||
|
||
## 12 · Fix 07 — Critique before emit
|
||
|
||
# Make the agent grade its own work — first.
|
||
|
||
*One line in the system prompt forces a critical pass before output. Two passes is normal.*
|
||
|
||
- **DISTINCTIVENESS** · does this look like THIS brief — or any brief
|
||
- **HIERARCHY** · can a reader tell first / second / third in 2 seconds
|
||
- **EXECUTION** · are the details right (rules, spacing, focus rings)
|
||
- **RESTRAINT** · cut what doesn't earn its place
|
||
|
||
Score each 1–5. Anything below 3 → revision pass.
|
||
|
||
*Speaker: The trick isn't the rubric — it's forcing the model to look at its own output critically before it returns. Two passes is normal. Three passes means the brief is too vague.*
|
||
|
||
---
|
||
|
||
## 13 · The whole playbook
|
||
|
||
# You can fit the whole playbook in one paragraph.
|
||
|
||
```md
|
||
# system_prompt.md
|
||
|
||
You are a designer, not a templater. Before you write code:
|
||
|
||
1. use shadcn/ui — never re-invent a primitive that already exists.
|
||
2. read DESIGN.md for tokens. Use only those.
|
||
3. pick ONE page shape (marquee, long-document, bento, stat-led, manifesto, catalogue).
|
||
4. ban: purple-cyan gradients, Inter on Inter, 3-col icon grids, 100vh centered hero,
|
||
card-in-card, background-clip text, pure #000 / #fff, invented metrics.
|
||
5. ship 8 states for every interactive element.
|
||
6. score Distinctiveness · Hierarchy · Execution · Restraint on 1–5.
|
||
anything <3 triggers a revision pass.
|
||
```
|
||
|
||
*Speaker: That's it. Seven lines. Drop this in any agent's system prompt — Cursor `.mdc`, Claude Code skill, v0 project instructions. Feel the difference on the next render.*
|
||
|
||
---
|
||
|
||
## 14 · Tools
|
||
|
||
# Pick your weapon.
|
||
|
||
*Same seven fixes. Different surfaces.*
|
||
|
||
| | | |
|
||
| --- | --- | --- |
|
||
| **v0** | shadcn / Tailwind playground | best UI quality out of the box |
|
||
| **Lovable** | full-stack chat-and-build | edit visually, ship live |
|
||
| **Bolt** | fast prototyping in StackBlitz | speed |
|
||
| **Cursor** | in-IDE assistant | lives in your editor |
|
||
| **Claude Code** | agent loop · file-aware · skills | longest-context coder |
|
||
|
||
*Speaker: All of these can do beautiful work if you put the seven fixes in. Pick the one that matches your stack.*
|
||
|
||
---
|
||
|
||
## 15 · Hallmark — one example our team open-sourced
|
||
|
||
# Hallmark.
|
||
|
||
*One example our team open-sourced.*
|
||
|
||
A Claude Code skill that bakes all seven fixes in.
|
||
|
||
→ `github.com/nutlope/hallmark`
|
||
|
||
*(Visual: the Hallmark OG image — "The best landing pages built with AI" with three real example pages baked in.)*
|
||
|
||
*Speaker: We packaged the seven fixes into a Claude Code skill for ourselves at Together AI, then open-sourced it. It's one approach — there are others (Anthropic's frontend-design skill, Taste, Impeccable, others). The principle is the same: stop letting the agent invent the rules. Hand it a system.*
|
||
|
||
---
|
||
|
||
## 16 · The big idea
|
||
|
||
# Design taste is a layer in the agent stack.
|
||
|
||
```
|
||
MODELS
|
||
TOOLS
|
||
MEMORY
|
||
RAG
|
||
EVALS
|
||
TASTE ← here
|
||
ORCHESTRATION
|
||
```
|
||
|
||
*If you don't put it in the stack, the model picks the mean.*
|
||
|
||
*Speaker: We treat eval as a first-class layer because we know models will optimize for the wrong thing without it. Taste is the same — not a polish step you add at the end. A layer. Same stack you already build with. New row.*
|
||
|
||
---
|
||
|
||
## 17 · Thanks
|
||
|
||
# Thanks.
|
||
|
||
```
|
||
github.com/nutlope/hallmark
|
||
together.ai
|
||
```
|
||
|
||
`@nutlope` `@YoussefXLM`
|
||
|
||
*(Visual right: a real QR code linking to the Hallmark repo.)*
|
||
|
||
> scan to install
|
||
|
||
*Speaker: Thanks. The skill is open today. I'd love to see what you build with it — and what fixes you'd add to your own agent's stack.*
|
||
|
||
---
|
||
|
||
# Designer / production notes
|
||
|
||
**Chrome — kept minimal on purpose**
|
||
|
||
- No eyebrow labels at the top of slides.
|
||
- No decorative hairlines, dividers, or accent rules.
|
||
- Footer is two elements only: the Together AI logo bottom-left (32×32), and the slide number bottom-right.
|
||
- Functional rectangles (code-block surfaces, button shapes on S11, axis cards on S12) are kept — they carry content.
|
||
|
||
**Palette — locked**
|
||
|
||
- BG `#0b1117` (deep slate)
|
||
- Surface `#161b22` (code blocks, cards)
|
||
- Ink primary `#e6edf3`
|
||
- Ink secondary `#7d8590`
|
||
- Accent `#58a6ff` (GitHub cool blue — links, key labels, accent fills)
|
||
- Alert `#f85149` (only on Fix 05 ban list and Fix 06 error button)
|
||
- Success `#3fb950` (only on Fix 06 success button)
|
||
|
||
**Type**
|
||
|
||
- Display: Inter (Black / Bold weights at huge sizes)
|
||
- Body: Inter Regular / Light
|
||
- Code & mono labels: Roboto Mono
|
||
|
||
**Pacing**
|
||
|
||
17 slides for an 18-minute slot ≈ 60 seconds per slide. The section opener (S05) is a 10-second beat. The system-prompt slide (S13) wants a moment for Hassan to read it out loud. The Hallmark slide (S15) is intentionally quiet — read the label, don't dwell.
|
||
|
||
**If running long**
|
||
|
||
In order: S04 (Why — can fold into S02 narration), S16 (the stack diagram — can be one sentence after S15). Never drop S05, S08, S09, S11.
|
||
|
||
**If running short**
|
||
|
||
Add a live demo after S09. Paste a screenshot of a designed site, run the agent, show the output. 90 seconds max.
|
||
|
||
**The markdown deliverable**
|
||
|
||
This file (`docs/talk-slides.md`) is the canonical copy. If the Figma file gets reorganized, this stays authoritative.
|
||
|
||
---
|
||
|
||
# Sources
|
||
|
||
- ["shadcn/ui March 2026 Update: CLI v4, AI Agent Skills and Design System Presets"](https://medium.com/@nakranirakesh/shadcn-ui-march-2026-update-cli-v4-ai-agent-skills-and-design-system-presets-d30cf200b0e9)
|
||
- ["AI-First UIs: Why shadcn/ui's Model is Leading the Pack" — Refine](https://refine.dev/blog/shadcn-blog/)
|
||
- ["Design Systems for the Vibe-Coding Era" — Anna Arteeva, Design Systems Collective](https://www.designsystemscollective.com/design-systems-for-the-vibe-coding-era-42282e1affef)
|
||
- [Anthropic — "Improving frontend design through Skills"](https://claude.com/blog/improving-frontend-design-through-skills)
|
||
- ["v0 by Vercel — Complete Guide 2026"](https://www.nxcode.io/resources/news/v0-by-vercel-complete-guide-2026)
|
||
- ["The Vibe-Coder's Prompting Guide" — Anna Arteeva, Medium](https://annaarteeva.medium.com/the-vibe-coders-prompting-guide-e04ba0295a18)
|
||
- ["Choosing your AI prototyping stack: Lovable, v0, Bolt, Replit, Cursor, Magic Patterns" — Anna Arteeva, Medium](https://annaarteeva.medium.com/choosing-your-ai-prototyping-stack-lovable-v0-bolt-replit-cursor-magic-patterns-compared-9a5194f163e9)
|
||
- [AI Engineer World's Fair 2026 — Jun 29 – Jul 2](https://www.ai.engineer/worldsfair)
|
||
- [Hassan El Mghari · DX at Together AI](https://www.nutlope.com/)
|