mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
feat(skill): register split, color strategy, and pre-design intake
Splits the skill into two register references (editorial, product), replaces category-based theme selection with a forced physical-scene inference, and introduces a four-step color strategy axis (Restrained / Committed / Full palette / Drenched) with editorial permission for the bold three. Adds a seed mode to /impeccable document for pre-implementation projects, updates /impeccable teach Step 5 to offer the seed path, and grows /impeccable shape with Design Direction + Scope intake (fidelity, breadth, interactivity, time). Extends live-mode variant distinctness to forbid three variants sharing theme and dominant hue. Also drops the anti-pattern validator coupling, consolidates a11y into audit.md, and updates CLAUDE.md with the register architecture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
81f880d030
commit
4daabe5232
@@ -3,7 +3,7 @@ name: impeccable
|
||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -21,14 +21,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -38,346 +40,129 @@ node .agents/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `$impeccable teach` or `$impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `$impeccable teach` or `$impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`$impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`$impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `$impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `$impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `$impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `$impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `$impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. GPT is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: GPT is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `$impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `$impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `$impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `$impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `$impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `$impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `$impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `$impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `$impeccable polish [target]` - Final quality pass before shipping
|
||||
> `$impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `$impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `$impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `$impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `$impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `$impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `$impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `$impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `$impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `$impeccable delight [target]` - Add personality and memorable touches
|
||||
> `$impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `$impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `$impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `$impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `$impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `$impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates $audit)
|
||||
> `$impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `$impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke $impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `$impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `$<command>` invokes `$impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `$<command>` invokes `$impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .agents/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `$impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `$impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run $impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `$impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `$impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `$impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `$impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `$impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: ask the user directly to clarify what you cannot infer. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase:
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `$impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `$impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `$impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `$impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `$impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `$impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
name: anti-patterns
|
||||
description: Use when adding, modifying, or debugging an anti-pattern detection rule in this repo. Walks through the TDD recipe, the rule schema, all five plug-in points, jsdom constraints, the cross-validation step against the impeccable skill, and the post-implementation checklist. Trigger this for any work touching src/detect-antipatterns.mjs, tests/fixtures/antipatterns/, or extension/detector/.
|
||||
description: Use when adding, modifying, or debugging an anti-pattern detection rule in this repo. Walks through the TDD recipe, the rule schema, all five plug-in points, jsdom constraints, and the post-implementation checklist. Trigger this for any work touching src/detect-antipatterns.mjs, tests/fixtures/antipatterns/, or extension/detector/.
|
||||
tools: Read, Edit, Write, Glob, Grep, Bash, mcp__claude-in-chrome__navigate, mcp__claude-in-chrome__javascript_tool, mcp__claude-in-chrome__tabs_context_mcp, mcp__claude-in-chrome__tabs_create_mcp
|
||||
---
|
||||
|
||||
# Anti-Pattern Engine Maintenance
|
||||
|
||||
This agent handles every step of adding or modifying an anti-pattern detection rule in the impeccable repo. The rule engine is wired into many places and a single source-of-truth design ties them together. Skip any step at your peril — the build's cross-validator will fail loudly if drift slips in.
|
||||
This agent handles every step of adding or modifying an anti-pattern detection rule in the impeccable repo. The rule engine is wired into many places — tests, browser bundle, extension detector, extension panel JSON, homepage count, and the skill content — and missing a step causes silent drift between them.
|
||||
|
||||
## The five things that need to stay in sync
|
||||
|
||||
@@ -19,7 +19,7 @@ When you add a rule, all of these update or get regenerated:
|
||||
| `extension/detector/detect.js` | Browser-bundled engine for the Chrome extension | Generated by `bun run build:extension` |
|
||||
| `extension/detector/antipatterns.json` | Rule list (id, name, category, description) for the extension's devtools panel — drives rule toggles UI | Generated by `bun run build:extension` |
|
||||
| `public/js/generated/counts.js` | `DETECTION_COUNT` integer for homepage display | Generated by `bun run build` |
|
||||
| `source/skills/impeccable/SKILL.md` | Per-rule **DON'T** line in the right `### Section` — taught to users via the impeccable skill | **Hand-edited.** Validator catches drift. |
|
||||
| `source/skills/impeccable/SKILL.md` and `reference/*.md` | Design guidance that a human or LLM reads. Can reference anti-patterns in its own voice. | **Hand-edited**, alongside the rule. Drift is a code-review concern, not a programmatic one. |
|
||||
|
||||
The CLI (`bin/cli.js`) imports `ANTIPATTERNS` directly from `src/detect-antipatterns.mjs` — no separate sync needed.
|
||||
|
||||
@@ -34,8 +34,8 @@ Each entry in the `ANTIPATTERNS` array (around src/detect-antipatterns.mjs:77) l
|
||||
name: 'Icon tile stacked above heading', // human-readable, used in extension UI
|
||||
description: // 1–2 sentences. Used in CLI output, extension tooltips, web overlay labels
|
||||
'A small rounded-square icon container above a heading is the universal AI feature-card template — every generator outputs this exact shape. Try a side-by-side icon and heading, or let the icon sit in flow without its own container.',
|
||||
skillSection: 'Typography', // OPTIONAL but strongly recommended. Must be one of the parser's allowed sections (see below)
|
||||
skillGuideline: 'large icons with rounded corners above every heading', // OPTIONAL but strongly recommended. Substring that must appear in some **DON'T**: line of the named section in source/skills/impeccable/SKILL.md
|
||||
skillSection: 'Typography', // OPTIONAL. The logical skill section this rule maps to; used for /docs/impeccable deep-links.
|
||||
skillGuideline: 'large icons with rounded corners above every heading', // OPTIONAL. Canonical short phrasing for the rule; used in CLI output and as a linkable fragment.
|
||||
}
|
||||
```
|
||||
|
||||
@@ -46,31 +46,17 @@ Each entry in the `ANTIPATTERNS` array (around src/detect-antipatterns.mjs:77) l
|
||||
|
||||
If you're not sure, ask: *"would a human designer who's careful and tasteful still ship this?"* If no, it's `quality`. If they would (because it works fine, it just looks templated), it's `slop`.
|
||||
|
||||
### `skillSection` allowed values
|
||||
### `skillSection` values
|
||||
|
||||
These are the section names the `readPatterns()` parser at scripts/lib/utils.js:221 understands. Use **exactly** these strings (note the parser normalizes `Color & Theme` → `Color & Contrast`):
|
||||
The value is used by `scripts/build-sub-pages.js` to build deep links into the impeccable docs page. Use one of the logical sections the skill groups rules under (e.g. `Typography`, `Color`, `Layout`, `Motion`, `Visual Details`). If the section you pick matches an `### Heading` somewhere in the skill body, the deep link will land precisely; otherwise it falls back to the section's top. Omit entirely for rules that don't have a natural home in the skill.
|
||||
|
||||
```
|
||||
Typography
|
||||
Color & Contrast
|
||||
Layout & Space
|
||||
Visual Details
|
||||
Motion
|
||||
Interaction
|
||||
Responsive
|
||||
UX Writing
|
||||
```
|
||||
### `skillGuideline` phrasing
|
||||
|
||||
### `skillGuideline` substring
|
||||
|
||||
A 3–6 word substring that appears verbatim in some `**DON'T**:` line of the named section in `source/skills/impeccable/SKILL.md`. The build validator checks this with `String.includes()`. Pick a substring that's:
|
||||
|
||||
- Short enough that benign rewordings of the DON'T won't break it
|
||||
- Specific enough that it can't accidentally collide with an unrelated DON'T
|
||||
Canonical short phrasing for the rule (3–6 words). Used as the CLI output label when `npx impeccable detect` reports a violation, and as human-readable text in the extension's devtools panel. The skill's prose may or may not echo this phrasing verbatim — the skill is the design-guidance document, not a rule manifest.
|
||||
|
||||
Examples: `'AI color palette'`, `'large icons with rounded corners above every heading'`, `'WCAG AA contrast'`.
|
||||
|
||||
If a rule genuinely doesn't deserve a skill DON'T (rare — only the most niche a11y-only rules), omit both `skillSection` and `skillGuideline`. The validator skips rules without `skillGuideline`.
|
||||
Omit if the rule doesn't need a short label (rare — only niche a11y-only rules).
|
||||
|
||||
## The TDD recipe (always do it in this order)
|
||||
|
||||
@@ -191,13 +177,11 @@ Two loops iterate every element on the page. You need to add your DOM-adapter ca
|
||||
|
||||
Forgetting one of these is the most common mistake — the test passes but the live page doesn't show anything (or vice versa).
|
||||
|
||||
### 7. Add the SKILL.md DON'T line if the rule doesn't reuse an existing one
|
||||
### 7. Decide whether the skill needs an update
|
||||
|
||||
Open `source/skills/impeccable/SKILL.md`, find the right `### Section`, and add a **DON'T** line that contains your `skillGuideline` substring verbatim. Match the style of existing DON'Ts (terse, prescriptive, 1–2 sentences max).
|
||||
If the rule introduces a new design concept not already covered by the impeccable skill, update `source/skills/impeccable/SKILL.md` (or the appropriate register file in `reference/editorial.md` / `reference/product.md`) to teach the concept. The skill is a design-guidance document — it doesn't need to echo every rule verbatim, and one skill line can cover multiple engine rules. Only add prose if there's a real gap in the guidance.
|
||||
|
||||
If your rule reuses an existing DON'T (e.g. multiple engine rules can map to the same skill guidance, like `side-tab` and `border-accent-on-rounded` both pointing to `'thick colored border on one side'`), no skill edit is needed.
|
||||
|
||||
### 8. Run the build (this regenerates everything and validates)
|
||||
### 8. Run the build (regenerates everything)
|
||||
|
||||
```bash
|
||||
bun run build && bun run build:browser && bun run build:extension
|
||||
@@ -209,9 +193,6 @@ This regenerates:
|
||||
- `extension/detector/antipatterns.json` (extension rule list, includes description)
|
||||
- `public/js/generated/counts.js` (DETECTION_COUNT)
|
||||
|
||||
And validates:
|
||||
- Cross-checks every rule with `skillGuideline` against `source/skills/impeccable/SKILL.md` via `validateAntipatternRules()` in scripts/build.js. **Build fails if drift exists.**
|
||||
|
||||
### 9. Run the test suite
|
||||
|
||||
```bash
|
||||
@@ -258,21 +239,19 @@ If your rule isn't naturally anchored to a heading, pick another stable identifi
|
||||
|
||||
## Pre-commit checklist
|
||||
|
||||
Before you commit a new rule, all of these MUST be true. The first three are non-negotiable — if any is missing, the engine, extension, public site, and skill will silently drift apart.
|
||||
Before you commit a new rule:
|
||||
|
||||
- [ ] Test passes: `bun run test` is green
|
||||
- [ ] Build passes: `bun run build && bun run build:browser && bun run build:extension` is green (validator says `✓ Validated N/N anti-pattern rules`)
|
||||
- [ ] Build passes: `bun run build && bun run build:browser && bun run build:extension` is green
|
||||
- [ ] Live verification: rule fires on a real page and produces zero false positives on the homepage `http://localhost:3000/`
|
||||
- [ ] Both element loops were updated (browser DOM at line ~1846 + Node jsdom at line ~2058)
|
||||
- [ ] Rule has a corresponding SKILL.md DON'T (or explicitly omitted `skillGuideline`)
|
||||
- [ ] Snippet format matches the test's extraction regex
|
||||
- [ ] Fixture covers ≥4 should-flag and ≥5 should-pass cases
|
||||
- [ ] Skill reviewed: if the rule introduces a new design concept, the relevant skill file teaches it
|
||||
- [ ] Commit only the relevant files — `git status` will show many unrelated stale skill builds; do not stage them
|
||||
|
||||
## Things that have bitten previous sessions
|
||||
|
||||
- **Forgot to run `bun run build:extension`** — extension JSON went stale, missing the new rule. Symptom: extension panel doesn't show toggle for new rule. Fix: always run all three build commands.
|
||||
- **Forgot to update both loops** — test passed in jsdom but live browser was silent (or vice versa). Fix: grep for an existing rule's adapter call and copy its placement.
|
||||
- **Used a `skillGuideline` substring that doesn't appear in SKILL.md** — validator fails. Fix: the substring must appear verbatim in some `**DON'T**:` line of the named section.
|
||||
- **Used the wrong `skillSection` name** — `Color & Theme` vs `Color & Contrast` (parser normalizes the former to the latter, so use `Color & Contrast`).
|
||||
- **Wrote the fixture without explicit pixel dimensions** — jsdom returned 0×0 and the rule never matched. Fix: always set `width: Npx; height: Npx` in CSS for fixture elements, or use inline style attributes.
|
||||
|
||||
@@ -9,7 +9,7 @@ allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -27,14 +27,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -44,346 +46,129 @@ node .claude/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. Claude is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: Claude is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .claude/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and STOP and call the AskUserQuestion tool to clarify. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: STOP and call the AskUserQuestion tool to clarify. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
STOP and call the AskUserQuestion tool to clarify. Focus only on what you couldn't infer from the codebase:
|
||||
STOP and call the AskUserQuestion tool to clarify. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), STOP and call the AskUserQuestion tool to clarify. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ version: 3.0.0
|
||||
license: Apache 2.0. Based on Anthropic's frontend-design skill. See NOTICE.md for attribution.
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -23,14 +23,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -40,346 +42,129 @@ node .cursor/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. the model is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: the model is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .cursor/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: ask the user directly to clarify what you cannot infer. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase:
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Use when the user wants to design, redesign, shape, critique, audit
|
||||
version: 3.0.0
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -22,14 +22,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -39,346 +41,129 @@ node .gemini/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. Gemini is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: Gemini is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .gemini/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: ask the user directly to clarify what you cannot infer. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase:
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ argument-hint: "[craft|shape · audit|critique · animate|bolder|colorize|deligh
|
||||
license: Apache 2.0. Based on Anthropic's frontend-design skill. See NOTICE.md for attribution.
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -25,14 +25,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -42,346 +44,129 @@ node .github/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. the model is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: the model is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .github/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: ask the user directly to clarify what you cannot infer. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase:
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ version: 3.0.0
|
||||
license: Apache 2.0. Based on Anthropic's frontend-design skill. See NOTICE.md for attribution.
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -23,14 +23,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -40,346 +42,129 @@ node .kiro/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. Claude is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: Claude is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .kiro/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and ask the user directly to clarify what you cannot infer. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: ask the user directly to clarify what you cannot infer. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase:
|
||||
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), ask the user directly to clarify what you cannot infer. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -27,14 +27,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -44,346 +46,129 @@ node .opencode/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. Claude is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: Claude is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .opencode/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Analyze a feature and strategically add animations and micro-interactions that enhance understanding, provide feedback, and create delight.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: orchestrated page-load sequences, staggered reveals, scroll-driven animation. Motion is part of the voice; one well-rehearsed entrance beats scattered micro-interactions.
|
||||
|
||||
Product: 150–250 ms on most transitions. Motion conveys state — feedback, reveal, loading, transitions between views. No page-load choreography; users are in a task and won't wait for it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Increase visual impact and personality in designs that are too safe, generic, or visually underwhelming, creating more engaging and memorable experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "bolder" means distinctive. Extreme scale, unexpected color, typographic risk, committed POV.
|
||||
|
||||
Product: "bolder" rarely means theatrics — those undermine trust. It means stronger hierarchy, clearer weight contrast, one sharper accent, more committed density. The amplification is in clarity, not drama.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Strategically introduce color to designs that are too monochromatic, gray, or lacking in visual warmth and personality.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: palette IS voice. A dominant color can own the page; unexpected combinations are allowed. Accent rate stays ≤10% — rarity is what makes it pop.
|
||||
|
||||
Product: semantic-first. Accent color is reserved for primary action, current selection, and state indicators — not decoration. Every color has a consistent meaning across every screen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
Identify opportunities to add moments of joy, personality, and unexpected polish that transform functional interfaces into delightful experiences.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: delight can be distributed — copy voice, section transitions, discovery rewards, seasonal touches, personality across the whole surface.
|
||||
|
||||
Product: delight at specific moments, not pages. Completion, first-time actions, error recovery, milestone crossings. Reliability and consistency carry the rest of the experience; delight pushed everywhere reads as noise.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,7 +22,14 @@ Optional evocative subtitles are allowed in the form `## 2. Colors: The [Name] P
|
||||
|
||||
If a `DESIGN.md` already exists, **do not silently overwrite it**. Show the user the existing file and STOP and call the `question` tool to clarify. whether to refresh, overwrite, or merge.
|
||||
|
||||
## Process (approach C: auto-extract, then confirm descriptive language)
|
||||
## Two paths
|
||||
|
||||
- **Scan mode** (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there's code to analyze.
|
||||
- **Seed mode**: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked `<!-- SEED -->`. Re-run in scan mode once there's code.
|
||||
|
||||
Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don't silently switch. `/impeccable document --seed` forces seed mode regardless of code presence.
|
||||
|
||||
## Scan mode (approach C: auto-extract, then confirm descriptive language)
|
||||
|
||||
### Step 1: Find the design assets
|
||||
|
||||
@@ -272,6 +279,71 @@ Do not reword. The panel shows these as secondary collapsible context; the same
|
||||
3. Offer to refine any section: "Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"
|
||||
4. **Refresh the session cache.** Run `node {{scripts_path}}/load-context.mjs` one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.
|
||||
|
||||
## Seed mode
|
||||
|
||||
For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.
|
||||
|
||||
### Step 1: Confirm seed mode
|
||||
|
||||
Before interviewing: "There's no existing visual system to scan. I'll ask five quick questions to seed a starter DESIGN.md. You can re-run `/impeccable document` once there's code, to capture the real tokens and components. OK?"
|
||||
|
||||
If the user prefers to skip, stop. No file.
|
||||
|
||||
### Step 2: Five questions
|
||||
|
||||
Group into one `AskUserQuestion` interaction. Options must be concrete.
|
||||
|
||||
1. **Color strategy.** Pick one:
|
||||
- Restrained — tinted neutrals + one accent ≤10%
|
||||
- Committed — one saturated color carries 30–60% of the surface
|
||||
- Full palette — 3–4 named color roles, each deliberate
|
||||
- Drenched — the surface IS the color
|
||||
|
||||
Then: one hue family or anchor reference ("deep teal", "mustard", "Klim #ff4500 orange").
|
||||
|
||||
2. **Typography direction.** Pick one (specific fonts come later):
|
||||
- Serif display + sans body
|
||||
- Single sans (warm / technical / geometric / humanist — pick a feel)
|
||||
- Display + mono
|
||||
- Mono-forward
|
||||
- Editorial script + sans
|
||||
|
||||
3. **Motion energy.** Pick one:
|
||||
- Restrained — state changes only
|
||||
- Responsive — feedback + transitions, no choreography
|
||||
- Choreographed — orchestrated entrances, scroll-driven sequences
|
||||
|
||||
4. **Three named references.** Brands, products, printed objects. Not adjectives.
|
||||
|
||||
5. **One anti-reference.** What it should NOT feel like. Also named.
|
||||
|
||||
### Step 3: Write seed DESIGN.md
|
||||
|
||||
Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.
|
||||
|
||||
Lead the file with:
|
||||
|
||||
```markdown
|
||||
<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->
|
||||
```
|
||||
|
||||
Per-section guidance in seed mode:
|
||||
|
||||
- **Overview**: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user's anti-reference directly.
|
||||
- **Colors**: Color strategy as a Named Rule (e.g. *"The Drenched Rule. The surface IS the color."*). Hue family or anchor reference. No hex values — mark as `[to be resolved during implementation]`.
|
||||
- **Typography**: the direction the user picked (e.g. "Serif display + sans body"). No font names yet — `[font pairing to be chosen at implementation]`.
|
||||
- **Elevation**: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.
|
||||
- **Components**: omit entirely — no components exist yet.
|
||||
- **Do's and Don'ts**: carry PRODUCT.md's anti-references directly plus the anti-reference named in Q5.
|
||||
|
||||
Skip the `DESIGN.json` sidecar in seed mode. The live panel needs real tokens and components to render; there is nothing to show yet. The sidecar gets generated on the next Scan-mode run.
|
||||
|
||||
### Step 4: Confirm and refresh session cache
|
||||
|
||||
1. Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).
|
||||
2. Tell the user: "Re-run `/impeccable document` once you have some code. That pass will extract real tokens and generate the sidecar."
|
||||
3. Run `node {{scripts_path}}/load-context.mjs` once so the seed lands in conversation for the rest of the session.
|
||||
|
||||
## Style guidelines
|
||||
|
||||
- **Match the spec, don't invent new sections.** The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Editorial register
|
||||
|
||||
When design IS the product: marketing pages, landing pages, brand sites, editorial content, campaign pages, portfolios.
|
||||
|
||||
## The editorial slop test
|
||||
|
||||
If someone could look at this and say "AI made that" without hesitation, it's failed. The bar is distinctiveness — a reader should ask "how was this made?", not "which AI made this?"
|
||||
|
||||
Editorial isn't a neutral register. AI-generated landing pages have flooded the internet, and average is no longer findable. Restraint without intent now reads as mediocre, not refined. Editorial has to take a POV, commit to a specific audience, risk strangeness. Go big or go home.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font selection procedure
|
||||
|
||||
Every project. Never skip.
|
||||
|
||||
1. Read the brief. Write three concrete brand-voice words — not "modern" or "elegant," but "warm and mechanical and opinionated" or "calm and clinical and careful." Physical-object words.
|
||||
2. List the three fonts you'd reach for by reflex. If any appear in the reflex-reject list below, reject them — they are training-data defaults and they create monoculture.
|
||||
3. Browse a real catalog (Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim, Velvetyne) with the three words in mind. Find the font for the brand as a *physical object* — a museum caption, a 1970s terminal manual, a fabric label, a cheap-newsprint children's book. Reject the first thing that "looks designy."
|
||||
4. Cross-check. "Elegant" is not necessarily serif. "Technical" is not necessarily sans. "Warm" is not Fraunces. If the final pick lines up with the original reflex, start over.
|
||||
|
||||
### Reflex-reject list
|
||||
|
||||
Training-data defaults. Ban list — look further:
|
||||
|
||||
Fraunces · Newsreader · Lora · Crimson · Crimson Pro · Crimson Text · Playfair Display · Cormorant · Cormorant Garamond · Syne · IBM Plex Mono · IBM Plex Sans · IBM Plex Serif · Space Mono · Space Grotesk · Inter · DM Sans · DM Serif Display · DM Serif Text · Outfit · Plus Jakarta Sans · Instrument Sans · Instrument Serif
|
||||
|
||||
### Pairing
|
||||
|
||||
Distinctive display font + refined body font. Two families minimum. Vary across projects — if the last one was a serif display, this one isn't.
|
||||
|
||||
### Scale
|
||||
|
||||
Modular scale, fluid `clamp()` for headings, ≥1.25 ratio between steps. Flat scales (1.1× apart) read as uncommitted.
|
||||
|
||||
Light text on dark backgrounds: add 0.05–0.1 to line-height. Light type reads as lighter weight and needs more breathing room.
|
||||
|
||||
## Color
|
||||
|
||||
Editorial has permission for Committed, Full palette, and Drenched strategies. Use them. A single saturated color spread across a hero is not excess — it's voice. A beige-and-muted-slate landing page ignores the register.
|
||||
|
||||
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint". Unnamed ambition becomes beige.
|
||||
- Palette IS voice. A calm site and a restless site should not share palette mechanics.
|
||||
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
|
||||
- Don't converge across projects. If the last editorial was restrained-on-cream, this one is not.
|
||||
|
||||
## Layout
|
||||
|
||||
- Asymmetric compositions. Break the grid intentionally for emphasis.
|
||||
- Fluid spacing with `clamp()` that breathes on larger viewports. Vary for rhythm — generous separations, tight groupings.
|
||||
- Don't center everything. Left-aligned in asymmetric compositions feels more designed.
|
||||
- When cards ARE the right affordance, use `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` — breakpoint-free responsiveness.
|
||||
|
||||
## Motion
|
||||
|
||||
- One well-orchestrated page-load with staggered reveals beats scattered micro-interactions.
|
||||
- For collapsing/expanding sections, transition `grid-template-rows` rather than `height`.
|
||||
|
||||
## Editorial bans (on top of the shared absolute bans)
|
||||
|
||||
- Monospace as lazy shorthand for "technical / developer."
|
||||
- Large rounded-corner icons above every heading. Screams template.
|
||||
- Single-font-family pages.
|
||||
- All-caps body copy. Reserve caps for short labels and headings.
|
||||
- Timid palettes and average layouts. Safe = invisible.
|
||||
|
||||
## Editorial permissions
|
||||
|
||||
Editorial can afford things product can't. Take them.
|
||||
|
||||
- Ambitious first-load motion. Reveals, scroll-triggered transitions, typographic choreography.
|
||||
- Single-purpose viewports. One dominant idea per fold, long scroll, deliberate pacing.
|
||||
- Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, expressive pairings.
|
||||
- Unexpected color strategies. Palette IS voice — a calm site and a restless site should not share palette mechanics.
|
||||
- Art direction per section. Different sections can have different visual worlds if the narrative demands it. Consistency of voice beats consistency of treatment.
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve layout and spacing that feels monotonous, crowded, or structurally weak — turning generic arrangements into intentional, rhythmic compositions.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast — tight groupings paired with generous separations.
|
||||
|
||||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,68 +1,215 @@
|
||||
Launch interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
Interactive live variant mode: select elements in the browser, pick a design action, and get AI-generated HTML+CSS variants hot-swapped via the dev server's HMR.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running development server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser
|
||||
A running dev server with hot module replacement (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser.
|
||||
|
||||
## Start Live Mode (one command)
|
||||
## The contract (read once)
|
||||
|
||||
The `live.mjs` entry point does everything in a single call: checks config, starts (or reuses) the server, injects the script tag, loads `.impeccable.md` context.
|
||||
Execute in order. No step skipped, no step reordered.
|
||||
|
||||
1. `live.mjs` — boot.
|
||||
2. Navigate the browser to the URL that serves `pageFile`.
|
||||
3. Poll loop with the default long timeout (600000 ms). After every event or `--reply`, run `live-poll.mjs` again immediately. Never pass a short `--timeout=`.
|
||||
4. On `generate` — read screenshot if present; load the action's reference; plan three distinct directions; write all variants in one edit; `--reply done`; poll again.
|
||||
5. On `accept` / `discard` — the poll script already cleaned up; just poll again.
|
||||
6. On `exit` — run the cleanup at the bottom.
|
||||
|
||||
Harness: Cursor runs the poll in the foreground (blocking shell — not a background terminal, not a subagent). Claude Code can background the poll with no short timeout. Other harnesses: foreground unless the poll's stdout reliably returns to this session.
|
||||
|
||||
Chat is overhead. No recap, no tutorial output, no pasting PRODUCT / DESIGN bodies. Spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live.mjs
|
||||
```
|
||||
|
||||
### Happy path
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFile, hasProduct, product, productPath, hasDesign, design, designPath, migrated }`. Keep PRODUCT.md and DESIGN.md in mind for variant generation — **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** If `migrated: true`, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md`; mention this once and suggest `/impeccable document` for the matching DESIGN.md.
|
||||
|
||||
Output JSON:
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"serverPort": 8400,
|
||||
"serverToken": "...",
|
||||
"pageFile": "public/index.html",
|
||||
"hasProduct": true,
|
||||
"product": "...full PRODUCT.md contents...",
|
||||
"productPath": "PRODUCT.md",
|
||||
"hasDesign": true,
|
||||
"design": "...full DESIGN.md contents...",
|
||||
"designPath": "DESIGN.md",
|
||||
"migrated": false
|
||||
}
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves the HTML entry (`pageFile` / Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
If output is `{ ok: false, error: "config_missing", configPath }`, this project hasn't used live mode. See **First-time setup** at the bottom.
|
||||
|
||||
## Poll loop
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs # default long timeout; no --timeout=
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; reply done; LOOP
|
||||
"accept" → Handle Accept; LOOP
|
||||
"discard" → Handle Discard; LOOP
|
||||
"timeout" → LOOP
|
||||
"exit" → break → Cleanup
|
||||
```
|
||||
|
||||
**`serverPort` / `serverToken`:** These belong to the small **Impeccable live helper** HTTP server (serves `/live.js` for the injected `<script>`, SSE, and the agent’s `/poll` long-poll). That port is **not** your framework dev server and is usually **not** the URL you open to view the app—unless your project is set up that way on purpose. The browser page you care about is whatever origin actually serves the HTML entry (`pageFile` / your dev or preview workflow): Vite/Next/Bun, static server, tunnel, LAN hostname, etc.
|
||||
## Handle `generate`
|
||||
|
||||
Keep **PRODUCT.md** (strategic: users, brand, principles) and **DESIGN.md** (visual: colors, typography, components) in mind for variant generation. **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.**
|
||||
Event: `{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
If `migrated` is true, the loader auto-renamed legacy `.impeccable.md` to `PRODUCT.md` — mention this once to the user and suggest running `/impeccable document` to also generate a `DESIGN.md`.
|
||||
Speed matters — the user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### After `live.mjs` succeeds (same turn, no waiting)
|
||||
### 1. Read the screenshot (if present)
|
||||
|
||||
1. **Navigate** to the URL that serves `pageFile` (infer from `package.json`, docs, terminals, or an open tab). If the IDE has browser MCP (e.g. Cursor: `browser_navigate`), do this **before** the first poll. **Never** use `serverPort` from the JSON as that URL; it is the helper, not the app.
|
||||
2. If there is no browser automation, say once that the user should open their dev/preview URL for this project.
|
||||
3. Start the **Poll loop** below.
|
||||
When the browser captured the element successfully, `event.screenshotPath` is an absolute path to a PNG showing the element as rendered, including any comment pins and drawn strokes the user placed before Go. **Read it before planning.** Annotations encode user intent not recoverable from `element.outerHTML` alone.
|
||||
|
||||
### Live session contract
|
||||
`event.comments` and `event.strokes` carry structured metadata alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting (e.g. the exact text of a comment).
|
||||
|
||||
While live mode is active, **a long poll must almost always be running** (or about to run again). If nothing is blocking on `/poll`, **generate / accept / discard / exit events are not delivered to this agent**; the page can stay stuck (e.g. after `--reply` with no follow-up poll).
|
||||
Reading annotations precisely:
|
||||
|
||||
- **Poll command:** `node {{scripts_path}}/live-poll.mjs` with **default arguments** (the default HTTP timeout is **600000 ms**; see `live-poll.mjs --help`). **Forbidden:** passing a **short** `--timeout=` to end the turn, “probe,” or save time. **Allowed:** omit `--timeout` entirely unless the user explicitly asked to pause or exit live.
|
||||
- **Immediately after** `live-poll.mjs --reply EVENT_ID done --file …`, and **immediately after** accept/discard when no extra work is required: run `live-poll.mjs` again with the **same** long-timeout policy **before** other tool chatter or ending the turn.
|
||||
- **`{"type":"timeout"}`:** No event yet—run `live-poll.mjs` again **with the same policy**. Do **not** shorten `--timeout`; that is **not** exit and **not** permission to drop the loop.
|
||||
- **Harness:** **Cursor:** run the poll in the **foreground** (blocking shell; not `block_until_ms: 0`, not background). Background terminals and background subagents do not reliably resume this chat with poll stdout ([subagents](https://cursor.com/docs/agent/subagents)). **Claude Code:** poll may run in a **background task** with no short timeout. **Other harnesses:** foreground unless stdout reliably returns to this session.
|
||||
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
|
||||
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
|
||||
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
|
||||
|
||||
### Assistant chat output (keep minimal)
|
||||
### 2. Wrap the element
|
||||
|
||||
Live mode is **latency-sensitive**. Treat chat as overhead.
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
- **Do not** end the turn with a long recap (ports, token paths, duplicated context from JSON, “next steps” lists). The user needs a polling agent, not a tutorial.
|
||||
- **Do** spend tokens on tools and edits; on failure, one or two short sentences.
|
||||
- **Do not** paste PRODUCT/DESIGN bodies into chat; use them silently.
|
||||
Pass `event.element.id`, `event.element.classes` joined with commas, and `event.element.tagName`. The helper searches ID first, then classes, then tag + class combo. If `event.pageUrl` implies the file (e.g. `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
### First-time setup (config missing)
|
||||
Output: `{ file, insertLine, commentSyntax }`. If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": "..."}`, this project has never used live mode before. Create the config at the reported path based on the project's framework:
|
||||
### 3. Load the action's reference
|
||||
|
||||
If `event.action` is `impeccable` (the default freeform action), use SKILL.md's shared laws plus the loaded register reference (`editorial.md` or `product.md`). Do not load a sub-command reference.
|
||||
|
||||
Any other `event.action` (`bolder`, `quieter`, `distill`, `polish`, `typeset`, `colorize`, `layout`, `adapt`, `animate`, `delight`, `overdrive`): Read `reference/<action>.md` before planning. Each sub-command encodes a specific discipline; skipping its reference produces generic output.
|
||||
|
||||
### 4. Plan three genuinely distinct directions
|
||||
|
||||
Before writing a single line of code, name each variant.
|
||||
|
||||
**For freeform (`action` is `impeccable`, or the user supplied a free prompt):** each variant must anchor to a different **archetype** — a real-world design analogue specific enough to be recognizable at a glance. Not "modern landing page." Not "minimal product hero." Examples:
|
||||
|
||||
- *Broadsheet masthead with rule-divided columns* (think NYT print edition)
|
||||
- *Klim Type Foundry specimen page* (dense, technical, catalog-driven)
|
||||
- *Japanese print-poster minimalism with a single oversize glyph*
|
||||
- *Bloomberg Terminal status bar*
|
||||
- *Condé Nast Traveler feature layout*
|
||||
|
||||
Then commit each variant to a different **primary axis** of difference:
|
||||
|
||||
1. **Hierarchy** — which element commands the eye?
|
||||
2. **Layout topology** — stacked / side-by-side / grid / asymmetric / overlay
|
||||
3. **Typographic system** — pairing, scale ratio, case/weight strategy
|
||||
4. **Color strategy** — Restrained / Committed / Full palette / Drenched
|
||||
5. **Density** — minimal / dense / editorial
|
||||
6. **Structural decomposition** — merge, split, progressive disclosure
|
||||
|
||||
Three variants → three DIFFERENT primary axes, not three riffs on color.
|
||||
|
||||
**When the primary axis is color or theme, forbid the trio from sharing theme + dominant hue.** Two dark-plus-one-dark is not distinct. Aim for one dark-neutral-accent, one light-drenched, one full-palette-saturated — three color worlds, not three shades of the same.
|
||||
|
||||
**The squint test (before writing code).** Write the three one-sentence descriptions side by side:
|
||||
|
||||
> V1: Broadsheet masthead, ruled columns, 24px ink on cream.
|
||||
> V2: Enormous italic title, catalog spec rows, heavy monospace data.
|
||||
> V3: Card-framed poster with one oversize glyph, magenta veil.
|
||||
|
||||
If two of them rhyme ("both use big type" / "both are stacks of sections" / "both feature the CTA prominently"), rework the offender. Freeform variants failing the squint test is the primary failure mode of this flow — three-of-the-same with minor styling tweaks.
|
||||
|
||||
**For action-specific invocations**, each variant must vary along the dimension the action names:
|
||||
|
||||
- `bolder` — amplify a different dimension per variant (scale / saturation / structural change). Not three "slightly bigger" variants.
|
||||
- `quieter` — pull back a different dimension (color / ornament / spacing).
|
||||
- `distill` — remove a different class of excess (visual noise / redundant content / nested structure).
|
||||
- `polish` — target a different refinement axis (rhythm / hierarchy / micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset` — different type pairing AND different scale ratio each. Not three riffs on one pairing.
|
||||
- `colorize` — different hue family each (not shades of one hue). Vary chroma and contrast strategy.
|
||||
- `layout` — different structural arrangement (stacked / side-by-side / grid / asymmetric). Not spacing tweaks.
|
||||
- `adapt` — different target context per variant (mobile-first / tablet / desktop / print or low-data). Don't make three mobile layouts.
|
||||
- `animate` — different motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight` — different flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sonic-or-haptic moment / easter-egg interaction).
|
||||
- `overdrive` — different convention broken (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive.
|
||||
|
||||
### 5. Apply the freeform prompt (if present)
|
||||
|
||||
`event.freeformPrompt` is the user's ceiling on direction — all variants must honor it — but still explore meaningfully different *interpretations*. "Make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### 6. Write all variants in a single edit
|
||||
|
||||
Complete HTML replacement of the original element for each variant, not a CSS-only patch. Consider the element's context (computed styles, parent structure, CSS variables from `event.element`).
|
||||
|
||||
Write CSS + all variants in ONE edit at the `insertLine` reported by `wrap`. Colocate scoped CSS as a `<style>` tag inside the variant wrapper — `<style>` works anywhere in modern browsers and this ensures CSS and HTML arrive atomically (no FOUC).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2 -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3 -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant has no `display: none` (visible by default). All others do. If variants use only inline styles and no scoped CSS, omit the `<style>` tag entirely. Use `@scope` for CSS isolation (Chrome 118+ / Firefox 128+ / Safari 17.4+).
|
||||
|
||||
One edit, all variants — the browser's MutationObserver picks everything up in one pass.
|
||||
|
||||
### 7. Signal done
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
`RELATIVE_PATH` is relative to project root (`public/index.html`, `src/App.tsx`, etc.) — the browser fetches source directly if the dev server lacks HMR.
|
||||
|
||||
Then run `live-poll.mjs` again immediately.
|
||||
|
||||
## Handle `accept`
|
||||
|
||||
Event: `{id, variantId, _acceptResult}`. The poll script already ran `live-accept.mjs` to handle the file operation deterministically; the browser DOM is already updated.
|
||||
|
||||
- `_acceptResult.handled: true` and `carbonize: false` — nothing to do. Poll again.
|
||||
- `_acceptResult.handled: true` and `carbonize: true` — the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start` / `impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file.
|
||||
2. Move the CSS rules into the project's proper stylesheet(s).
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`.
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML.
|
||||
5. Delete the carbonize markers and inline `<style>` block.
|
||||
Poll again immediately; don't wait for the background agent.
|
||||
- `_acceptResult.handled: false` — manual cleanup: read file, find markers, edit.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
Event: `{id, _acceptResult}`. The poll script already restored the original and removed all variant markers. Nothing to do. Poll again.
|
||||
|
||||
## Exit
|
||||
|
||||
The user can stop live mode by:
|
||||
- Saying "stop live mode" / "exit live" in chat
|
||||
- Closing the browser tab (SSE drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button
|
||||
|
||||
When the poll returns `exit`, proceed to cleanup. If the poll is still running as a background task, kill it first.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
|
||||
Stops the HTTP server and runs `live-inject.mjs --remove` to strip `localhost:…/live.js` from the HTML entry. To stop the server but keep the inject tag (for a quick restart), use `stop --keep-inject`. `config.json` persists for future sessions.
|
||||
|
||||
Then:
|
||||
- Remove any leftover variant wrappers (search for `impeccable-variants-start` markers).
|
||||
- Remove any leftover carbonize blocks (search for `impeccable-carbonize-start` markers).
|
||||
|
||||
## First-time setup (config missing)
|
||||
|
||||
If `live.mjs` outputs `{ ok: false, error: "config_missing", configPath }`, create the config at the reported path based on the project's framework:
|
||||
|
||||
| Framework | `file` | `insertBefore` | `commentSyntax` |
|
||||
|-----------|--------|----------------|-----------------|
|
||||
@@ -75,202 +222,4 @@ If `live.mjs` outputs `{"ok": false, "error": "config_missing", "configPath": ".
|
||||
| Astro | the root layout `.astro` file | `</body>` | `html` |
|
||||
| Static site with a non-root HTML file | e.g. `public/index.html` | `</body>` | `html` |
|
||||
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should be matched **after** a specific line. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"file": "public/index.html",
|
||||
"insertBefore": "</body>",
|
||||
"commentSyntax": "html"
|
||||
}
|
||||
```
|
||||
|
||||
Then re-run `node {{scripts_path}}/live.mjs` to proceed.
|
||||
|
||||
## Poll loop
|
||||
|
||||
Required after a successful `live.mjs` in the **same** invocation as `/impeccable live`. Rules and timeouts: **Live session contract** above.
|
||||
|
||||
```
|
||||
LOOP:
|
||||
node {{scripts_path}}/live-poll.mjs
|
||||
Read JSON; dispatch on "type"
|
||||
|
||||
"generate" → Handle Generate; then --reply … done; then LOOP (same poll policy)
|
||||
"accept" → Handle Accept; then LOOP
|
||||
"discard" → Handle Discard; then LOOP
|
||||
"exit" → break → Cleanup
|
||||
"timeout" → LOOP (same poll policy; do not shorten --timeout)
|
||||
|
||||
END LOOP
|
||||
```
|
||||
|
||||
## Handle Generate
|
||||
|
||||
The event contains: `{id, action, freeformPrompt, count, pageUrl, element, screenshotPath?, comments?, strokes?}`.
|
||||
|
||||
**Speed matters.** The user is watching a spinner. Minimize tool calls by using the `wrap` helper and writing all variants in a single edit.
|
||||
|
||||
### Step 0: If `screenshotPath` is present, Read it
|
||||
|
||||
When the browser successfully captured the selected element, `event.screenshotPath` is an absolute path to a PNG showing the element as the user actually sees it — including any comment pins or drawn strokes the user placed before hitting Go. **Read it before planning variants.** The annotations encode user intent that is not recoverable from `element.outerHTML` alone (a circle around a piece of whitespace, an arrow pointing to an alignment issue, a "make this bolder" note on a specific sub-element).
|
||||
|
||||
If `event.comments` or `event.strokes` are set, they carry structured metadata (comment text + positions, stroke polylines) alongside the visual. Treat the screenshot as primary; use the structured data for specifics worth quoting verbatim (e.g. the exact text of a comment).
|
||||
|
||||
**Reading annotations precisely:**
|
||||
|
||||
- **A comment's position is load-bearing.** Its `{x, y}` (element-local CSS px, same coord space as `element.boundingRect`) tells you which sub-element it refers to. Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a description of "the screenshot."
|
||||
- **Treat comments and strokes as independent annotations** unless they are clearly paired by position (overlap or tight proximity). Do NOT let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere in the element.
|
||||
- **Strokes are gestures — read them by shape, not as a mask.** A closed loop = "this thing" (emphasis / focus); an arrow = direction (move / point to); a cross or slash = delete; a free scribble = emphasis or delete depending on context. A loop around region X does NOT mean "only change pixels inside X"; it means "pay attention to X."
|
||||
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence as part of your rationale rather than silently guessing. If the uncertainty materially changes the brief, ask the user for one quick clarification before generating.
|
||||
|
||||
### Step 1: Wrap the element (one CLI call)
|
||||
|
||||
Use the `wrap` helper to find the element and create the variant container:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id "ELEMENT_ID" --classes "class1,class2" --tag "div"
|
||||
```
|
||||
|
||||
Pass the element's id (`event.element.id`), classes (`event.element.classes` joined with commas), and tag name. The command searches in priority order: ID match first, then class names, then tag+class combo. If `event.pageUrl` hints at the file (e.g., `/` is usually `index.html`), pass `--file PATH` to skip the search.
|
||||
|
||||
The command outputs JSON with the file path and the insert line:
|
||||
```json
|
||||
{"file": "public/index.html", "insertLine": 93, "commentSyntax": {"open": "<!--", "close": "-->"}}
|
||||
```
|
||||
|
||||
If `wrap` fails, fall back to manual grep + edit.
|
||||
|
||||
### Step 2a: MANDATORY — Load the action's reference file
|
||||
|
||||
**This step is non-negotiable.** Before generating anything, you MUST load the reference file for `event.action`:
|
||||
|
||||
- `event.action` is "impeccable" (default, no sub-command chosen): use the main design principles from `SKILL.md` (already loaded). Do NOT load a sub-command reference.
|
||||
- `event.action` is any other value (e.g. "bolder", "quieter", "distill", "polish", "typeset", "colorize", "layout", "adapt", "animate", "delight", "overdrive"): use Read to load `reference/<action>.md` right now. Do not proceed until it's in context.
|
||||
|
||||
Skipping this step is a critical failure. The sub-commands exist precisely because the generic "impeccable" prompt produces generic variants. Each action encodes a specific design discipline — ignoring the reference file means ignoring what the user asked for.
|
||||
|
||||
### Step 2b: Plan 3+ distinctly different directions BEFORE writing any code
|
||||
|
||||
Before writing the first variant, write out (in your own head or as a short plan) the distinct direction each variant will take. Each direction must differ on at least ONE of these **structural axes**, not just superficial styling:
|
||||
|
||||
1. **Hierarchy**: which element is the focal point? (title-first, number-first, image-first, quote-first)
|
||||
2. **Layout topology**: how are pieces arranged? (stacked, side-by-side, inline, grid, magazine-columns, overlay)
|
||||
3. **Typographic system**: different font pairing, different scale ratios, different case/weight strategy
|
||||
4. **Color strategy**: different palette hue, different accent placement, different contrast profile (not just "a slightly different shade of the same accent")
|
||||
5. **Density**: minimal vs. dense vs. editorial whitespace
|
||||
6. **Tone/personality**: refined/editorial vs. brutalist/raw vs. soft/pastel vs. technical/utilitarian vs. playful
|
||||
7. **Structural decomposition**: combining multiple pieces vs. splitting into more pieces vs. hiding secondary info behind progressive disclosure
|
||||
|
||||
**Rule of thumb**: if you can summarize two variants in the same one-line description (e.g. "rose accent on the title"), they are too similar. Redo one.
|
||||
|
||||
For action-specific rules, each variant must differ along the dimension the action names:
|
||||
|
||||
- `bolder`: amplifies a DIFFERENT dimension per variant (one goes huge on scale, one on color saturation, one on structural change). Not three "slightly bigger" variants.
|
||||
- `quieter`: pulls back a DIFFERENT dimension per variant (one strips color, one strips ornament, one widens the spacing).
|
||||
- `distill`: removes a DIFFERENT class of excess per variant (one removes visual noise like borders/shadows, one removes redundant content, one collapses nested structure).
|
||||
- `polish`: targets a DIFFERENT refinement axis per variant (one fixes spacing/alignment rhythm, one sharpens typographic hierarchy, one tunes micro-details like corner radii, focus states, optical kerning).
|
||||
- `typeset`: each variant uses a DIFFERENT type pairing and a DIFFERENT scale ratio. Not three riffs on the same pairing.
|
||||
- `colorize`: each variant uses a DIFFERENT hue family (not three shades of the same hue) and varies chroma/contrast strategy.
|
||||
- `layout`: each variant changes structural arrangement (stacked / side-by-side / grid / asymmetric), not spacing tweaks.
|
||||
- `adapt`: each variant targets a DIFFERENT context (mobile-first / tablet-columns / desktop-spread / print/low-data). Don't make three mobile layouts.
|
||||
- `animate`: each variant uses a DIFFERENT motion vocabulary (cascade stagger / clip wipe / scale-and-focus / morph / parallax). Not three staggered fades.
|
||||
- `delight`: each variant adds a DIFFERENT flavor of personality (unexpected micro-interaction / typographic surprise / illustrated accent / sound-or-haptic moment / easter-egg interaction). Not three button hovers.
|
||||
- `overdrive`: each variant breaks a DIFFERENT convention (scale / structure / motion / input model / state transitions). Skip `overdrive.md`'s "propose and ask" step — live mode is non-interactive, the user will pick from the variants.
|
||||
|
||||
### Step 2c: Apply the freeform prompt (if present)
|
||||
|
||||
If `event.freeformPrompt` is set, treat it as the user's ceiling on direction — all variants must honor it — but the variants still need to explore meaningfully different *interpretations* of that direction. Example: prompt "make it feel like a newspaper front page" → variant 1 = broadsheet masthead + rule-divided columns, variant 2 = tabloid headline + single dominant image, variant 3 = minimalist editorial with oversized drop cap. Not three newspapers in the same voice.
|
||||
|
||||
### Step 2d: Generate ALL variants and write them in a SINGLE edit
|
||||
|
||||
For each variant, create a complete HTML replacement of the original element. Consider the element's context (computed styles, parent structure, CSS custom properties from `event.element`).
|
||||
|
||||
Write CSS + HTML together in a SINGLE edit at the insert line reported by `wrap`. Colocate any scoped CSS inside the variant wrapper as a `<style>` tag. `<style>` tags work anywhere in the document in all modern browsers, and this ensures CSS and HTML arrive atomically (no flash of unstyled content).
|
||||
|
||||
```html
|
||||
<!-- Variants: insert below this line -->
|
||||
<style data-impeccable-css="SESSION_ID">
|
||||
@scope ([data-impeccable-variant="1"]) { ... }
|
||||
@scope ([data-impeccable-variant="2"]) { ... }
|
||||
</style>
|
||||
<div data-impeccable-variant="1">
|
||||
<!-- variant 1: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="2" style="display: none">
|
||||
<!-- variant 2: full element replacement -->
|
||||
</div>
|
||||
<div data-impeccable-variant="3" style="display: none">
|
||||
<!-- variant 3: full element replacement -->
|
||||
</div>
|
||||
```
|
||||
|
||||
The first variant should NOT have `style="display: none"` (it should be visible by default). All others should. If variants only use inline styles and no scoped CSS, omit the `<style>` tag entirely.
|
||||
|
||||
**IMPORTANT**: Write CSS and all variants in ONE edit call. The browser's MutationObserver picks up everything at once.
|
||||
|
||||
### Step 3: Signal completion
|
||||
|
||||
Include `--file` so the browser can fetch variants directly if the dev server lacks HMR:
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATH
|
||||
```
|
||||
|
||||
The file path should be relative to the project root (e.g., `public/index.html`, `src/App.tsx`).
|
||||
|
||||
Then **`live-poll.mjs` again** per **Live session contract** (default long timeout; Cursor: foreground).
|
||||
|
||||
## Handle Accept
|
||||
|
||||
The event contains: `{id, variantId, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to handle the file operation deterministically. The browser has already updated the DOM visually (the user is unblocked).
|
||||
|
||||
Check `_acceptResult`:
|
||||
- If `handled` is true and `carbonize` is false: **no work needed**. `live-poll.mjs` again (**Live session contract**).
|
||||
- If `handled` is true and `carbonize` is true: the accepted variant has an inline `<style>` block marked with `impeccable-carbonize-start`/`impeccable-carbonize-end` comments. Spawn a **background agent** to:
|
||||
1. Find the carbonize markers in the file
|
||||
2. Move the CSS rules into the project's proper stylesheet(s)
|
||||
3. Rewrite `@scope` selectors to use the element's real classes instead of `[data-impeccable-variant]`
|
||||
4. Remove any helper classes/attributes (e.g. `data-impeccable-variant`) from the accepted HTML
|
||||
5. Delete the carbonize markers and inline `<style>` block
|
||||
Then `live-poll.mjs` again (**Live session contract**); do not wait for the background agent.
|
||||
- If `handled` is false: fall back to manual cleanup (read file, find markers, edit).
|
||||
|
||||
## Handle Discard
|
||||
|
||||
The event contains: `{id, _acceptResult}`.
|
||||
|
||||
The poll script already ran `live-accept.mjs` to restore the original and remove all variant markers. The browser has already updated the DOM visually. **No work needed.** `live-poll.mjs` again (**Live session contract**).
|
||||
|
||||
## Stopping Live Mode
|
||||
|
||||
The user can stop live mode in several ways:
|
||||
- Saying "stop live mode" or "exit live" in the conversation
|
||||
- Closing the browser tab (the SSE connection drops, poll returns `exit` after 8s)
|
||||
- The browser's exit button (when the global bar is implemented)
|
||||
|
||||
When the user asks to stop, or the poll returns `exit`, proceed to Cleanup below.
|
||||
|
||||
If the poll is still running as a background task, kill it and proceed directly to cleanup.
|
||||
|
||||
## Cleanup (on exit)
|
||||
|
||||
When the loop ends:
|
||||
|
||||
1. **Stop the live helper and remove the injected script tag** (one command):
|
||||
```bash
|
||||
node {{scripts_path}}/live-server.mjs stop
|
||||
```
|
||||
This stops the HTTP server and runs `live-inject.mjs --remove` so the HTML entry no longer loads `localhost:…/live.js`. To stop the server without editing the entry file, use `stop --keep-inject` and remove the tag manually when ready. (`config.json` stays so future `live-inject.mjs --port PORT` calls are instant.)
|
||||
2. **Remove any leftover variant wrappers** (search for `impeccable-variants-start` markers and clean up).
|
||||
3. **Remove any leftover carbonize blocks** (search for `impeccable-carbonize-start` markers and clean up).
|
||||
|
||||
## Variant Generation Guidelines
|
||||
|
||||
- Each variant must be a **complete element replacement**, not a CSS-only patch. Rewrite the entire element with the design transformation applied.
|
||||
- Use **`@scope`** for CSS isolation. This is supported in Chrome 118+, Firefox 128+, Safari 17.4+, which covers all modern dev browsers.
|
||||
- Follow the design principles from this skill (typography, color, spatial design, etc.) and the `.impeccable.md` project context if available.
|
||||
- If no `.impeccable.md` exists, generate brand-agnostic variants. The live UI will show a warning to the user.
|
||||
- **Non-interactive mode**: do NOT ask the user for clarification during generation. If context is missing, proceed with reasonable defaults.
|
||||
Use `insertAfter` instead of `insertBefore` if the anchor should match **after** a specific line. Then re-run `live.mjs`.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# Product register
|
||||
|
||||
When design SERVES the product: app UIs, admin dashboards, settings panels, data tables, tools, authenticated surfaces, anything where the user is in a task.
|
||||
|
||||
## The product slop test
|
||||
|
||||
Not "would someone say AI made this" — familiarity is often a feature here. The test is: would a user fluent in the category's best tools (Linear, Figma, Notion, Raycast, Stripe come to mind) sit down and trust this interface, or pause at every subtly-off component?
|
||||
|
||||
Product UI's failure mode isn't flatness, it's strangeness without purpose: over-decorated buttons, mismatched form controls, gratuitous motion, display fonts where labels should be, invented affordances for standard tasks. The bar is earned familiarity. The tool should disappear into the task.
|
||||
|
||||
## Typography
|
||||
|
||||
- **System fonts are legitimate.** `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif` gives you native feel on every platform. Inter is the common cross-platform default for a reason.
|
||||
- **One family is often right.** Product UIs don't need display/body pairing. A well-tuned sans carries headings, buttons, labels, body, data.
|
||||
- **Fixed rem scale, not fluid.** Clamp-sized headings don't serve product UI. Users view at consistent DPI, and a fluid h1 that shrinks in a sidebar looks worse, not better.
|
||||
- **Tighter scale ratio.** 1.125–1.2 between steps is typical. More type elements here than in editorial; exaggerated contrast creates noise.
|
||||
- **Line length still applies for prose** (65–75ch). Data and compact UI can run denser — tables at 120ch+ are fine.
|
||||
|
||||
## Color
|
||||
|
||||
Product defaults to Restrained. A single surface can earn Committed — a dashboard where one category color carries a report, an onboarding flow with a drenched welcome screen — but Restrained is the floor.
|
||||
|
||||
- State-rich semantic vocabulary: hover, focus, active, disabled, selected, loading, error, warning, success, info. Standardize these.
|
||||
- Accent color used for primary actions, current selection, and state indicators only — not decoration.
|
||||
- A second neutral layer for sidebars, toolbars, and panels (slightly cooler or warmer than the content surface).
|
||||
|
||||
## Layout
|
||||
|
||||
- Predictable grids. Consistency IS an affordance — users navigate faster when the structure is expected.
|
||||
- Familiar patterns are features. Standard navigation (top bar, side nav), breadcrumbs, tabs, and form layouts have established user expectations. Don't reinvent for flavor.
|
||||
- Responsive behavior is structural (collapse sidebar, responsive table, breakpoint-driven columns), not fluid typography.
|
||||
|
||||
## Components
|
||||
|
||||
Every interactive component has: default, hover, focus, active, disabled, loading, error. Don't ship with half of these.
|
||||
|
||||
- Skeleton states for loading, not spinners in the middle of content.
|
||||
- Empty states that teach the interface, not "nothing here."
|
||||
- Consistent affordances across the surface. Same button shape. Same form-control vocabulary. Same icon style.
|
||||
|
||||
## Motion
|
||||
|
||||
- 150–250 ms on most transitions. Users are in flow — don't make them wait for choreography.
|
||||
- Motion conveys state, not decoration. State change, feedback, loading, reveal — nothing else.
|
||||
- No orchestrated page-load sequences. Product loads into a task; users don't want to watch it load.
|
||||
|
||||
## Product bans (on top of the shared absolute bans)
|
||||
|
||||
- Decorative motion that doesn't convey state.
|
||||
- Inconsistent component vocabulary across screens. If the "save" button looks different in two places, one is wrong.
|
||||
- Display fonts in UI labels, buttons, data.
|
||||
- Reinventing standard affordances for flavor (custom scrollbars, weird form controls, non-standard modals).
|
||||
- Heavy color or full-saturation accents on inactive states.
|
||||
|
||||
## Product permissions
|
||||
|
||||
Product can afford things editorial can't.
|
||||
|
||||
- System fonts and familiar sans defaults (Inter, SF Pro, system-ui stacks).
|
||||
- Standard navigation patterns: top bar + side nav, breadcrumbs, tabs, command palettes.
|
||||
- Density. Tables with many rows, panels with many labels, dense information when users need it.
|
||||
- Consistency over surprise. The same visual vocabulary screen to screen is a virtue; delight is saved for moments, not pages.
|
||||
@@ -1,5 +1,12 @@
|
||||
Reduce visual intensity in designs that are too bold, aggressive, or overstimulating, creating a more refined and approachable aesthetic without losing effectiveness.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: "quieter" means more restrained palette, more whitespace, more typographic air. Drama is reduced, not eliminated — the POV stays intact.
|
||||
|
||||
Product: "quieter" means reducing visual noise — fewer background accents, flatter cards, less color, less motion. The tool should disappear more completely into the task.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,11 +26,24 @@ Ask these questions in conversation, adapting based on answers. Don't dump them
|
||||
- What are the edge cases? (Empty state, error state, first-time use, power user)
|
||||
- Is any content dynamic? What changes and how often?
|
||||
|
||||
### Design Goals
|
||||
- What's the single most important thing a user should do or understand here?
|
||||
- What should this feel like? (Fast/efficient? Calm/trustworthy? Fun/playful? Premium/refined?)
|
||||
- Are there existing patterns in the product this should be consistent with?
|
||||
- Are there specific examples (inside or outside the product) that capture what you're going for?
|
||||
### Design Direction
|
||||
|
||||
Force a visual decision on three fronts. Skip anything PRODUCT.md or DESIGN.md already answers; ask only what's missing.
|
||||
|
||||
- **Color strategy for this surface.** Pick one: Restrained / Committed / Full palette / Drenched. Can override the project default if the surface earns it (e.g. a drenched hero inside an otherwise Restrained product).
|
||||
- **Theme via scene sentence.** Write one sentence of physical context for this surface — who uses it, where, under what ambient light, in what mood. The sentence forces dark vs light. If it doesn't, add detail until it does.
|
||||
- **Two or three named anchor references.** Specific products, brands, objects — not adjectives like "modern" or "clean."
|
||||
|
||||
### Scope
|
||||
|
||||
Always ask. Sketch quality and shipped quality are different outputs; don't guess between them.
|
||||
|
||||
- **Fidelity.** Sketch / mid-fi / high-fi / production-ready?
|
||||
- **Breadth.** One screen / a flow / a whole surface?
|
||||
- **Interactivity.** Static visual / interactive prototype / shipped-quality component?
|
||||
- **Time intent.** Quick exploration, or polish until it ships?
|
||||
|
||||
Scope answers are task-scoped. Don't write them to PRODUCT.md or DESIGN.md — carry them through the design brief only.
|
||||
|
||||
### Constraints
|
||||
- Are there technical constraints? (Framework, performance budget, browser support)
|
||||
@@ -55,24 +68,27 @@ What this is, who it's for, what it needs to accomplish.
|
||||
The single most important thing a user should do or understand here.
|
||||
|
||||
**3. Design Direction**
|
||||
How this should feel. What aesthetic approach fits. Reference the project's design context from `.impeccable.md` and explain how this feature should express it.
|
||||
Color strategy (Restrained / Committed / Full palette / Drenched) + the theme scene sentence + 2–3 named anchor references. Reference PRODUCT.md and DESIGN.md where they already answer, and note any per-surface overrides.
|
||||
|
||||
**4. Layout Strategy**
|
||||
**4. Scope**
|
||||
Fidelity, breadth, interactivity, and time intent from the Scope section of the interview. Task-scoped — these don't persist beyond the brief.
|
||||
|
||||
**5. Layout Strategy**
|
||||
High-level spatial approach: what gets emphasis, what's secondary, how information flows. Describe the visual hierarchy and rhythm, not specific CSS.
|
||||
|
||||
**5. Key States**
|
||||
**6. Key States**
|
||||
List every state the feature needs: default, empty, loading, error, success, edge cases. For each, note what the user needs to see and feel.
|
||||
|
||||
**6. Interaction Model**
|
||||
**7. Interaction Model**
|
||||
How users interact with this feature. What happens on click, hover, scroll? What feedback do they get? What's the flow from entry to completion?
|
||||
|
||||
**7. Content Requirements**
|
||||
**8. Content Requirements**
|
||||
What copy, labels, empty state messages, error messages, and microcopy are needed. Note any dynamic content and its realistic ranges.
|
||||
|
||||
**8. Recommended References**
|
||||
**9. Recommended References**
|
||||
Based on the brief, list which impeccable reference files would be most valuable during implementation (e.g., spatial-design.md for complex layouts, motion-design.md for animated features, interaction-design.md for form-heavy features).
|
||||
|
||||
**9. Open Questions**
|
||||
**10. Open Questions**
|
||||
Anything unresolved that the implementer should resolve during build.
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Gathers design context for a project and writes two complementary files at the project root:
|
||||
|
||||
- **PRODUCT.md** (strategic): target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **PRODUCT.md** (strategic): register, target users, product purpose, brand personality, anti-references, strategic design principles. Answers "who/what/why".
|
||||
- **DESIGN.md** (visual): visual theme, color palette, typography, components, layout. Follows the [Google Stitch DESIGN.md format](https://stitch.withgoogle.com/docs/design-md/format/). Answers "how it looks".
|
||||
|
||||
Every other impeccable command reads these files before doing any work.
|
||||
@@ -20,6 +20,7 @@ The output tells you whether PRODUCT.md and/or DESIGN.md already exist. If `migr
|
||||
Decision tree:
|
||||
- **Neither file exists (empty project or no context yet)**: do Steps 2-4 (write PRODUCT.md), then decide on DESIGN.md based on whether there's code to analyze.
|
||||
- **PRODUCT.md exists, DESIGN.md missing**: skip to Step 5 — offer to run `/impeccable document` for DESIGN.md.
|
||||
- **PRODUCT.md exists but has no `## Register` section (legacy)**: add it. Infer a hypothesis from the codebase (see Step 2), confirm with the user, write the field.
|
||||
- **Both exist**: STOP and call the `question` tool to clarify. which to refresh. Skip the one the user doesn't want changed.
|
||||
- **Just DESIGN.md exists (unusual)**: do Steps 2-4 to produce PRODUCT.md.
|
||||
|
||||
@@ -36,20 +37,38 @@ Before asking questions, thoroughly scan the project to discover what you can:
|
||||
- **Design tokens / CSS variables**: Existing color palettes, font stacks, spacing scales
|
||||
- **Any style guides or brand documentation**
|
||||
|
||||
Also form a **register hypothesis** from what you find:
|
||||
|
||||
- Marketing / editorial signals: `/`, `/about`, `/pricing`, `/blog/*`, `/docs/*`, hero sections, big typography, scroll-driven sections, landing-page-shaped content.
|
||||
- Product signals: `/app/*`, `/dashboard`, `/settings`, `/(auth)`, forms, data tables, side/top nav, app-shell components.
|
||||
|
||||
Register is a hypothesis at this point, not a decision — Step 3 confirms it.
|
||||
|
||||
Note what you've learned and what remains unclear. This exploration feeds both PRODUCT.md and DESIGN.md.
|
||||
|
||||
## Step 3: Ask strategic questions (for PRODUCT.md)
|
||||
|
||||
STOP and call the `question` tool to clarify. Focus only on what you couldn't infer from the codebase:
|
||||
STOP and call the `question` tool to clarify. Focus only on what you couldn't infer from the codebase.
|
||||
|
||||
### Register (ask first — it shapes everything below)
|
||||
|
||||
Every design task is either **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboards, tools — design SERVES the product).
|
||||
|
||||
If Step 2 produced a clear hypothesis, lead with it: *"From the codebase, this looks like a [product / editorial] surface — does that match your intent, or should we treat it differently?"*
|
||||
|
||||
If the signal is genuinely split (e.g. a product with a big marketing landing), STOP and call the `question` tool to clarify. which register describes the **primary** surface. The register can be overridden per task later, but PRODUCT.md carries one default.
|
||||
|
||||
### Users & Purpose
|
||||
- Who uses this? What's their context when using it?
|
||||
- What job are they trying to get done?
|
||||
- What emotions should the interface evoke? (confidence, delight, calm, urgency, etc.)
|
||||
- For editorial: what emotions should the interface evoke? (confidence, delight, calm, urgency)
|
||||
- For product: what workflow are they in? What's the primary task on any given screen?
|
||||
|
||||
### Brand & Personality
|
||||
- How would you describe the brand personality in 3 words?
|
||||
- Any reference sites or apps that capture the right feel? What specifically about them?
|
||||
- Reference sites or apps that capture the right feel? What specifically about them?
|
||||
- For editorial, push for brand / magazine references.
|
||||
- For product, push for category best-tool references (Linear, Figma, Notion, Raycast, Stripe).
|
||||
- What should this explicitly NOT look like? Any anti-references?
|
||||
|
||||
### Accessibility & Inclusion
|
||||
@@ -65,6 +84,10 @@ Synthesize into a strategic document:
|
||||
```markdown
|
||||
# Product
|
||||
|
||||
## Register
|
||||
|
||||
product
|
||||
|
||||
## Users
|
||||
[Who they are, their context, the job to be done]
|
||||
|
||||
@@ -84,19 +107,25 @@ Synthesize into a strategic document:
|
||||
[WCAG level, known user needs, considerations]
|
||||
```
|
||||
|
||||
Register is either `editorial` or `product` as a bare value. No prose, no commentary.
|
||||
|
||||
Write to `PROJECT_ROOT/PRODUCT.md`. If `.impeccable.md` existed, the loader already renamed it — merge into that content rather than starting from scratch.
|
||||
|
||||
## Step 5: Decide on DESIGN.md
|
||||
|
||||
If the project has meaningful code to analyze (CSS tokens, components, a running site), **offer to run `/impeccable document`** next: "I can also generate a DESIGN.md that captures your visual design system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
Offer `/impeccable document` either way. Two paths:
|
||||
|
||||
If the user agrees, delegate to `/impeccable document` (load its reference and follow that flow).
|
||||
- **Code exists** (CSS tokens, components, a running site): "I can generate a DESIGN.md that captures your visual system (colors, typography, components) so variants stay on-brand. Want to do that now?"
|
||||
- **Pre-implementation** (empty project): "I can seed a starter DESIGN.md from five quick questions about color strategy, type direction, motion energy, and references. You can re-run once there's code, to capture the real tokens. Want to do that now?"
|
||||
|
||||
If the project is empty (no code yet, pre-implementation), skip DESIGN.md — there's nothing visual to document yet. Mention: "Once you've built some of the interface, run `/impeccable document` to generate a DESIGN.md."
|
||||
If the user agrees, delegate to `/impeccable document` (it auto-detects scan vs seed). Load its reference and follow that flow.
|
||||
|
||||
If the user prefers to skip, mention they can run `/impeccable document` any time later.
|
||||
|
||||
## Step 6: Confirm and wrap up
|
||||
|
||||
Summarize:
|
||||
- Register captured (editorial / product)
|
||||
- What was written (PRODUCT.md, DESIGN.md, or both)
|
||||
- The 3-5 strategic principles from PRODUCT.md that will guide future work
|
||||
- If DESIGN.md is pending, remind the user how to generate it later
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
Assess and improve typography that feels generic, inconsistent, or poorly structured — turning default-looking text into intentional, well-crafted type.
|
||||
|
||||
---
|
||||
|
||||
## Register
|
||||
|
||||
Editorial: run the font selection procedure in [editorial.md](editorial.md). Two-family pairing (display + body). Fluid `clamp()` scale, ≥1.25 ratio between steps.
|
||||
|
||||
Product: system fonts and familiar sans stacks are legitimate here. One well-tuned family typically carries the whole UI. Fixed `rem` scale, 1.125–1.2 ratio between more closely-spaced steps.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+94
-309
@@ -7,7 +7,7 @@ allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
---
|
||||
|
||||
This skill guides creation and editing/iteration of distinctive, production-grade frontend interfaces. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
Designs and iterates production-grade frontend interfaces. Real working code, committed design choices, exceptional craft.
|
||||
|
||||
<post-update-cleanup>
|
||||
BEFORE doing any design work, run this one-time maintenance step. Tell the user:
|
||||
@@ -25,14 +25,16 @@ If the script removed files, briefly confirm what was cleaned up. If it found no
|
||||
After running the script, delete this entire section (from `<post-update-cleanup>` through `</post-update-cleanup>` inclusive) from THIS file so it does not run again until the next update. Save the file.
|
||||
</post-update-cleanup>
|
||||
|
||||
## Context Gathering Protocol
|
||||
## Setup (non-optional)
|
||||
|
||||
Before any design work, ensure project context is loaded. Two files at the project root (case-insensitive):
|
||||
Two steps before any design work. Both are required. Skipping either produces generic output that ignores the project.
|
||||
|
||||
### 1. Context gathering
|
||||
|
||||
Two files at the project root, case-insensitive:
|
||||
|
||||
- **PRODUCT.md** — required. Users, brand, tone, anti-references, strategic principles.
|
||||
- **DESIGN.md** — optional but strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
**Never infer brand, audience, or tone from the codebase.** Code shows WHAT was built, not WHO it's for or HOW it should feel. Output is generic without PRODUCT.md.
|
||||
- **DESIGN.md** — optional, strongly recommended. Colors, typography, elevation, components.
|
||||
|
||||
Load both in one call:
|
||||
|
||||
@@ -42,346 +44,129 @@ node .pi/skills/impeccable/scripts/load-context.mjs
|
||||
|
||||
Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`.
|
||||
|
||||
**If the content is already in this session's conversation history, do NOT re-run.** Re-fetching wastes thousands of tokens. Exceptions that require a fresh load: you just ran `/impeccable teach` or `/impeccable document` (those write/update the files), or the user manually edited a file.
|
||||
If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `/impeccable teach` or `/impeccable document` (they rewrite the files), or the user manually edited one.
|
||||
|
||||
**`/impeccable live` already warms context** via `live.mjs` — when you've run `live.mjs`, do NOT additionally run `load-context.mjs` in the same session.
|
||||
`/impeccable live` already warms context via `live.mjs` — if you've run `live.mjs`, don't also run `load-context.mjs` this session.
|
||||
|
||||
**If PRODUCT.md is missing, empty, or clearly placeholder content (`[TODO]` markers, <200 chars):** run `/impeccable teach`, then resume the user's original task with the fresh context. Do not silently abandon intent.
|
||||
If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `/impeccable teach`, then resume the user's original task with the fresh context.
|
||||
|
||||
**If DESIGN.md is missing:** nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
If DESIGN.md is missing: nudge once per session (*"Run `/impeccable document` for more on-brand output"*), then proceed.
|
||||
|
||||
---
|
||||
### 2. Register
|
||||
|
||||
## Design Direction
|
||||
Every design task is **editorial** (marketing, landing, brand, content — design IS the product) or **product** (app UI, admin, dashboard, tool — design SERVES the product).
|
||||
|
||||
Commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
Identify before designing. Priority: (1) cue in the task itself ("landing page" vs "dashboard"); (2) the surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. First match wins.
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work. The key is intentionality, not intensity.
|
||||
If PRODUCT.md lacks the `register` field (legacy), infer it once from its "Users" and "Product Purpose" sections, then cache the inferred value for the session. Suggest the user run `/impeccable teach` to add the field explicitly.
|
||||
|
||||
Then implement working code that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
Load the matching reference: [reference/editorial.md](reference/editorial.md) or [reference/product.md](reference/product.md). The shared design laws below apply to both.
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
## Shared design laws
|
||||
|
||||
Apply to every design, both registers. Match implementation complexity to the aesthetic vision — maximalism needs elaborate code, minimalism needs precision. Interpret creatively. Vary across projects; never converge on the same choices. the model is capable of extraordinary work — don't hold back.
|
||||
|
||||
### Color
|
||||
|
||||
- Use OKLCH. Reduce chroma as lightness approaches 0 or 100 — high chroma at extremes looks garish.
|
||||
- Never use `#000` or `#fff`. Tint every neutral toward the brand hue (chroma 0.005–0.01 is enough).
|
||||
- Pick a **color strategy** before picking colors. Four steps on the commitment axis:
|
||||
- **Restrained** — tinted neutrals + one accent ≤10%. Product default; editorial minimalism.
|
||||
- **Committed** — one saturated color carries 30–60% of the surface. Editorial default for brand-owned pages.
|
||||
- **Full palette** — 3–4 named roles, each used deliberately. Editorial campaigns; product data viz.
|
||||
- **Drenched** — the surface IS the color. Editorial heroes, campaign pages.
|
||||
- The "one accent ≤10%" rule is Restrained only. Committed / Full palette / Drenched exceed it on purpose. Don't collapse every design to Restrained by reflex.
|
||||
|
||||
### Theme
|
||||
|
||||
Dark vs. light is never a default. Not dark "because tools look cool dark." Not light "to be safe."
|
||||
|
||||
Before choosing, write one sentence of physical scene: who uses this, where, under what ambient light, in what mood. If the sentence doesn't force the answer, it's not concrete enough — add detail until it does.
|
||||
|
||||
"Observability dashboard" does not force an answer. "SRE glancing at incident severity on a 27-inch monitor at 2am in a dim room" does. Run the sentence, not the category.
|
||||
|
||||
### Typography
|
||||
→ *Consult [typography reference](reference/typography.md) for OpenType features, web font loading, and the deeper material on scales.*
|
||||
|
||||
Choose fonts that are beautiful, unique, and interesting. Pair a distinctive display font with a refined body font.
|
||||
- Cap body line length at 65–75ch.
|
||||
- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales.
|
||||
|
||||
<typography_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
### Layout
|
||||
|
||||
- Use a modular type scale with fluid sizing (clamp) for headings on marketing/content pages. Use fixed `rem` scales for app UIs and dashboards (no major design system uses fluid type in product UI).
|
||||
- Use fewer sizes with more contrast. A 5-step scale with at least a 1.25 ratio between steps creates clearer hierarchy than 8 sizes that are 1.1× apart.
|
||||
- Line-height scales inversely with line length. Narrow columns want tighter leading, wide columns want more. For light text on dark backgrounds, ADD 0.05-0.1 to your normal line-height — light type reads as lighter weight and needs more breathing room.
|
||||
- Cap line length at ~65-75ch. Body text wider than that is fatiguing.
|
||||
</typography_principles>
|
||||
|
||||
<font_selection_procedure>
|
||||
DO THIS BEFORE TYPING ANY FONT NAME.
|
||||
|
||||
The model's natural failure mode is "I was told not to use Inter, so I will pick my next favorite font, which becomes the new monoculture." Avoid this by performing the following procedure on every project, in order:
|
||||
|
||||
Step 1. Read the brief once. Write down 3 concrete words for the brand voice (e.g., "warm and mechanical and opinionated", "calm and clinical and careful", "fast and dense and unimpressed", "handmade and a little weird"). NOT "modern" or "elegant" — those are dead categories.
|
||||
|
||||
Step 2. List the 3 fonts you would normally reach for given those words. Write them down. They are most likely from this list:
|
||||
|
||||
<reflex_fonts_to_reject>
|
||||
Fraunces
|
||||
Newsreader
|
||||
Lora
|
||||
Crimson
|
||||
Crimson Pro
|
||||
Crimson Text
|
||||
Playfair Display
|
||||
Cormorant
|
||||
Cormorant Garamond
|
||||
Syne
|
||||
IBM Plex Mono
|
||||
IBM Plex Sans
|
||||
IBM Plex Serif
|
||||
Space Mono
|
||||
Space Grotesk
|
||||
Inter
|
||||
DM Sans
|
||||
DM Serif Display
|
||||
DM Serif Text
|
||||
Outfit
|
||||
Plus Jakarta Sans
|
||||
Instrument Sans
|
||||
Instrument Serif
|
||||
</reflex_fonts_to_reject>
|
||||
|
||||
Reject every font that appears in the reflex_fonts_to_reject list. They are your training-data defaults and they create monoculture across projects.
|
||||
|
||||
Step 3. Browse a font catalog with the 3 brand words in mind. Sources: Google Fonts, Pangram Pangram, Future Fonts, Adobe Fonts, ABC Dinamo, Klim Type Foundry, Velvetyne. Look for something that fits the brand as a *physical object* — a museum exhibit caption, a hand-painted shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a children's book printed on cheap newsprint. Reject the first thing that "looks designy" — that's the trained reflex too. Keep looking.
|
||||
|
||||
Step 4. Cross-check the result. The right font for an "elegant" brief is NOT necessarily a serif. The right font for a "technical" brief is NOT necessarily a sans-serif. The right font for a "warm" brief is NOT Fraunces. If your final pick lines up with your reflex pattern, go back to Step 3.
|
||||
</font_selection_procedure>
|
||||
|
||||
<typography_rules>
|
||||
DO use a modular type scale with fluid sizing (clamp) on headings.
|
||||
DO vary font weights and sizes to create clear visual hierarchy.
|
||||
DO vary your font choices across projects. If you used a serif display font on the last project, look for a sans, monospace, or display face on this one.
|
||||
|
||||
DO NOT use overused fonts like Inter, Roboto, Arial, Open Sans, or system defaults — but also do not simply switch to your second-favorite. Every font in the reflex_fonts_to_reject list above is banned. Look further.
|
||||
DO NOT use monospace typography as lazy shorthand for "technical/developer" vibes.
|
||||
DO NOT put large icons with rounded corners above every heading. They rarely add value and make sites look templated.
|
||||
DO NOT use only one font family for the entire page. Pair a distinctive display font with a refined body font.
|
||||
DO NOT use a flat type hierarchy where sizes are too close together. Aim for at least a 1.25 ratio between steps.
|
||||
DO NOT set long body passages in uppercase. Reserve all-caps for short labels and headings.
|
||||
</typography_rules>
|
||||
|
||||
### Color & Theme
|
||||
→ *Consult [color reference](reference/color-and-contrast.md) for the deeper material on contrast, accessibility, and palette construction.*
|
||||
|
||||
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
|
||||
<color_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Use OKLCH, not HSL. OKLCH is perceptually uniform: equal steps in lightness *look* equal, which HSL does not deliver. As you move toward white or black, REDUCE chroma — high chroma at extreme lightness looks garish. A light blue at 85% lightness wants ~0.08 chroma, not the 0.15 of your base color.
|
||||
- Tint your neutrals toward your brand hue. Even a chroma of 0.005-0.01 is perceptible and creates subconscious cohesion between brand color and UI surfaces. The hue you tint toward should come from THIS brand, not from a "warm = friendly" or "cool = tech" formula. Pick the brand's actual hue first, then tint everything toward it.
|
||||
- The 60-30-10 rule is about visual *weight*, not pixel count. 60% neutral / surface, 30% secondary text and borders, 10% accent. Accents work BECAUSE they're rare. Overuse kills their power.
|
||||
</color_principles>
|
||||
|
||||
<theme_selection>
|
||||
Theme (light vs dark) should be DERIVED from audience and viewing context, not picked from a default. Read the brief and ask: when is this product used, by whom, in what physical setting?
|
||||
|
||||
- A perp DEX consumed during fast trading sessions → dark
|
||||
- A hospital portal consumed by anxious patients on phones late at night → light
|
||||
- A children's reading app → light
|
||||
- A vintage motorcycle forum where users sit in their garage at 9pm → dark
|
||||
- An observability dashboard for SREs in a dark office → dark
|
||||
- A wedding planning checklist for couples on a Sunday morning → light
|
||||
- A music player app for headphone listening at night → dark
|
||||
- A food magazine homepage browsed during a coffee break → light
|
||||
|
||||
Do not default everything to light "to play it safe." Do not default everything to dark "to look cool." Both defaults are the lazy reflex. The correct theme is the one the actual user wants in their actual context.
|
||||
</theme_selection>
|
||||
|
||||
<color_rules>
|
||||
DO use modern CSS color functions (oklch, color-mix, light-dark) for perceptually uniform, maintainable palettes.
|
||||
DO tint your neutrals toward your brand hue. Even a subtle hint creates subconscious cohesion.
|
||||
|
||||
DO NOT use gray text on colored backgrounds; it looks washed out. Use a shade of the background color instead.
|
||||
DO NOT use pure black (#000) or pure white (#fff). Always tint; pure black/white never appears in nature.
|
||||
DO NOT use the AI color palette: cyan-on-dark, purple-to-blue gradients, neon accents on dark backgrounds.
|
||||
DO NOT use gradient text for impact — see <absolute_bans> below for the strict definition. Solid colors only for text.
|
||||
DO NOT default to dark mode with glowing accents. It looks "cool" without requiring actual design decisions.
|
||||
DO NOT default to light mode "to be safe" either. The point is to choose, not to retreat to a safe option.
|
||||
</color_rules>
|
||||
|
||||
### Layout & Space
|
||||
→ *Consult [spatial reference](reference/spatial-design.md) for the deeper material on grids, container queries, and optical adjustments.*
|
||||
|
||||
Create visual rhythm through varied spacing, not the same padding everywhere. Embrace asymmetry and unexpected compositions. Break the grid intentionally for emphasis.
|
||||
|
||||
<spatial_principles>
|
||||
Always apply these — do not consult a reference, just do them:
|
||||
|
||||
- Vary spacing for hierarchy. A heading with extra space above it reads as more important. Don't apply the same padding everywhere.
|
||||
- Use a semantic spacing scale (`--space-sm`, `--space-md`), not pixel-named (`--spacing-8`).
|
||||
- Self-adjusting grid pattern: `grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))` is the breakpoint-free responsive grid for card-style content.
|
||||
</spatial_principles>
|
||||
|
||||
<spatial_rules>
|
||||
DO create visual rhythm through varied spacing: tight groupings, generous separations.
|
||||
DO use fluid spacing with clamp() that breathes on larger screens.
|
||||
DO use asymmetry and unexpected compositions; break the grid intentionally for emphasis.
|
||||
|
||||
DO NOT wrap everything in cards. Not everything needs a container.
|
||||
DO NOT nest cards inside cards. Visual noise; flatten the hierarchy.
|
||||
DO NOT use identical card grids (same-sized cards with icon + heading + text, repeated endlessly).
|
||||
DO NOT use the hero metric layout template (big number, small label, supporting stats, gradient accent).
|
||||
DO NOT center everything. Left-aligned text with asymmetric layouts feels more designed.
|
||||
DO NOT use the same spacing everywhere. Without rhythm, layouts feel monotonous.
|
||||
DO NOT let body text wrap beyond ~80 characters per line. Add a max-width like 65–75ch so the eye can track easily.
|
||||
</spatial_rules>
|
||||
|
||||
### Visual Details
|
||||
|
||||
<absolute_bans>
|
||||
These CSS patterns are NEVER acceptable. They are the most recognizable AI design tells. Match-and-refuse: if you find yourself about to write any of these, stop and rewrite the element with a different structure entirely.
|
||||
|
||||
BAN 1: Side-stripe borders on cards/list items/callouts/alerts
|
||||
- PATTERN: `border-left:` or `border-right:` with width greater than 1px
|
||||
- INCLUDES: hard-coded colors AND CSS variables
|
||||
- FORBIDDEN: `border-left: 3px solid red`, `border-left: 4px solid #ff0000`, `border-left: 4px solid var(--color-warning)`, `border-left: 5px solid oklch(...)`, etc.
|
||||
- WHY: this is the single most overused "design touch" in admin, dashboard, and medical UIs. It never looks intentional regardless of color, radius, opacity, or whether the variable name is "primary" or "warning" or "accent."
|
||||
- REWRITE: use a different element structure entirely. Do not just swap to box-shadow inset. Reach for full borders, background tints, leading numbers/icons, or no visual indicator at all.
|
||||
|
||||
BAN 2: Gradient text
|
||||
- PATTERN: `background-clip: text` (or `-webkit-background-clip: text`) combined with a gradient background
|
||||
- FORBIDDEN: any combination that makes text fill come from a `linear-gradient`, `radial-gradient`, or `conic-gradient`
|
||||
- WHY: gradient text is decorative rather than meaningful and is one of the top three AI design tells
|
||||
- REWRITE: use a single solid color for text. If you want emphasis, use weight or size, not gradient fill.
|
||||
</absolute_bans>
|
||||
|
||||
DO: Use intentional, purposeful decorative elements that reinforce brand.
|
||||
DO NOT: Use border-left or border-right greater than 1px as a colored accent stripe on cards, list items, callouts, or alerts. See <absolute_bans> above for the strict CSS pattern.
|
||||
DO NOT: Use glassmorphism everywhere (blur effects, glass cards, glow borders used decoratively rather than purposefully).
|
||||
DO NOT: Use sparklines as decoration. Tiny charts that look sophisticated but convey nothing meaningful.
|
||||
DO NOT: Use rounded rectangles with generic drop shadows. Safe, forgettable, could be any AI output.
|
||||
DO NOT: Use modals unless there's truly no better alternative. Modals are lazy.
|
||||
- Vary spacing for rhythm. Same padding everywhere is monotony.
|
||||
- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong.
|
||||
- Don't wrap everything in a container. Most things don't need one.
|
||||
|
||||
### Motion
|
||||
→ *Consult [motion reference](reference/motion-design.md) for timing, easing, and reduced motion.*
|
||||
|
||||
Focus on high-impact moments: one well-orchestrated page load with staggered reveals creates more delight than scattered micro-interactions.
|
||||
- Don't animate CSS layout properties.
|
||||
- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic.
|
||||
|
||||
**DO**: Use motion to convey state changes: entrances, exits, feedback
|
||||
**DO**: Use exponential easing (ease-out-quart/quint/expo) for natural deceleration
|
||||
**DO**: For height animations, use grid-template-rows transitions instead of animating height directly
|
||||
**DON'T**: Animate layout properties (width, height, padding, margin). Use transform and opacity only
|
||||
**DON'T**: Use bounce or elastic easing. They feel dated and tacky; real objects decelerate smoothly
|
||||
### Absolute bans
|
||||
|
||||
### Interaction
|
||||
→ *Consult [interaction reference](reference/interaction-design.md) for forms, focus, and loading patterns.*
|
||||
Match-and-refuse. If you're about to write any of these, rewrite the element with different structure.
|
||||
|
||||
Make interactions feel fast. Use optimistic UI: update immediately, sync later.
|
||||
- **Side-stripe borders.** `border-left` or `border-right` greater than 1px as a colored accent on cards, list items, callouts, or alerts. Never intentional. Rewrite with full borders, background tints, leading numbers/icons, or nothing.
|
||||
- **Gradient text.** `background-clip: text` combined with a gradient background. Decorative, never meaningful. Use a single solid color. Emphasis via weight or size.
|
||||
- **Glassmorphism as default.** Blurs and glass cards used decoratively. Rare and purposeful, or nothing.
|
||||
- **The hero-metric template.** Big number, small label, supporting stats, gradient accent. SaaS cliché.
|
||||
- **Identical card grids.** Same-sized cards with icon + heading + text, repeated endlessly.
|
||||
- **Modal as first thought.** Modals are usually laziness. Exhaust inline / progressive alternatives first.
|
||||
|
||||
**DO**: Use progressive disclosure. Start simple, reveal sophistication through interaction (basic options first, advanced behind expandable sections; hover states that reveal secondary actions)
|
||||
**DO**: Design empty states that teach the interface, not just say "nothing here"
|
||||
**DO**: Make every interactive surface feel intentional and responsive
|
||||
**DON'T**: Repeat the same information (redundant headers, intros that restate the heading)
|
||||
**DON'T**: Make every button primary. Use ghost buttons, text links, secondary styles; hierarchy matters
|
||||
### Copy
|
||||
|
||||
### Responsive
|
||||
→ *Consult [responsive reference](reference/responsive-design.md) for mobile-first, fluid design, and container queries.*
|
||||
- Every word earns its place. No restated headings, no intros that repeat the title.
|
||||
- **No em dashes.** Use commas, colons, semicolons, periods, or parentheses. Also not `--`.
|
||||
|
||||
**DO**: Use container queries (@container) for component-level responsiveness
|
||||
**DO**: Adapt the interface for different contexts, not just shrink it
|
||||
**DON'T**: Hide critical functionality on mobile. Adapt the interface, don't amputate it
|
||||
### The AI slop test
|
||||
|
||||
### UX Writing
|
||||
→ *Consult [ux-writing reference](reference/ux-writing.md) for labels, errors, and empty states.*
|
||||
If someone could look at this interface and say "AI made that" without doubt, it's failed. Cross-register failures are the absolute bans above. Register-specific failures live in each reference.
|
||||
|
||||
**DO**: Make every word earn its place
|
||||
**DON'T**: Repeat information users can already see
|
||||
**Category-reflex check.** If someone could guess the theme and palette from the category name alone — "observability → dark blue", "healthcare → white + teal", "finance → navy + gold", "crypto → neon on black" — it's the training-data reflex. Rework the scene sentence and color strategy until the answer is no longer obvious from the domain.
|
||||
|
||||
---
|
||||
## Commands
|
||||
|
||||
## The AI Slop Test
|
||||
| Command | Category | Description | Reference |
|
||||
|---|---|---|---|
|
||||
| `craft [feature]` | Build | Shape, then build a feature end-to-end | [reference/craft.md](reference/craft.md) |
|
||||
| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |
|
||||
| `teach` | Build | Set up PRODUCT.md and DESIGN.md context | [reference/teach.md](reference/teach.md) |
|
||||
| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |
|
||||
| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |
|
||||
| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |
|
||||
| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) |
|
||||
| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |
|
||||
| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |
|
||||
| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |
|
||||
| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |
|
||||
| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |
|
||||
| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |
|
||||
| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |
|
||||
| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |
|
||||
| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |
|
||||
| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |
|
||||
| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |
|
||||
| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |
|
||||
| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |
|
||||
| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) |
|
||||
| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |
|
||||
| `live` | Iterate | Visual variant mode: pick elements in the browser, generate alternatives | [reference/live.md](reference/live.md) |
|
||||
|
||||
**Critical quality check**: If you showed this interface to someone and said "AI made this," would they believe you immediately? If yes, that's the problem.
|
||||
|
||||
A distinctive interface should make someone ask "how was this made?" not "which AI made this?"
|
||||
|
||||
Review the DON'T guidelines above. They are the fingerprints of AI-generated work.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Principles
|
||||
|
||||
Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices across generations.
|
||||
|
||||
Remember: the model is capable of extraordinary creative work. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Command Router
|
||||
|
||||
This skill supports sub-commands. Parse the first word of the argument string to determine routing.
|
||||
Plus two management commands — `pin <command>` and `unpin <command>`, detailed below.
|
||||
|
||||
### Routing rules
|
||||
|
||||
1. **No argument at all** (user typed just `/impeccable`): Display the command menu below, then ask the user what they'd like to do.
|
||||
2. **First word matches a sub-command**: Route to that command's reference file. Everything after the sub-command name is the target.
|
||||
3. **First word does NOT match any sub-command**: This is a general design invocation. Follow the Design Direction and Implementation Principles above, using the full argument string as context.
|
||||
1. **No argument** — render the table above as the user-facing command menu, grouped by category. Ask what they'd like to do.
|
||||
2. **First word matches a command** — load its reference file and follow its instructions. Everything after the command name is the target.
|
||||
3. **First word doesn't match** — general design invocation. Apply the setup steps, shared design laws, and the loaded register reference, using the full argument as context.
|
||||
|
||||
### Command menu (display when invoked with no argument)
|
||||
|
||||
> **Available commands:**
|
||||
>
|
||||
> **Build & Plan**
|
||||
> `/impeccable craft [feature]` - Shape, then build a feature end-to-end
|
||||
> `/impeccable shape [feature]` - Plan UX/UI before writing code
|
||||
> `/impeccable teach` - Set up PRODUCT.md and DESIGN.md context for this project
|
||||
> `/impeccable document` - Generate DESIGN.md from existing project code
|
||||
> `/impeccable extract [target]` - Pull reusable tokens and components into design system
|
||||
>
|
||||
> **Evaluate**
|
||||
> `/impeccable critique [target]` - UX design review with heuristic scoring
|
||||
> `/impeccable audit [target]` - Technical quality checks (a11y, perf, responsive)
|
||||
>
|
||||
> **Refine**
|
||||
> `/impeccable polish [target]` - Final quality pass before shipping
|
||||
> `/impeccable bolder [target]` - Amplify safe/bland designs
|
||||
> `/impeccable quieter [target]` - Tone down aggressive/overstimulating designs
|
||||
> `/impeccable distill [target]` - Strip to essence, remove complexity
|
||||
> `/impeccable harden [target]` - Production-ready: errors, i18n, edge cases
|
||||
> `/impeccable onboard [target]` - Design first-run flows, empty states, activation
|
||||
>
|
||||
> **Enhance**
|
||||
> `/impeccable animate [target]` - Add purposeful animations and motion
|
||||
> `/impeccable colorize [target]` - Add strategic color to monochromatic UIs
|
||||
> `/impeccable typeset [target]` - Improve typography hierarchy and fonts
|
||||
> `/impeccable layout [target]` - Fix spacing, rhythm, and visual hierarchy
|
||||
> `/impeccable delight [target]` - Add personality and memorable touches
|
||||
> `/impeccable overdrive [target]` - Push past conventional limits
|
||||
>
|
||||
> **Fix**
|
||||
> `/impeccable clarify [target]` - Improve UX copy, labels, and error messages
|
||||
> `/impeccable adapt [target]` - Adapt for different devices and screen sizes
|
||||
> `/impeccable optimize [target]` - Diagnose and fix UI performance
|
||||
>
|
||||
> **Iterate**
|
||||
> `/impeccable live` - Visual variant mode: pick elements in the browser, generate alternatives
|
||||
>
|
||||
> **Manage**
|
||||
> `/impeccable pin <command>` - Create a standalone shortcut (e.g., pin audit creates /audit)
|
||||
> `/impeccable unpin <command>` - Remove a pinned shortcut
|
||||
>
|
||||
> Or use `/impeccable [description]` directly to apply design principles to any task.
|
||||
|
||||
### Sub-command reference table
|
||||
|
||||
When a sub-command is matched, load the linked reference and follow its instructions. The design principles, guidelines, and Context Gathering Protocol from this skill are already loaded. Do NOT re-invoke /impeccable.
|
||||
|
||||
| Command | Reference | Summary |
|
||||
|---------|-----------|---------|
|
||||
| `craft` | [craft](reference/craft.md) | Full shape-then-build flow with visual iteration |
|
||||
| `teach` | [teach](reference/teach.md) | One-time setup: gather design context for the project |
|
||||
| `extract` | [extract](reference/extract.md) | Pull reusable tokens and components into design system |
|
||||
| `document` | [document](reference/document.md) | Generate DESIGN.md from existing project code (visual design system doc) |
|
||||
| `shape` | [shape](reference/shape.md) | Plan UX and UI before writing code (produces a design brief) |
|
||||
| `critique` | [critique](reference/critique.md) | UX design review with heuristic scoring and persona testing |
|
||||
| `audit` | [audit](reference/audit.md) | Technical quality checks across a11y, perf, theming, responsive, anti-patterns |
|
||||
| `polish` | [polish](reference/polish.md) | Final quality pass: alignment, spacing, consistency, micro-details |
|
||||
| `bolder` | [bolder](reference/bolder.md) | Amplify safe or boring designs for more visual impact |
|
||||
| `quieter` | [quieter](reference/quieter.md) | Tone down visually aggressive or overstimulating designs |
|
||||
| `distill` | [distill](reference/distill.md) | Strip designs to their essence, remove unnecessary complexity |
|
||||
| `harden` | [harden](reference/harden.md) | Production-ready: error handling, i18n, text overflow, edge cases |
|
||||
| `onboard` | [onboard](reference/onboard.md) | Design onboarding flows, first-run experiences, and empty states that guide users to value |
|
||||
| `animate` | [animate](reference/animate.md) | Add purposeful animations and micro-interactions |
|
||||
| `colorize` | [colorize](reference/colorize.md) | Add strategic color to monochromatic interfaces |
|
||||
| `typeset` | [typeset](reference/typeset.md) | Improve typography: fonts, hierarchy, sizing, readability |
|
||||
| `layout` | [layout](reference/layout.md) | Improve layout, spacing, and visual rhythm |
|
||||
| `delight` | [delight](reference/delight.md) | Add personality, joy, and memorable touches |
|
||||
| `overdrive` | [overdrive](reference/overdrive.md) | Push interfaces past conventional limits |
|
||||
| `clarify` | [clarify](reference/clarify.md) | Improve UX copy, labels, error messages, and microcopy |
|
||||
| `adapt` | [adapt](reference/adapt.md) | Adapt designs across screen sizes, devices, and platforms |
|
||||
| `optimize` | [optimize](reference/optimize.md) | Diagnose and fix UI performance issues |
|
||||
| `live` | [live](reference/live.md) | Interactive visual variant mode: pick elements, generate alternatives in the browser |
|
||||
|
||||
---
|
||||
Setup (context gathering, register) is already loaded by then; sub-commands don't re-invoke `/impeccable`.
|
||||
|
||||
## Pin / Unpin
|
||||
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project so shortcuts work across every AI tool the user has installed.
|
||||
**Pin** creates a standalone shortcut so `/<command>` invokes `/impeccable <command>` directly. **Unpin** removes it. The script writes to every harness directory present in the project.
|
||||
|
||||
```bash
|
||||
node .pi/skills/impeccable/scripts/pin.mjs <pin|unpin> <command>
|
||||
```
|
||||
|
||||
Valid `<command>` is any sub-command from the router table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Valid `<command>` is any command from the table above. Report the script's result concisely — confirm the new shortcut on success, relay stderr verbatim on error.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user