
Ui Design
- 606 installs
- 74 repo stars
- Updated August 5, 2026
- mblode/agent-skills
ui-design is an agent skill that applies typography, spacing, color, hierarchy, and component conventions so generated interfaces look polished, accessible, and on-brand for developers shipping user-facing screens.
About
ui-design is an agent skill from mblode/agent-skills that gives coding agents explicit guidance on shaping interfaces with consistent typography scales, spacing rhythm, color systems, visual hierarchy, and component choices. Instead of accepting default markup, the skill steers agents toward accessible contrast, logical heading structure, aligned grids, and reusable UI patterns that read as intentional product design rather than generic boilerplate. Developers reach for ui-design when agent-generated dashboards, forms, or marketing pages need polish before handoff to design review or production merge. The skill fits early UI scaffolding and refactor passes where small spacing or type decisions compound into noticeably better screens. ui-design complements framework-specific frontend skills by focusing on visual design decisions—what to render and how it should look—rather than routing, data fetching, or test setup.
- Layout hierarchy and spacing systems
- Typography and color discipline
- Component-level UX patterns
- Accessibility-minded defaults
- Brand-consistent visual language
Ui Design by the numbers
- 606 all-time installs (skills.sh)
- +47 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #533 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mblode/agent-skills --skill ui-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 606 |
|---|---|
| repo stars | ★ 74 |
| Last updated | August 5, 2026 |
| Repository | mblode/agent-skills ↗ |
How do you make agent-generated UI look polished?
Shape interfaces with consistent typography, spacing, color, hierarchy, and component choices so agent-generated screens feel polished, accessible, and on-brand.
Who is it for?
Frontend developers using coding agents to scaffold dashboards, landing pages, or app shells that must look intentional rather than default HTML styling.
Skip if: Developers needing motion choreography, design-system token codegen, or Figma-to-code pipelines where dedicated animation or tooling skills are a better fit.
When should I use this skill?
The user asks for polished UI, consistent spacing and typography, accessible color contrast, visual hierarchy, or on-brand component choices in agent-generated screens.
What you get
On-brand UI layouts with consistent type scale, spacing tokens, color hierarchy, and accessible component choices ready for frontend review.
- polished UI markup
- accessible color and type choices
- consistent spacing layout
Files
UI Design
Design and build UI: pick the visual direction, then implement it in code following the ui.sh design guideline system.
- IS: choosing visual direction (palettes, type scales, tokens, layout systems, CRO strategy, brand boards) and building or refining UI in code: one definitive design, multiple variants compared in the browser, a semantic markup scaffold from a UI image, retrofitting dark mode and responsive behavior, or extracting components and canonicalizing Tailwind classes.
- IS NOT: auditing existing UI quality (use
ui-audit); deep typography audits (usetypography-audit); motion design (useui-animation); landing-page copy (usecopywriting).
Modes
Pick exactly one mode from the user's wording, then load only that mode's files:
| Mode | Dispatch when the user asks for | Load |
|---|---|---|
| Direction | visual direction, palettes, fonts, tokens, "make this look premium", "pick a style", conversion strategy, a brand kit; the deliverable is a spec, not code | the Direction section below |
| Build (default) | one design in code: "build a landing page", "create a dashboard", "add a pricing section" | design-guidelines.md plus every applicable rule file |
| Options | several directions, options, variants, or alternatives to compare in the browser: "show me 3 hero layouts", "a few ideas for this section" | ideas.md, plus the guidelines for each variant |
| Scaffold | semantic, unstyled markup from a screenshot, Figma export, mockup, or wireframe: "turn this screenshot into markup" | markup-from-image.md only; the scaffold stays unstyled |
| Dark mode | retrofitting dark mode onto existing UI, or a dark variant of an image: "add dark mode", "make a dark version of this image" | add-dark-mode.md; for raster images also dark-mode-image.md, which requires the imagegen skill (Codex) |
| Responsive | adapting existing desktop-oriented UI across breakpoints: "make this responsive", "fix this on mobile" | make-responsive.md |
| Componentize | extracting reusable components or cleaning up Tailwind class lists: "componentize this page", "clean up the Tailwind" | componentize.md; for class cleanup also canonicalize-tailwind.md |
Direction and Build chain naturally: when the user wants a new surface and no direction exists, run Direction first (or propose one inline for small surfaces), then Build. When a direction already exists in the project, go straight to Build.
Direction mode
The output is a decision set, not markup: a one-sentence visual thesis (mood, material, energy), palette as CSS variables, type pairing and scale, spacing grid, radius and depth strategy, the layout pattern for the primary surface, and for conversion pages the section sequence, CTA plan, and proof placement. Close with the track's litmus checks as the exit gate, then hand off to Build mode.
Pick a track
| Surface | Track | Optimises for |
|---|---|---|
| Dashboards, admin panels, data tables, settings pages, internal and dev tools | direction/product-ui.md | Information density, calm chrome, scanability, utility copy |
| Landing pages, brand sites, promotional pages, portfolios, pricing pages | direction/marketing-ui.md | Visual impact, storytelling, one-CTA conversion flow |
Tie-breakers: a marketing site for a SaaS product is the marketing track; the app behind the login is the product track; design them separately. If the page's job is to convert a stranger, it's marketing. If its job is to let an operator work, it's product.
Shared foundations (load with either track)
- direction/aesthetic-direction.md: AI-slop signals, restraint philosophy, reference products, polish details. Read after picking a track, before proposing a direction.
- direction/design-in-code.md: low-fi ASCII wireframing and the copy-what-works workflow. Read before building any new surface from scratch.
Marketing references (conversion pages only)
Load when the marketing track involves a landing page, signup flow, or any page with a conversion goal. Skip for pure brand/portfolio work and for all product UI.
| File | Read when |
|---|---|
| direction/cro.md | Choosing persuasion tactics, social proof, or page length, or writing a CRO plan: Cialdini's principles, proof credibility hierarchy, conversion benchmarks, Voice of Customer mining |
| direction/testing.md | Optimising an existing page or planning experiments: test prioritisation, A/B vs multivariate, significance rules, heatmap insights, CTA statistics |
| direction/modern.md | Tuning page speed, mobile-first conversion, personalisation, accessible copy, or microcopy |
Brand kit
For "create a brand kit", "generate a visual identity", or a brand direction board from a product idea, load direction/brand-kit.md. Rendering the final board needs the imagegen skill (Codex, gpt-image-2); in agents without it, deliver the direction as text plus the generated image prompt for the user to render.
Build mode
1. Inspect the user's request, target files, existing design conventions, and available components. 2. Load design-guidelines.md plus every applicable rule file it indexes (the guidelines/ folder). 3. Implement the UI using the project's existing framework, component patterns, assets, and Tailwind conventions. 4. Check the result across responsive breakpoints and interaction states.
Rules:
- Treat the guideline files in this skill as the source of truth for new UI design work.
- Err on the side of loading too many applicable guideline files rather than too few.
- Preserve user constraints unless a guideline explicitly requires asking about a design conflict.
Options mode follows ideas.md; Scaffold mode follows markup-from-image.md; Dark mode follows add-dark-mode.md; Responsive follows make-responsive.md; Componentize follows componentize.md.
Quality Bar
Calibrate taste against gold-standard product and UI design. When making judgment calls the guidelines leave open, ask what these teams would ship, and channel the craft, not the trade dress:
- Linear: restrained palette, information density without clutter, keyboard-first product UI
- Raycast: dark-first polish, crisp iconography, fast-feeling interactions
- Things 3: calm, spacious layouts, friendly without being cute
- OpenAI: typography-led, editorial minimalism in marketing surfaces
- ElevenLabs: modern AI-product clarity, confident use of whitespace
- Mintlify: docs-grade legibility, tidy navigation, quiet color
- Family (crypto wallet): delightful detail and motion in small moments
- Zed Editor: minimal chrome, performance-feel, developer-tool austerity
A design that would look out of place beside these products is not done.
Verify
- Check desktop and mobile layouts.
- Confirm every applicable guideline or track file was loaded and followed.
Gotchas
- Running the marketing track on a product surface puts hero sections and campaign copy on dashboards, so operators can't find status or actions. product-ui.md's "Utility copy" section exists for exactly this failure.
- Skipping aesthetic-direction.md in Direction mode is how Inter-on-white-with-purple-gradients ships; it is the anti-slop calibration layer for both tracks.
- Loading the CRO references for a brand or portfolio page biases the design toward conversion furniture (badge strips, sticky CTAs, urgency banners) the brief never asked for.
- Quoting the references' conversion stats as promises ("this will lift conversions 34%") misrepresents them. They are directional priors for prioritising tests.
- Skipping
colors.mdin Build mode produces the stock Tailwind look: indigo accents andgray-*neutrals, both banned as defaults.
Related Skills
ui-audit: page-level quality and accessibility audit of the built resulttypography-audit: rule-level audit of existing typography; route "fix the fonts" on shipped CSS thereui-animation: motion timing, easing, and reviewcopywriting: landing-page copy, message match, persuasion frameworksoptimise-seo: meta descriptions and page titles
Add Dark Mode
Use this when the user wants to add dark mode support to an existing UI.
Load First
- Load guidelines/dark-mode.md for the dark-mode design rules.
- For raster image work (auditing flagged images or a standalone "dark version of this image" request), load dark-mode-image.md.
Workflow
1. Inspect the existing UI and project Tailwind conventions. 2. Convert markup to include appropriate dark-mode classes. 3. Audit rasterized images for dark-mode variants. 4. For each rasterized image that needs a dark-mode variant, follow dark-mode-image.md, which requires the imagegen skill before creating or editing image assets. 5. Save generated dark-mode images alongside the originals and wire them into the dark-mode UI.
Guardrails
- Do not generate, edit, or replace raster image assets without first loading dark-mode-image.md and the
imagegenskill it requires. - Require the dark-mode-image +
imagegenworkflow even when the image change seems simple, decorative, or incidental.
Verify
- Check light and dark modes for contrast, missing variants, and images that still assume a light background.
Canonicalize Tailwind
Use this when the user wants to clean up, canonicalize, or normalize Tailwind class lists.
Workflow
1. Identify Tailwind class strings in the requested files or components. 2. Canonicalize class strings with npx @tailwindcss/cli canonicalize. 3. Apply changed class strings back to the source. 4. Run the project's formatter or relevant checks when available.
Commands
- Use
npx @tailwindcss/cli canonicalizeto clean up Tailwind class lists: collapses shorthands (mt-2 mr-2 mb-2 ml-2→m-2), resolves overrides (py-3 p-1 px-3→p-3), canonicalizes arbitrary values to named utilities, and sorts classes; pass--css path/to/input.cssif the project uses a custom CSS entry file
Single class string:
npx @tailwindcss/cli canonicalize "mt-2 mr-2 mb-2 ml-2"
# m-2Multiple class strings as positional args (each returned on its own line):
npx @tailwindcss/cli canonicalize "py-3 p-1 px-3" "mt-2 mr-2 mb-2 ml-2"
# p-3
# m-2Pipe class strings via stdin (one per line):
echo "py-3 p-1 px-3\nmt-2 mr-2 mb-2 ml-2" | npx @tailwindcss/cli canonicalize
# p-3
# m-2Use --format json or --format jsonl for structured output with input/output/changed fields:
npx @tailwindcss/cli canonicalize --format json "py-3 p-1 px-3"
# [{ "input": "py-3 p-1 px-3", "output": "p-3", "changed": true }]Use --stream to process stdin line-by-line without buffering:
npx @tailwindcss/cli canonicalize --streamVerify
- Confirm class strings still express the same visual intent after canonicalization.
Componentize
Use this when the user wants to componentize, extract, or organize UI code into reusable components, or clean up Tailwind class lists.
Load First
- For Tailwind class cleanup (standalone or finishing pass), load canonicalize-tailwind.md for the
npx @tailwindcss/cli canonicalizeworkflow and command reference. - Component extraction itself needs no companion files.
Workflow
1. Inspect existing project component patterns before creating new components. 2. Identify repeated patterns, logical sections, and self-contained UI blocks. 3. Extract components with call-site spacing and configurable class merging. 4. Reuse or extend existing project components where available. 5. Re-scan extracted components for remaining duplication. 6. Finish with a Tailwind canonicalize pass over the touched class lists (canonicalize-tailwind.md).
Rules
- Break designs into small, focused components instead of rendering everything in a single large component: extract repeated patterns, logical sections, and self-contained UI blocks into their own components
- Never bake margins into components: apply margins at the call site instead; every component must accept a
classattribute and merge it with the classes on the component's top-level element - Use
clsxor similar to merge classes together in client-side components - Always extract form controls into reusable components organized by HTML element: one
Inputcomponent for all<input>types (text, email, password, etc.), oneSelectfor<select>, oneTextareafor<textarea>; never create type-specific components likeEmailInputorPasswordInput; check the project for existing ones before creating new ones - When two or more elements share the same structure and styling but differ only in props like labels, placeholders, or types: extract them into a single reusable component parameterized by those differences
- After extracting components, scan them for duplicated patterns and extract shared elements into reusable components: e.g. repeated section container/max-width/padding wrappers, repeated heading group structures (eyebrow + heading + subheading), repeated card shells, repeated button styles
- Always use existing project components when they are available: reuse or extend them instead of creating new ones; buttons and form elements are especially common candidates
Verify
- Confirm extracted components preserve the original UI and behavior.
Dark Mode Image
Use this when the user wants to adapt a standalone source image into a dark-mode-suitable version.
Model requirement: the image-generation steps below need the imagegen skill (Codex, gpt-image-2). In agents without it (such as Claude Code), identify the images needing dark variants and list them with the target background colors, then ask the user to generate them or source dark versions manually. Never substitute CSS filter workarounds.Load First
- Before image generation or editing, load and follow the
imagegenskill.
Workflow
1. Load imagegen. 2. Inspect the source image and the dark-mode UI context. 3. Generate or edit a dark-mode version with the same dimensions as the original. 4. Save the dark-mode image with a -dark suffix alongside the original. 5. Return the saved project path for the caller to wire into the UI.
Rules
- Before doing any image generation or editing, you MUST load and follow the
imagegenskill - The
imagegenskill invocation is not optional: do not skip it, do not replace it with an ad hoc image-generation workflow, and do not call image tooling directly without first applyingimagegen - Let
imagegenchoose and run the correct image workflow; for normal dark-mode image variants, that will usually mean its default built-inimage_gentool mode - If the source image is a local file, follow
imagegen's local-image guidance before editing so the image is visible in the conversation context - Follow
imagegen's save-path policy: move or copy project-bound generated outputs into the workspace, and never leave a project-referenced dark-mode asset only under$CODEX_HOME/* - When generating a dark-mode image, choose a background color that feels like an appropriate inversion of the original background color: black or dark gray for white, dark gray for off-white, or the specific dark color provided by the user; if the original image's background matched the site background, match the dark-mode site background instead
- Preserve the same contrast characteristics as the original image; light sections should become darker while relative separation and readability stay intact
- Preserve blurs and softness; never sharpen anything that was blurry in the original image
- Preserve the foreground color palette hues, adjusting saturation and lightness only as needed so the image presents correctly on a dark background
- Preserve the original vibe as much as possible: bright and intense images should stay bright and intense, while subtle and muted images should stay subtle and muted
- Pay attention to areas that fade out and preserve those fades in the dark-mode version
- The generated dark-mode image must be exactly the same dimensions as the original image
- Save dark-mode images with a
-darksuffix, for examplebg.jpgandbg-dark.jpg
Verify
- Confirm the generated image dimensions match the original exactly.
- Confirm the dark-mode image preserves the original composition, softness, fades, and foreground palette.
UI Design Guidelines
Use this when designing or building new UI with the top-level design skill, or when a workflow tells you to load design guidance before editing UI code.
Load Contract
- Before writing UI code, scan the rule-file index below and load every rule file that could apply.
- Err on the side of loading too many rule files rather than too few.
- Treat rules as applicable even when they are indirect: heading group rules apply to hero sections; landing page rules apply to individual page sections; surface rules apply to dashboard cards and list items.
- Load reference modules only when the user's request needs that reference material.
General Design Principles
- Every layout must adapt from mobile to desktop: use responsive breakpoint classes to adjust the design at different screen sizes; see Responsive Design for detailed rules
Rule Files
Follow these rules when designing or building UI. Each rule file covers a specific topic:
- Avatars: profile photos, user thumbnails, and people images used in testimonials, team sections, comments, and anywhere a person's face appears
- Badges: badges, tags, pills, status indicators, labels, and chips with or without icons
- Border Radius: rounding corners on cards, containers, buttons, images, screenshots, and nested elements with concentric radii
- Buttons: primary and secondary buttons, CTAs, icon buttons, destructive/danger actions, and touch targets
- Colors: brand colors, accent colors, color palette selection, and default color choices
- Copywriting: punctuation, periods, headings, taglines, subtitles, descriptions, and list items
- Custom Fonts: loading custom fonts via
<link>tags or@import url(), registering fonts in@themewith--font-*, font-feature-settings, and font-variation-settings - Dark Mode: dark theme styling, contrast ratios, colored panels, card backgrounds, shadow removal, decorative elements, heading colors, dark-mode image handoff, and inline/external SVG dark-mode handling
- Description Lists:
<dl>,<dt>, and<dd>styling, term/detail contrast and font weight hierarchy - Dashboards: dashboard layouts, stat grids, KPI cards, metric cards, admin panels, analytics views, and any section displaying key statistics, charts, or summary data
- Feature Lists: feature grids, feature sections, benefit lists, and any section that lists multiple features with titles and descriptions
- Flexbox Layout: flex containers, flex children,
min-w-0shrinking behavior,shrink-0on icons/images/SVGs, fluid vs fixed layouts, sidebar + content patterns, and any layout usingflex-1or flexible sizing - Footers: page footers, footer logos, footer links, social media icons, and site-wide bottom navigation
- Form Controls: inputs, selects, checkboxes, radio buttons, login forms, sign-up forms, checkout forms, search bars, newsletter sign-up fields, and input + button combos
- General: general markup rules (class placement on block vs inline elements, redundant display classes,
role="list") and Tailwind CSS authoring rules (utility preferences, spacing conventions, arbitrary value syntax, variant patterns, deprecated utilities) that apply across all components - Headers: site headers, navigation bars, navbars, top bars, logos, mobile menus, and hamburger menus
- Heading Groups: the headline, subheadline, and optional eyebrow at the top of marketing and landing page sections (hero, features, team, pricing, CTA, etc.); does not apply to blog posts, articles, or editorial content
- Icons: SVG icons, icon sizing, icon alignment with text, Heroicons, filled vs stroked icons, and inline list icons like checkmarks
- Images: photos, thumbnails, screenshots, app UI mockups, and image borders/outlines
- Interactivity: hover states, transitions, animations, and interactive behavior on clickable vs non-clickable elements
- Landing Pages: full page consistency rules for buttons, fonts, containers, border radius, column gaps, layout alignment, and responsive constraints across all sections on a page
- Login Pages: login, sign-in, sign-up, and authentication page backgrounds and layout rules
- Logo Clouds: logo grids, client logo rows, partner logos, trust bars, and any section displaying a collection of brand logos
- Navigation: sidebar nav, header nav, mobile nav menus, tabs, tab bars, vertical menus, active/selected states, and current page indicators in any navigation pattern
- Pagination: page number links, previous/next buttons, and paged navigation controls
- Placeholder Content: dummy logos, placeholder avatars, app screenshots, wallpapers, and the assets API for generating realistic placeholder content
- Prose Content: styling raw HTML from markdown, CMS, or database content where Tailwind classes can't be applied to individual elements; replaces the
@tailwindcss/typographyplugin with a custom.proseclass - Pricing Cards: pricing tiers, pricing tables, plan cards, emphasized/popular plan styling, and button alignment across pricing columns
- Responsive Design: responsive breakpoints, container queries,
@containerplacement, and mobile-to-desktop layout adaptation - SVG: inline SVG elements,
xmlnsattributes, SVG color styling (fill,stroke,currentColor), and SVG markup conventions used anywhere in HTML/JSX - Section Layout: left-aligned vs centered section layouts, content width constraints, and aligning containers across stacked page sections
- Shadows: box shadows on cards, modals, popovers, dropdowns, and elevated elements, including border pairing rules
- Surfaces: cards, wells, borders, dividers, and white space as surface treatments; when to use cards vs subtle dividers vs recessed backgrounds vs no separation at all; applies to stat grids, dashboard metrics, list items, sidebars, and any content grouping decision
- Tables: data tables, comparison tables, table headings, row dividers, and table containers
- Team Sections: team grids, team member cards, staff listings, about-us sections, and people galleries with photos and bios
- Testimonials: customer quotes, reviews, social proof sections, testimonial cards, hanging punctuation, and attribution layout
- Typography: font weights, line heights, text sizes, heading styles, max-width constraints, text-pretty/text-balance, tracking, and eyebrow text
Reference Modules
Load these only when the request needs the reference:
- Assets API: placeholder asset URLs, query parameters, and examples for marks, avatars, logos, screenshots, and wallpapers
- Font Recommendations: optional font suggestions for when the user asks for help choosing a font or wants to try different fonts across design variations; includes sourcing notes, feature settings, and tips for each font
Design Conflicts
When a rule says ⚠️ ask-user, the user's input conflicts with a design guideline. Do not silently override the user or silently follow their request. Instead:
1. Use the AskUserQuestion tool to flag the conflict 2. Explain what the guideline recommends and why the input doesn't fit 3. Offer a concrete alternative (e.g. a rewritten version of their copy, a different layout) 4. Wait for the user to choose before proceeding
Never skip this, even if it feels minor. The user should always be aware when their input bumps up against a design rule.
Aesthetic Direction
Shared calibration layer for both tracks. Goal: make the UI look human-designed, not AI-default.
AI slop signals
- Default fonts (Inter/Roboto/Arial/system).
- Purple-on-white gradients and generic cards.
- Predictable layouts and repeated component patterns.
- Excess glow and unnecessary complexity.
Philosophy
- Delete aggressively; clarity over decoration.
- Do not compete for attention you have not earned.
- Structure should be felt, not seen.
- Prune extra icons, controls, and separators before styling what remains.
- Restraint plus hierarchy beats noise.
Study references
- Linear, Stripe, Notion, Raycast, ElevenLabs, Zed.
Upgrade choices
- Icon sets: Phosphor, Heroicons, Tabler.
- Typography sources: Typewolf, Fonts In Use, commercial foundries.
- Animation study: animations.dev, devouringdetails.com.
Polish details
- Match box-shadows to references.
- Dark-mode aware SVG favicon.
- Intentional hover/active states and loading/error/empty states.
Reject these failures
- Generic SaaS card grid as the first impression.
- Beautiful image with weak brand presence.
- Strong headline with no clear action.
- Busy imagery behind text.
- Sections that repeat the same mood statement.
- Carousel with no narrative purpose.
- App UI made of stacked cards instead of layout.
Brand Kit Prompt
Contents
- Purpose
- Source Handling
- Attached Images
- Workflow
- Canonical Board Spec
- Page Mockups
- Design-System Rail
- Creative Direction
- Final Prompt Structure
- Rules
Purpose
Generate one complete, production-ready image prompt for a fixed-structure 4K marketing-site brand case-study image. Output prompt text only; do not generate images.
This skill prioritizes distinctive frontend art direction, production-grade public-facing marketing website mockups, generous whitespace, and consistent side-by-side comparison. Even when the concept is a web app, desktop app, mobile app, SaaS product, or other software interface, the board should show the public marketing site for that product. The final image must feel like two real, spacious website surfaces plus a concise typography/color rail, not a cramped moodboard, component inventory, app UI board, or traditional brand-system sheet.
Source Handling
- Use only the user's concept, brief, notes, constraints, references, attached images, audience, tone, required pages, and avoid-list items.
- If the input is thin but usable, make careful creative inferences.
- Ask a question only when there is no usable brand, product, company, idea, or concept.
- Preserve user-supplied vocabulary, constraints, page requests, examples, references, attached-image inspiration, and avoid-list items.
- Output only the final prompt, with no preamble, rationale, commentary, follow-up, or setup text.
Attached Images
If the user attaches images, inspect them and translate their visual qualities into prompt language. Use them as design inspiration only:
- Extract aesthetic direction, composition style, visual density, color atmosphere, type mood, spacing feel, texture, lighting, layout rhythm, and interaction/presentation patterns.
- Do not copy or recreate attached-image content, logos, wordmarks, brand marks, icons, mascots, characters, product names, readable text, photography subjects, proprietary UI, exact layouts, or distinctive artwork.
- Do not treat attached images as mandatory content for the generated brand kit unless the user explicitly says the image is their own brand asset and asks to use it.
- If attached images conflict with the written concept, preserve the written concept and use the images only for visual direction.
- In the final prompt, include a short "Reference Image Use" note when images are attached: describe the style inspiration to borrow and explicitly state that attached images are style references only, not content or logo sources.
Workflow
1. Infer the purpose, audience, positioning, product context, and brand personality. 2. Choose one clear, memorable aesthetic direction that fits the concept. 3. Choose the two public marketing-site page examples:
- Page mockup 1 defaults to the homepage.
- Page mockup 2 defaults to a concept-appropriate supporting page with a different content pattern from the homepage.
- If the user asks for specific pages, use those instead.
- If the concept is an app or software product, choose pages that can naturally show product screenshots inside the marketing site.
4. If images are attached, summarize their reusable visual qualities using Attached Images. 5. Assemble one internally consistent image-generation prompt using the structure in Final Prompt Structure.
Canonical Board Spec
The generated prompt must request this exact image structure unless the user explicitly asks for a different structure:
- Canvas: one single 3840 x 2160 px, 16:9 landscape, high-quality 4K image.
- Layout: three full-height vertical columns with clean gutters.
- Widths: page mockup 1 = 40%, page mockup 2 = 40%, design-system rail = 20%; equivalent ratio 2 : 2 : 1.
- Left column: page mockup 1.
- Middle column: page mockup 2.
- Right column: design-system details rail.
- The two page mockups must dominate and read as large, inspectable website pages.
- The rail must be quieter than the mockups but legible at full 4K size.
- Keep the page mockups spacious and breathable, with clear margins, open section rhythm, and enough negative space that the design does not feel busy.
- Do not add extra panels, page thumbnails, floating device mockups, moodboard imagery, standalone logo explorations, component inventories, callout overlays, or decorative filler.
- Do not generate a separate design-system board, a two-board split, multiple images, unreadably tiny UI fragments, or a dashboard/workspace/app UI board unless the user explicitly requests an interface-only board instead of a marketing site.
Page Mockups
The two mockups should be substantial public-facing marketing website pages with generous spacing, strong breathing room, and restrained content density. Treat an app concept as a product that needs a marketing site, not as permission to make the board an app UI study. Product/app UI may appear only as supporting content embedded inside a page mockup.
If the concept is a web app, desktop app, mobile app, SaaS product, marketplace, creator tool, productivity tool, or other software product, include at least one realistic screenshot or framed view of the app inside the marketing pages. These screenshots should help explain the product and provide brand inspiration, while the surrounding page remains the main subject.
Page mockup 1:
- Default to the homepage.
- Make it the clearest expression of the marketing promise.
- Include primary navigation with an appropriate logo, wordmark, or brand mark; a strong hero system; primary CTA; and enough below-the-fold content to show section pacing.
- For app/software concepts, include a prominent but embedded product screenshot, device frame, desktop/webapp frame, mobile screen, or interface crop.
Page mockup 2:
- Default to a supporting page that reveals a different side of the system.
- Prefer pages that add new content patterns: pricing, booking, signup, product/service detail, collection/category, editorial/content, comparison, case study, lead-capture, checkout, account creation, search/results, commerce, structured data, forms, tables, cards, proof blocks, dense typography, or screenshot-led feature explanation.
- Reuse the same logo, wordmark, or mark from the homepage in realistic page chrome when appropriate.
For each page, define:
- Page type and purpose.
- Layout structure, hierarchy, key components, and copy tone.
- Logo/wordmark/mark placement when a real site would include one.
- Product screenshot placement when the concept is an app/software product.
- Visible design behavior: grid/composition, generous spacing feel, low-to-moderate density, type scale, navigation, CTAs, forms, cards, pricing tables, proof blocks, product tiles, filters, commerce modules, editorial modules, or other relevant components.
- Whitespace strategy: wide margins, clear gutters, open hero composition, fewer simultaneous content blocks, and section pacing that feels calm rather than crowded.
- Distinctive frontend composition: asymmetry, overlap, strict grid, dense utility, editorial pacing, diagonal flow, immersive media, tactile states, active/hover states, scroll moments, or another concept-appropriate idea.
Design-System Rail
The right rail documents only values that are hard to recover from the mockups without OCR.
Include:
- Typography: display/headline, body, and UI/label/numeric/mono typeface names or typeface directions; include brief hierarchy, casing, weight, tracking, or pairing notes only when useful.
- Color: dominant/core colors separated from supporting/accent colors; approximate hex-style values; short role labels such as background, foreground, primary, surface, border, signal, accent, semantic, or category.
- Color hierarchy: dominant/load-bearing colors shown as larger swatches or bars; supporting/accent/signal colors shown as smaller grouped chips.
- Rail text optimized for full-4K readability: short labels, large enough type, clear spacing, no dense captions.
Do not include in the rail:
- Logo, wordmark, mark construction, lockups, logo notes, logo variations, or logo-spec content.
- Spacing scales, border radius, grid specs, motion notes, component inventories, component states, icon notes, elevation/shadow specs, or arbitrary brand copy.
- Slogans, positioning paragraphs, mood words, or any text that does not directly document typography or color values used in the page mockups.
Creative Direction
Choose a bold but concept-appropriate aesthetic direction, such as brutally minimal, maximalist, retro-futuristic, organic, luxury, playful, editorial, brutalist, art deco, soft, industrial, utilitarian, or another direction inferred from the brief.
Define:
- Purpose: what visitors should understand, trust, and do.
- Marketing focus: how the site introduces, explains, proves, and sells the brand.
- Tone: 3-5 strong adjectives, not a neutral default.
- Differentiation: the one visual, typographic, interaction, material, motif, or page-structure idea someone would remember.
- Constraints: production-grade, functional, accessible, plausible for a real frontend.
- Intensity: maximalist systems may be rich; refined systems should rely on restraint, proportion, and precision.
- Spacing: preserve generous whitespace even for expressive or maximalist concepts; use scale, contrast, and composition for impact instead of cramming in more modules.
Avoid:
- Defaulting to Inter, Roboto, Arial, system fonts, or overused neutral typography unless requested.
- Cliche purple-blue gradients on white, generic glassmorphism, bland SaaS dashboards, default rounded cards, cookie-cutter component layouts, unrelated gradient blobs, or decorative effects unrelated to the brand.
- Cramped layouts, busy collages, overfilled sections, dense rows of tiny cards, excessive annotations, or too many simultaneous UI fragments.
- Reusing the same trendy typefaces or color systems across concepts.
Final Prompt Structure
Assemble the final answer as the image prompt itself, using these sections:
1. Brand Positioning
- Target audience, market positioning, 3-5 tone adjectives, brand personality, relevant comparables/references, and avoid list.
2. Aesthetic Concept
- Core frontend art direction in one vivid phrase, why it fits, memorable design idea, intensity/restraint, and what makes it specific to this brand.
3. Reference Image Use
- Include only when images are attached. Summarize reusable visual qualities and state that references are for style inspiration only, not for copied content, logos, text, exact layouts, or proprietary UI.
4. Board Layout
- Restate the canonical 3840 x 2160, 40% / 40% / 20%, three-column layout and the prohibition on extra panels or alternate layouts.
5. Page Mockups
- Define the homepage and supporting page using the
Page Mockupsrequirements, or use the user's requested pages.
6. Design-System Rail
- Define only the typography block and hierarchical color block using the
Design-System Railrequirements.
7. Visual Style Constraints
- State what to avoid, what to emphasize, anti-generic constraints, generous whitespace requirements, and that the fixed layout still applies even when the aesthetic is expressive.
8. Rendering / Style Hints
- End with one concise rendering line: one 3840 x 2160 px 16:9 high-quality 4K presentation image; fixed 40% page mockup 1 / 40% page mockup 2 / 20% typography-and-color rail; crisp readable UI and rail text; production-grade marketing website mockups; bold concept-specific art direction; generous margins, open section rhythm, and calm whitespace; realistic polished visual design.
Rules
- Be specific and concrete; maintain internal consistency across all sections.
- Make the aesthetic direction memorable and concept-specific.
- Keep the website mockups spacious; do not trade readability and whitespace for extra content.
- Use specific typeface names or precise typeface directions and approximate color values.
- Specify which colors are dominant/load-bearing and which are supporting/rare accents, and require that hierarchy to be visible.
- Keep all visible rail text short enough for image generation to render legibly.
- Do not hardcode examples from one concept into another concept.
- Do not ask for a separate design-system board or two images.
- Do not explain your reasoning.
Brand Kit
Model requirement: rendering the final board needs the imagegen skill (Codex, gpt-image-2). In agents without it (such as Claude Code), run the workflow through the prompt-generation step, then deliver the direction as text (typography, color palette, mockup descriptions) and the generated image prompt so the user can render the board themselves.Thin wrapper: Brand Kit Prompt is the source of truth for the board structure, attached-image rules, creative direction, and prompt format. If anything here conflicts with it, follow the prompt file.
Workflow
1. Treat the user's concept, brief, constraints, references, audience, tone, avoid-list items, and attached images as the source input. 2. Read Brand Kit Prompt and generate one production-ready mockup-first image prompt from the source input. Treat the prompt as intermediate working content; do not present it as the final answer unless asked. 3. Render the prompt through the imagegen skill, passing attached images as style references when supported. Generate exactly one 3840 x 2160 px 16:9 board. 4. Return the rendered image with minimal commentary.
Wrapper rules
- Make careful creative inferences from a thin concept; ask a follow-up only when there is no usable brand, product, or idea information at all.
- Do not stop after producing the intermediate prompt, and do not summarize it so heavily that brand details are lost.
- If the prompt-generation step produces multiple boards, alternatives, or any output shape other than the fixed structure, normalize it to match the prompt file before rendering.
- If the user asks for the image plus the prompt, render the image first, then include the prompt text.
Conversion Fundamentals
Reference for landing page conversion strategy. Load when building or auditing marketing pages.
Table of contents
- Persuasion principles
- Social proof patterns
- Conversion benchmarks
- Voice of Customer research
- Page length decision
---
Persuasion principles
Cialdini's seven principles applied to landing pages. Each principle is a tool, not a trick: misuse destroys trust faster than it builds conversion.
| Principle | Landing page application | Misuse to avoid |
|---|---|---|
| Reciprocity | Offer something free first (a tool, a calculator, a guide) before asking for commitment | Gating basic information behind a form; the "gift" must feel genuinely useful |
| Commitment | Start with a micro-yes (quiz, configurator, email-only form) before the full ask | Bait-and-switch: small ask that reveals a hidden large commitment |
| Social proof | Reviews, badges, user counts, testimonials near the CTA (see below) | Fake reviews or obviously fabricated numbers; readers smell it instantly |
| Authority | Certifications, press logos, expert endorsements, "as seen in" strips | Citing authority without specifics: "trusted by thousands" proves nothing |
| Liking | Brand voice, customer-as-hero framing, relatable imagery | Over-familiarity or forced warmth that doesn't match the product |
| Scarcity | Limited-time offers, remaining seats, closing deadlines | Fake countdown timers that reset on refresh; permanent "last chance" banners |
| Unity | In-group language ("fellow founders"), shared identity framing | Exclusionary language that alienates adjacent audiences |
Urgency (a subset of scarcity) increases conversion by up to 332% when real, and destroys credibility when fabricated.
---
Social proof patterns
Landing pages with social proof convert 34% better than those without. But not all proof is equal.
Credibility hierarchy
From highest to lowest trust:
1. Third-party review badges: G2, Capterra, Trustpilot, Product Hunt. Independently verified. Highest credibility for B2B SaaS. 2. Specific-outcome testimonials: "Cut our reporting from 4 hours to 20 minutes." Named person, real photo, company. 3. X/Twitter testimonials: Publicly verifiable. Underused but high-trust because anyone can check. 4. Logo walls: Show that recognisable companies use the product. Less persuasive alone. 5. User counts: "Join 50,000+ teams." Effective at scale, meaningless below ~1,000. 6. Vague praise: "Great product, love it!" tells nothing. Almost never moves the needle.
Placement rules
- Near the CTA: proof should appear within one scroll of every conversion point
- Above the fold: 3-5 logos or one credibility stat; don't delay trust signals
- Adjacent to pricing: testimonials matched to plan type reduce choice anxiety
- After objection sections: proof answers "but does it actually work?"
The specificity test
If a competitor could use the same testimonial unchanged, it's too generic. "Great tool" fails. "Reduced our deploy time from 45 minutes to 3" passes.
---
Conversion benchmarks
Median conversion rates by industry and channel (directional industry data):
| Segment | Median | Top quartile |
|---|---|---|
| All industries | 6.6-8.1% | 10%+ |
| Financial services | 8.4% | 12%+ |
| Legal services | 7.4% | 11%+ |
| eCommerce | 4.3% | 8%+ |
| Healthcare | 3.0-4.2% | 8-10% |
| B2B SaaS (cold) | 1-3% | 5%+ |
| Traffic source | Average conversion |
|---|---|
| Email campaigns | 19.3% |
| Webinar pages | 22.3% |
| Organic search | 4-6% |
| Paid search | ~1.2% |
| Paid social | 2-4% |
Use these as directional benchmarks, not targets. A 3% rate for a $50K ACV product is a different business than 3% for a free trial.
CRO tools report average ROI of 223%. Median rates have been rising, driven largely by AI-assisted A/B testing, which a majority of mid-market brands now use.
---
Voice of Customer research
The fastest way to write landing page copy that resonates: steal the reader's exact words.
The highlight-and-steal method
1. Read 50+ reviews (G2, Trustpilot, app stores, Reddit threads, support tickets) 2. Highlight recurring phrases, especially emotional language about pain and outcomes 3. Use them verbatim in headlines, pain sections, and CTAs
Where to mine
| Source | What you get |
|---|---|
| G2/Trustpilot reviews | Pain phrases, outcome language, competitor comparisons |
| Support tickets | Objections, confusion points, feature requests |
| Sales call transcripts | Buying triggers, decision criteria, exact questions asked |
| Cancellation reasons | Why people leave, often the inverse of your best headline |
| Reddit/forums | Unfiltered frustration in the reader's own words |
| Survey open-ends | Direct responses to "what almost stopped you from signing up?" |
What to steal
- Pain phrases → Problem/Agitate sections
- Outcome phrases → Benefit statements and headlines
- Objection phrases → FAQ and objection-handling sections
- Comparison language → Differentiation copy
VoC feeds directly into the copywriting brief (questions 2 and 3 in the copywriting skill).
Common mistakes
- Reading 5 reviews instead of 50. Patterns only emerge at volume.
- Paraphrasing instead of quoting. The reader's exact words resonate because they are literally the reader's words.
- Mining only positive reviews. Negative reviews reveal the objections your landing page must handle.
---
Page length decision
Short-form and long-form landing pages serve different situations. The decision is not about preference; it's about the reader's needs.
Decision matrix
| Price | Complexity | Awareness | Recommended length |
|---|---|---|---|
| Low | Simple | High (warm traffic) | Short: under 125 words. 15% higher conversion. |
| Low | Simple | Low (cold traffic) | Medium: establish context, then convert. |
| High | Complex | High | Medium-long: address objections, show proof. |
| High | Complex | Low | Long: full persuasion sequence. Crazy Egg saw 363% lift. |
Short-form rules
- Under 125 words of body copy
- One screen on desktop, two on mobile
- Hero, one proof point, CTA, nothing else
- Best for: free resources, newsletter signups, known brands, warm referral traffic
Long-form rules
- Each section must answer a specific objection or build a specific confidence
- Sections that just "fill space" are friction, not persuasion
- Repeat the CTA after hero, after proof, and at bottom
- Best for: high-ticket products, complex services, cold traffic, solution-aware comparison shoppers
The Rule of One applies regardless of length: one reader, one offer, one promise, one CTA.
Design in Code
Fast, low-fi planning before visual polish.
Start low-fi
- Plan the layout with ASCII wireframes (in Markdown or a comment block).
- Build structure first; make it usable before making it pretty.
- Use constraints early (grid, spacing, and type scale).
Copy what works
- Start from a gold-standard product.
- Match layout, spacing, and hierarchy; then adapt to context.
- When refreshing an existing product, keep a live old/new toggle behind a feature flag for fast comparison.
- Tune colour and token changes in the running product when possible, then sync exact values back to the design system.
- Use quick review questions during polish: what should hold focus, which controls are louder than the task, and which borders or icons can be removed with no loss of meaning.
Tools (defaults)
- shadcn/ui + Tailwind tokens.
- Keep components boring and conventional for faster iteration.
Marketing / Brand UI
Commit to a clear aesthetic point of view before any code is written. Avoid generic AI aesthetics.
Contents
- Working model
- Beautiful defaults
- Landing page default sequence (Hero rules, Viewport budget)
- Imagery
- Copy
- UX baseline
- Aesthetic rules
- Motion
- Hard rules
- Litmus checks
- Conversion strategy
Working model (before building)
Write three things before touching code:
- Visual thesis: one sentence describing mood, material, and energy.
- Content plan: hero, support, detail, final CTA, with what each section must communicate.
- Interaction thesis: 2-3 motion ideas that change the feel of the page.
Each section gets one job, one dominant visual idea, and one primary takeaway or action.
Beautiful defaults
- Start with composition, not components.
- Prefer a full-bleed hero or full-canvas visual anchor.
- Make the brand or product name the loudest text.
- Keep copy short enough to scan in seconds.
- Use whitespace, alignment, scale, cropping, and contrast before adding chrome.
- Two typefaces max, one accent color by default.
- Default to cardless layouts. Use sections, columns, dividers, lists, and media blocks instead.
- Treat the first viewport as a poster, not a document.
Landing page default sequence
1. Hero: brand or product, promise, CTA, and one dominant visual. 2. Support: one concrete feature, offer, or proof point. 3. Detail: atmosphere, workflow, product depth, or story. 4. Final CTA: convert, start, visit, or contact.
Hero rules
- One composition only. Full-bleed image or dominant visual plane.
- On branded landing pages, the hero runs edge-to-edge with no inherited page gutters, framed container, or shared max-width. Constrain only the inner text/action column.
- Brand first, headline second, body third, CTA fourth.
- No hero cards, stat strips, logo clouds, pill soup, or floating dashboards by default.
- Keep headlines to roughly 2-3 lines on desktop and readable in one glance on mobile.
- Keep the text column narrow and anchored to a calm area of the image.
- All text over imagery must maintain strong contrast and clear tap targets.
If the first viewport still works after removing the image, the image is too weak. If the brand disappears after hiding the nav, the hierarchy is too weak.
Viewport budget
- If the first screen includes a sticky/fixed header, that header counts against the hero. Combined header + hero content must fit within the initial viewport.
- When using
100vh/100svhheroes, subtract persistent UI chrome (calc(100svh - header-height)) or overlay the header instead of stacking it.
Imagery
Imagery must do narrative work.
- Use at least one strong, real-looking image for brands, venues, editorial pages, and lifestyle products.
- Prefer in-situ photography over abstract gradients or fake 3D objects.
- Choose or crop images with a stable tonal area for text.
- Do not use images with embedded signage, logos, or typographic clutter fighting the UI.
- Do not generate images with built-in UI frames, splits, cards, or panels.
- If multiple moments are needed, use multiple images, not one collage.
Copy
- Write in product language, not design commentary.
- Let the headline carry the meaning.
- Supporting copy should usually be one short sentence.
- Cut repetition between sections.
- Do not include prompt language or design commentary in the UI.
- Give every section one responsibility: explain, prove, deepen, or convert.
If deleting 30 percent of the copy improves the page, keep deleting.
UX baseline (non-negotiable)
- Ensure full keyboard support and visible focus.
- Hit targets >= 24px (>= 44px on mobile).
- Keep forms accessible (labels, enter-to-submit, inline errors).
- Handle loading/empty/error states and long content.
Aesthetic rules
- Typography: choose distinctive fonts (not Inter/Roboto/Arial/system). Weight >= 400. Use
clamp(). - Colour: commit to a palette with CSS variables; avoid pure black/white; use one sharp accent.
- Composition: use asymmetry, contrast, and negative space intentionally.
- Backgrounds: build atmosphere with gradients/noise/patterns, not flat fills.
- Interaction details: set
pointer-events: noneon decorative layers; allow text selection by default.
Motion
- Ship at least 2-3 intentional motions: one entrance sequence in the hero, one scroll-linked or depth effect, one hover/reveal/layout transition.
- Follow
ui-animationguidelines for timing, easing, and motion review.
Hard rules
- No cards by default.
- No boxed or center-column hero when the brief calls for full bleed.
- No more than one dominant idea per section.
- No headline should overpower the brand on branded pages.
- No filler copy.
- No split-screen hero unless text sits on a calm, unified side.
- No more than two typefaces without a clear reason.
- No more than one accent color unless the product already has a strong system.
Litmus checks
- Is the brand or product unmistakable in the first screen?
- Is there one strong visual anchor?
- Can the page be understood by scanning headlines only?
- Does each section have one job?
- Are cards actually necessary?
- Does motion improve hierarchy or atmosphere?
- Would the design still feel premium if all decorative shadows were removed?
Conversion strategy
For pages with a conversion goal, load cro.md (persuasion, social proof, benchmarks, page length), testing.md (experiment planning), and modern.md (mobile, speed, personalisation, microcopy). The layout rules below are the track-level decisions; the references cover the psychology and the numbers.
Conversion-aware layout
- One CTA, repeated. Primary CTA appears after hero, after proof, and at bottom. Don't introduce competing actions.
- Strip navigation on landing pages. Every link that isn't the CTA is a leak.
- Every section must earn its place. Each section either builds confidence, handles an objection, or drives toward the CTA. Sections that just describe the company are page furniture; cut them.
- Message match. The hero headline must echo the promise that brought the reader here (ad, email, referral). If the ad said "Cut your AWS bill in half" and the page opens with "Welcome to CloudSave", the reader bounces.
- Proof near every conversion point: within one scroll of each CTA, with 3-5 logos or one credibility stat above the fold. Placement rules and the proof credibility hierarchy are in cro.md.
- Mobile is a separate design, not a reflow: above-the-fold CTA kept visible via sticky bar, proof within two scroll-lengths, single-column 16px+ forms. Full rules in modern.md.
Modern Conversion Techniques
Reference for personalisation, mobile-first conversion, page speed, accessible copy, and microcopy. Load alongside cro.md when building or auditing marketing pages.
Table of contents
---
AI personalisation
Non-personalised B2B landing pages convert at 1-3%. Personalised pages lift conversion by 25-40%. The gap is widening: personalisation is becoming table stakes, not a competitive advantage.
What to personalise
| Element | Personalisation source | Example |
|---|---|---|
| Headline | UTM campaign or referral source | Ad says "Cut your AWS bill" → headline echoes "Cut your AWS bill in half" |
| CTA | Awareness stage | First visit: "See how it works" / Return visit: "Start your free trial" |
| Hero image | Industry or persona | Show a dashboard for SaaS buyers, a storefront for ecommerce |
| Social proof | Visitor segment | Show testimonials from the visitor's industry |
| Pricing emphasis | Company size (firmographic) | Highlight the plan most likely to fit |
Data sources
- UTM parameters: campaign, source, medium, content
- IP-based firmographics: company size, industry, location (tools like Clearbit, 6sense)
- Behavioural: returning visitor, pages viewed, time on site
- Cookie/session data: previous interactions, abandoned forms
The risk spectrum
- Under-personalisation: wastes the infrastructure. Dynamic content that shows the same thing to everyone.
- Over-personalisation: feels creepy. "Hi Sarah from Acme Corp, we noticed you visited our pricing page three times" crosses the line.
- Sweet spot: adapt the message to the visitor's context without revealing how much you know.
Adoption of AI personalisation for landing pages is accelerating; it is moving from differentiator to baseline expectation.
Common mistakes
- Personalising before the baseline page converts. Fix the fundamentals first. Personalisation amplifies a working page; it doesn't rescue a broken one.
- Too many segments with too little traffic. Each segment needs enough visitors to validate. Start with 2-3 segments, not 20.
---
Mobile-first conversion
62% of ecommerce traffic is mobile. Design for mobile first, then enhance for desktop, not the reverse.
Layout rules
- Single-column layout. No side-by-side comparisons that force horizontal scrolling.
- 44-48px tap targets. Apple specifies 44px minimum; Google recommends 48px. Anything smaller frustrates thumb navigation.
- Thumb-zone CTA placement. Primary actions in the bottom-centre of the screen, reachable without stretching.
- Sticky CTA. Keep the primary CTA visible as the user scrolls. A fixed bottom bar or floating button ensures the action is always one tap away.
The 70% rule
70% of mobile users don't scroll to mid-page. This changes everything about section ordering:
- CTA must appear above the fold on mobile
- Social proof must appear within the first two scroll-lengths
- Problem/pain sections that work on desktop may need to be shortened or reordered for mobile
- Test mobile and desktop layouts independently; what converts on desktop may fail on mobile
Forms
- Fewer fields. Every field removed reduces friction. Test 3-field vs 5-field.
- Larger inputs. Font size ≥ 16px prevents iOS zoom-on-focus.
- `inputmode` attributes. Use
inputmode="email",inputmode="tel",inputmode="numeric"to show the right keyboard. - Single-column forms only. Never place fields side-by-side on mobile.
Speed
Pages loading under 1 second convert 3x better than those loading in 5+ seconds. Mobile speed is non-negotiable; see Page speed below.
---
Page speed
Every 100ms of load time costs approximately 1% in conversions. Speed is not a technical detail; it's a conversion lever.
The numbers
| Metric | Impact |
|---|---|
| Every 100ms delay | ~1% conversion drop |
| Pages under 1 second | 3x better conversion vs 5+ seconds |
| 0.1s improvement | Up to 8% conversion lift |
| 3+ second load time | 53% of visitors abandon |
Only a minority of mobile sites pass all three Core Web Vitals. CWV affects both organic visibility and paid traffic quality scores, so speed work pays twice.
Core Web Vitals targets
| Metric | Target | What it measures |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | Loading: how quickly the main content appears |
| INP (Interaction to Next Paint) | < 200ms | Responsiveness: how quickly the page reacts to input |
| CLS (Cumulative Layout Shift) | < 0.1 | Stability: how much the layout shifts during load |
Three highest-leverage fixes
1. Fonts. Use font-display: swap or optional. Subset fonts to the characters actually used. Preload the primary font file. Self-host instead of Google Fonts CDN when possible. 2. Images. Serve WebP/AVIF. Use width and height attributes to prevent CLS. Lazy-load below-the-fold images. Serve responsive sizes via srcset. 3. Third-party scripts. Audit every external script (analytics, chat widgets, A/B testing tools, social embeds). Each script adds DNS lookups, connections, and parse time. Defer or remove anything non-essential for the conversion goal.
Common mistakes
- Optimising server response time when the bottleneck is render-blocking JS. Measure first, optimise the actual bottleneck.
- Adding a "speed badge" without measuring. Claiming fast performance without Core Web Vitals data is like claiming "easy setup" without testing it.
- A/B testing tools that slow the page. Ironic but common: the tool you're using to improve conversion is killing it via load time. Measure the testing tool's own impact.
---
Accessible copy
Accessible copy is not a compliance checkbox; it expands your addressable market and improves conversion for everyone. Target WCAG 2.2.
WCAG rules that affect copy
| Criterion | What it means for copy |
|---|---|
| 2.4.4 Link purpose | Link text must describe the destination. "Click here" and "Learn more" fail. Use "View case studies" or "Download the guide". |
| 2.4.6 Headings and labels | Headings must describe the content that follows. No heading should be a mystery. |
| 1.4.3 Contrast | Text must meet minimum contrast ratios. This affects colour choices for CTA buttons and hero text over images. |
| 3.1 Readability | Write at or below grade 8 reading level for marketing copy (Flesch-Kincaid). |
| 1.3.1 Info and relationships | Heading hierarchy must be semantic (H1 → H2 → H3). Don't skip levels for visual sizing. |
Plain language rules
- Sentence length: aim for 15-20 words average. Break long sentences at the strongest claim.
- Paragraph length: max 3-4 sentences. On mobile, even 2 sentences per paragraph is better.
- Left-align body text. Never centre body copy; centred text creates uneven left edges that slow reading.
- Avoid jargon unless your audience uses it daily. If in doubt, use the simpler word.
Descriptive CTAs and link text
"Click here" and "Learn more" fail WCAG 2.4.4 and they fail conversion. Replace with action + outcome:
| Inaccessible | Accessible and clearer |
|---|---|
| Click here | Download the 2026 benchmark report |
| Learn more | See how Acme reduced churn by 40% |
| Read more | Read the full case study |
| Submit | Send my request |
---
Microcopy
The small text that isn't the headline or body copy, but still drives conversion.
Button labels
Descriptive button text yields +25% CTR over generic labels. "Submit" → "Reserve my seat now" (specific, outcome-driven). See the copywriting skill's CTA Clarity framework for the full formula: action verb + what they get + qualifier.
Form labels and help text
- Labels are identification and micro-persuasion: "Work email" signals B2B context; "Your best email" signals personal.
- Help text below fields reduces errors: "We'll send your login link here, no password needed."
- Placeholder text is not a label. Placeholders disappear on focus, breaking usability.
Privacy reassurance
Place a privacy statement near every email field. Keep it short:
- "We won't share your email. Unsubscribe anytime."
- "No spam. Cancel anytime."
- "Your data stays private. See our privacy policy."
Privacy reassurance near forms increases completion rates, especially on mobile where trust signals are harder to spot.
Error messages
Explain what went wrong and how to fix it:
| Bad | Good |
|---|---|
| "Invalid input" | "Enter a valid email address (e.g. you@company.com)" |
| "Error" | "That password is too short, use at least 8 characters" |
| "Required field" | "We need your email to send the guide" |
Product UI (SaaS/Admin/Data-heavy)
Use for dashboards, admin tools, and data-dense workflows.
Contents
- Commit to a direction
- Core craft rules
- Calm dense interfaces
- Controls
- Type and data
- Colour and contrast
- Navigation context
- Motion
- Interaction baseline
- Utility copy
- Anti-patterns
- Litmus checks
Commit to a direction
- Define product context, user type, and emotional goal.
- Pick one dominant personality: precision/density, warm/approachable, trust/financial, bold/modern, utility/dev, data/analytics.
- Choose a colour foundation (warm, cool, neutral, tinted), light or dark, and a single accent.
- Pick a layout approach: dense grid, spacious, sidebar, top nav, or split list-detail.
- Choose typography that matches the product (system, geometric sans, humanist, mono).
Core craft rules
- Use a 4px spacing grid.
- Keep padding symmetrical unless there is a clear visual reason.
- Choose one radius system and use it everywhere.
- Concentric border radius:
outer-radius = inner-radius + padding. Mismatched radii on nested elements (a card containing an inner component, a button containing an icon badge) are the most common unnoticed visual error in production UIs. - Choose one depth strategy: borders-only, subtle shadow, layered shadow, or surface tint. When elements sit on non-white backgrounds, prefer
box-shadowoverborder: rgba transparency adapts to any surface; solid colors don't. - Layered shadow formula for cards, inputs, and containers:
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.06),
0 1px 2px -1px rgba(0, 0, 0, 0.06),
0 2px 4px 0 rgba(0, 0, 0, 0.04);Hover state: increase each opacity by 0.02. Transition with transition: box-shadow 200ms ease.
- Image outlines: add a 1px inset outline to images for depth. Use
outline(notborder) so layout dimensions are unaffected:
img {
outline: 1px solid rgba(0, 0, 0, 0.1);
outline-offset: -1px;
}
.dark img { outline-color: rgba(255, 255, 255, 0.1); }- Keep surface treatment consistent across cards, even if internal layouts differ.
Calm dense interfaces
Default to Linear-style restraint: calm surface hierarchy, strong typography and spacing, few colors, dense but readable information, minimal chrome. Cards only when the card is the interaction.
- Make the work surface dominant; navigation and orientation chrome should recede after the user arrives.
- Separate location/context, view controls, and page actions so each bar has one job.
- Keep shared header actions in predictable slots across comparable views.
- Use compact tabs and secondary bars; avoid full-width chrome when a smaller group communicates the same state.
- Reduce brightness, saturation, and icon size on supporting chrome before shrinking the content area itself.
- Audit every border, icon, and tint. If it does not clarify meaning, remove or soften it.
- If a panel can become plain layout without losing meaning, remove the card treatment.
Controls
- Prefer native selects/date inputs by default for accessibility and mobile UX.
- Use custom controls only when product requirements justify the added complexity.
- Preserve keyboard navigation, semantics, and screen-reader support when custom controls are necessary.
- For select triggers, use
inline-flex+white-space: nowrap.
Type and data
- Create a clear hierarchy (headline, body, label).
- Use tabular numbers or monospace for data tables and IDs.
- Icons must add meaning; remove decorative icons and unnecessary icon backgrounds.
- Use sentence case and follow the project locale/style guide.
Colour and contrast
- Use a 4-level contrast hierarchy (primary, secondary, muted, faint).
- Use colour only for meaning (status, action).
- Prefer restrained neutrals for core surfaces; keep warm or cool bias subtle.
Navigation context
- Show navigation, page location, and user/workspace context.
- Keep supporting bars and inactive navigation a step quieter than the main surface.
- In dark mode, prefer borders over shadows; adjust semantic colours.
Motion
- Keep motion subtle and functional.
- Follow
ui-animationguidelines.
Utility copy
When the work is a dashboard, app surface, admin tool, or operational workspace, default to utility copy over marketing copy.
- Prioritize orientation, status, and action over promise, mood, or brand voice.
- Start with the working surface itself: KPIs, charts, filters, tables, status, or task context. Do not introduce a hero section unless explicitly requested.
- Section headings should say what the area is or what the user can do there (e.g., "Selected KPIs", "Plan status", "Search metrics", "Last sync").
- Avoid aspirational hero lines, metaphors, or campaign-style language on product surfaces.
- Supporting text should explain scope, behavior, freshness, or decision value in one sentence.
- If a sentence could appear in a homepage hero or ad, rewrite it until it sounds like product UI.
- Litmus check: if an operator scans only headings, labels, and numbers, can they understand the page immediately?
Anti-patterns
- Heavy shadows, glowing borders, or thick borders on routine controls: every element shouts, so nothing reads as primary.
- Large radii on small controls: buttons and inputs read as toy-like next to dense data.
- Dashboard-card mosaics as the primary layout strategy: the page becomes a wall of boxes; hierarchy comes from the grid of cards instead of the data.
- Decorative gradients behind routine product UI: they reduce text contrast and read as marketing on a work surface.
- Multiple competing accent colors: status colours stop carrying meaning when accents appear everywhere.
- Ornamental icons and icon backgrounds: each one costs a fixation without aiding scanning.
- Excessive spacing on data-dense surfaces: operators scroll instead of scan.
- Stacked cards instead of plain layout when the card boundary adds no meaning.
Litmus checks
- Is the work surface louder than the navigation and chrome around it?
- Does every border, icon, and tint clarify meaning, and has everything that doesn't been removed?
- Is colour reserved for status and action?
- Do nested elements follow the concentric radius rule (outer = inner + padding)?
- Can an operator scanning only headings, labels, and numbers understand the page?
Testing and Optimisation
Reference for A/B testing, heatmap analysis, and conversion optimisation loops. Load when optimising an existing landing page or planning a testing strategy.
---
The CRO loop
Measure → Hypothesise → Test → Implement → Repeat.
Only 39.6% of companies have a documented CRO strategy. Most optimise ad-hoc, testing whatever feels wrong rather than what the data says matters. Structure the loop:
1. Measure: identify the weakest conversion point with analytics (bounce rate, scroll depth, click maps) 2. Hypothesise: state what you believe is wrong and why, with a predicted outcome 3. Test: run an A/B test with one variable changed 4. Implement: ship the winner 5. Repeat: move to the next weakest point
---
What to test first
Prioritised by typical impact on conversion rate:
| Priority | Element | Why it matters |
|---|---|---|
| 1 | Headline | The first thing read; determines whether the rest gets read |
| 2 | CTA text | Personalised CTAs convert 202% better than generic |
| 3 | Hero image/video | Sets emotional tone; context-of-use images outperform stock |
| 4 | Social proof placement | Moving proof above the fold or near the CTA can shift conversion significantly |
| 5 | Form length | Every field removed reduces friction; test 3-field vs 5-field |
| 6 | Page length | Short vs long; see cro.md for the decision matrix |
| 7 | CTA colour/size | Lower-leverage but easy to test; button size change can yield +90% |
Test high-leverage elements first. Don't optimise button colour when the headline doesn't match the ad.
---
A/B vs multivariate
| Method | When to use | Traffic requirement |
|---|---|---|
| A/B testing | Most landing page optimisation. One variable changed per test. Clean isolation: you know exactly why one version won. | Moderate (hundreds to low thousands of conversions) |
| Multivariate | Testing combinations of multiple elements simultaneously. Powerful but requires massive traffic to isolate which combination caused the lift. | Very high (thousands of conversions per variant) |
Default to A/B. Multivariate testing is impractical for most landing pages unless you're running tens of thousands of visitors per week.
---
Statistical significance
- Run until significant, not until the result looks good. A test that shows +20% after 50 visitors is noise, not signal.
- Minimum sample: depends on baseline conversion rate and minimum detectable effect. Use a sample size calculator before starting.
- Duration: run for at least one full business cycle (typically 1-2 weeks) to account for day-of-week variation.
- Never stop a test early because one variant is "clearly winning." Early results are unreliable. Pre-commit to a sample size and honour it.
---
Heatmap and scroll map insights
Heatmaps and scroll maps show where attention actually goes, not where you assume it goes.
Key findings
- 70% of mobile users don't scroll to mid-page. If your strongest proof or CTA is below the fold on mobile, most visitors never see it.
- Desktop scroll depth is deeper but still drops off sharply after the hero and first support section.
- Dead clicks reveal where users expect something interactive but find nothing: a missed CTA opportunity.
What to do with scroll data
1. Move your strongest message higher. If heatmaps show attention clustering in the top 30% of the page, that's where your best proof and CTA belong. 2. Create separate mobile and desktop strategies. Mobile users scan faster and scroll less, so prioritise differently. 3. Test section order. Move testimonials above features, or features above the problem statement, and measure the impact. 4. Identify drop-off cliffs. If 60% of users stop scrolling at a specific section, that section is either boring or confusing, so fix or remove it.
Real example
A local service business discovered via scroll maps that 70% of mobile users never reached their mid-page offer. Moving the offer above the fold doubled conversions within one month.
---
CTA statistics
Data-backed insights for CTA optimisation:
| Change | Impact on conversion |
|---|---|
| Personalised CTA (vs generic) | +202% |
| Single CTA per page (vs multiple) | +266% |
| Adding urgency (real, limited-time) | +332% |
| Increasing button size | +90% CTR |
| Changing button colour | +21% |
| Mobile-optimised CTA | +32.5% |
| Inline CTA (vs sidebar) | +121% CTR |
These are directional, not guaranteed. Every audience is different. Test your own variants, but start with the highest-leverage changes first.
Assets API
Covers: placeholder marks, avatars, logos, screenshots, wallpapers, and concrete asset URL parameters.
Base URL: https://assets.ui.sh
Prefer file extensions in asset URLs whenever the route supports them. Use /marks/{id}.svg, /avatars/{id}.webp, /logos/{id}.svg, /screenshots/{id}.webp, and /wallpapers/{type}.webp?variant={name}.
Marks
GET /marks/{id}
Preferred URL: /marks/{id}.svg
Returns an SVG mark, optionally with text.
IDs: 1
| Param | Type | Default | Notes |
|---|---|---|---|
text | string | none | Optional label text |
font | string | inter | inter, dm-sans, sora, outfit, instrument-sans, space-grotesk |
weight | number | 600 | Font weight |
color | string | black | Mark color |
textColor | string | color | Text color |
letterSpacing | number | -1 | Spacing between letters in pixels |
Avatars
GET /avatars/{id}
Preferred URL: /avatars/{id}.webp
Other image extensions such as .jpg, .jpeg, and .png are also accepted. Prefer .webp in docs and examples.
Returns an avatar image.
IDs: 1-16
| Param | Type | Default | Notes |
|---|---|---|---|
size | number | none | Square resize |
w | number | none | Width |
h | number | none | Height |
grayscale | flag | off | Apply grayscale |
Logos
GET /logos/{id}
Preferred URL: /logos/{id}.svg
Returns an SVG logo. IDs are matched fuzzily: case-insensitive, ignoring non-alphanumeric characters.
IDs: align, artifact, axiom, concise, looply, orbital, pinelabs, quirk, relay
| Param | Type | Default | Notes |
|---|---|---|---|
color | string | none | Primary fill |
accent-color | string | color | Secondary fill |
height | string | none | SVG height |
width | string | none | SVG width |
Screenshots
GET /screenshots/{id}
Preferred URL: /screenshots/{id}.webp
Other image extensions such as .jpg, .jpeg, and .png are also accepted. Prefer .webp in docs and examples.
Returns a screenshot image.
IDs: 1
1colors:mauve,mist,olive,stone,taupe
| Param | Type | Default | Notes |
|---|---|---|---|
color | string | none | Variant name |
top | number | none | Crop from top |
bottom | number | none | Crop from bottom |
left | number | none | Crop from left |
right | number | none | Crop from right |
Crop:
top+bottom: heighttop + bottomfromy=0toponly: top crop with heighttopbottomonly: bottom crop with heightbottomleft+right: widthleft + rightfromx=0leftonly: left crop with widthleftrightonly: right crop with widthright- All values must be positive integers
Wallpapers
GET /wallpapers/{type}
Preferred URL: /wallpapers/{type}.webp?variant={name}
Other image extensions such as .jpg, .jpeg, and .png are also accepted. Prefer .webp in docs and examples.
Returns a wallpaper image.
| Param | Type | Default | Notes |
|---|---|---|---|
variant | string | type-specific | Variant name |
Aliases:
landscape->landscapes
blend
Default: arctic-glimmer
Variants:
arctic-glimmer: cool arctic slate and frosted mint in the upper left flowing through a serene cerulean blue then merging into a deep navy and obsidian shadow toward the lower rightemerald-mist: deep forest green and dark moss in the upper left flowing through a vibrant sage and misty lime transition then settling into a soft eucalyptus and pale silver-grey at the lower rightgolden-hour-mist: soft champagne and pale cream in the upper left shifting into a warm apricot glow then deepening into a rich honey and toasted sienna at the lower rightmidnight-nebula: deep indigo and charcoal in the upper left transitioning into a vibrant violet haze followed by electric magenta and finishing in a soft turquoise glow at the bottom rightnebula-glow:: ###haze
Default: default
Variants:
dark: dark charcoal and deep grey monochromedefault: warm off-white and cream monochromemauve-dark: dark muted purple-grey monochromemauve: muted purple-grey and soft lavender monochromemist-dark: dark cool blue-grey monochromemist: cool blue-grey monochromesage: muted sage green and soft olive-grey monochrometaupe-dark: dark warm taupe monochrometaupe: warm taupe and neutral grey monochrome
horizon
Default: arctic-rim
Variants:
arctic-rim: Deep navy and cold-charcoal backgrounds with highlights of desaturated cyan and pale frosted silver.calcite-dusk: Deep charcoal and slate backgrounds with highlights of desaturated pearl and soft bone-white.celestial-lead: Cold lead-gray and charcoal backgrounds with highlights of desaturated lilac and frosted zinc.jade-corner: Deep oceanic-gray and muted charcoal backgrounds with highlights of desaturated jade and pale misty teal.obsidian-ember: Deep mahogany and dark umber backgrounds with highlights of desaturated bronze and weathered ash-gray.oxide-center: Deep graphite and charred-umber backgrounds with highlights of matte rust and weathered bronze.sepia-rim: Deep umber and warm-charcoal backgrounds with highlights of matte gold and weathered bronze.
landscapes
Default: valley
Variants:
arctic-fjord: deep-seated glacial fjord flanked by sheer granite cliffs and distant ice-capped peaks: icy cerulean, muted indigo, frosted slate, pale bone whitebasalt-plateau: vast basalt plateau with distant volcanic ridges: ash grey, muted obsidian, dark pewter, faint earthy umbercoast: coastal beach with gentle waves: slate blues, soft teal, pale grey sky, cool sandy beigedunes: desert dunes at sunset: dusty rose, terracotta, warm mauve, soft peach skyforest: misty pine forest valley: sage greens, cool grays, muted blue-greenfossil-cliffs: towering chalk cliffs overlooking a still, pale sea: creamy bone white, soft oyster grey, muted sea-foam green, pale flint bluehighland-moors: rolling highland moorland with patches of wild heather and moss: muted heather purple, deep moss green, weathered peat brown, soft charcoal greyhills: rolling pastoral hills with scattered autumn trees: olive green, faded ochre, burnt umber, warm taupelake: still lake at twilight with forested shoreline: deep slate blue, muted teal, soft peach undertoneslimestone-karst: submerged limestone pillars rising from a calm and misty bay: faded lichen green, weathered grey stone, soft misty blue watermeadow: alpine meadow with distant mountains: soft sage green, pale grey-blue mountains, warm hay tonesmisty-marshland: low-lying wetlands with scattered pools and tall reeds: mossy green, muted bronze, dark water grey, pale foggy lavenderpampas-grassland: expansive plains of tall pampas grass under a wide, open sky: pale straw, muted silver, dusty lilac, soft grey-bluesalt-crust-expanse: expansive dry salt flats with distant mountain silhouettes: pearl white, ivory, faint lilac shadows, muted silver-greysnow: minimalist snowfield with soft rolling dunes: off-white snow, cool blue-grey shadows, pale skyvalley: misty mountain valley with scattered trees: sage greens, soft grays, warm taupe undertonesweathered-badlands: deeply eroded sedimentary hills and canyons with horizontal strata lines: muted terracotta, dusty clay, pale sandstone, soft ochre, warm charcoal
silk
Default: crimson-surge
Variants:
crimson-surge: Deep scarlet and polished ruby texturescyan-glacier: Vivid turquoise and liquid crystalline texturesemerald-glint: Deep hunter green and iridescent teal accentsmidnight-violet: Deep obsidian and translucent violet huesmolten-amber: Deep burnt orange and polished bronze texturesplatinum-flow: Liquid mercury and polished titanium texturessapphire-flux: Deep royal blue and luminous sapphire-blue textures
Color Resolution
Color params accept Tailwind names like red-500 and blue-600, resolved to oklch(). Other CSS colors pass through unchanged.
Avatars
Covers: profile photos, user thumbnails, testimonial people, comments, team members, and overlapping avatar groups.
- See Assets API for avatar URLs and query parameters
- Prefer extension-suffixed avatar URLs such as
/avatars/1.webp - Use
outline-1 -outline-offset-1 outline-black/5oroutline-black/10on light surfaces; useoutline-white/10on dark surfaces - Give stacked/overlapping avatar groups a 2px
ringthat matches the background color (e.g.ring-2 ring-white)
Badges
Covers: badges, tags, pills, labels, chips, status indicators, and compact metadata with icons.
- Badges with a leading or trailing icon: never use symmetric
px-*; usepl-*/pr-*and set the icon side's padding equal to the vertical padding:py-1 pr-2 pl-1(left icon),py-1 pr-1 pl-2(right icon)
Border Radius
Covers: rounded cards, panels, buttons, images, screenshots, nested surfaces, and any UI element where radius consistency matters.
- Use concentric border radii on closely nested rounded elements: define the relationship explicitly with CSS variables and
calc()so the math is enforced, e.g.rounded-(--radius) p-(--padding)on the outer element,rounded-[calc(var(--radius)-var(--padding))]on the inner - Use
min()with viewport units for image/screenshot border radii instead of fixedrounded-*values: e.g.rounded-[min(1vw,12px)]; the radius should match the intended value at full desktop width and scale proportionally as the screen shrinks - Keep one radius family per view: don't mix rounded and sharp corners on sibling elements; pick a small set of radii (e.g. controls, cards, fullscreen surfaces) and apply them consistently
Buttons
Covers: primary buttons, secondary buttons, CTAs, icon buttons, destructive actions, form actions, and touch targets.
Design Rules
- When adding shadows to buttons, follow the shadow rules in
shadows.md: never pairshadow-*with solid gray borders; usering-1 ring-black/5orring-1 ring-black/10instead - Primary buttons with a ring: never use reduced opacity on the ring; use a solid color that matches the button background (e.g.
ring-indigo-600on anbg-indigo-600button, notring-black/10) - Dangerous actions like "Delete" use a secondary/muted button style by default: only use a primary button style when the dangerous action is the primary action on the page or dialog (e.g. a confirm-delete dialog)
- Only one primary button per page: scan the entire page and ensure only one button uses a filled/solid primary style; every other button must use a secondary style, soft/muted (solid with opacity), outline, or ghost (text-only); treat dialogs/modals as their own page
- Never make a secondary button higher contrast than the primary button: the primary button must always be the most visually prominent
- Any button that is not the page's primary submit/save action is an inline form action: change avatar, change photo, upload file, generate password, verify email, add item, resend code, etc.; always use the smaller of the two button sizes and a secondary style; these must never be the same height as the form's primary/submit button
Sizing
- Use less horizontal padding:
px-3 py-2notpx-4 py-2,px-4 py-3notpx-5 py-3 - Application UIs (dashboards, settings, admin):
text-smwith compact padding, nevertext-base; total rendered button height (including outer wrapper/ring) must stay within 28-38px; account for thep-pxborder wrapper when calculating, the wrapper adds 2px total - Maximum 2 button sizes per application UI: pick two distinct heights and use only those; the difference between them must be at least 6px
- Buttons with a leading or trailing icon: never use symmetric
px-*; usepl-*/pr-*and set the icon side's padding equal to the vertical padding:py-2 pr-3 pl-2(left icon),py-2 pr-2 pl-3(right icon),py-1.5 pr-2.5 pl-1.5(left icon, compact)
Focus Styles
- Solid buttons need a custom focus ring: use
focus-visible:outline-*withfocus-visible:outline-offset-2; default tofocus-visible:outline-blue-500if the project has no established focus color
Coding Rules
- Small/icon buttons must meet the 48×48px minimum touch target: make the button
relativeand add<span class="absolute top-1/2 left-1/2 size-[max(100%,3rem)] -translate-1/2 pointer-fine:hidden" aria-hidden="true" />as a direct child
Colors
Covers: brand colors, accent colors, neutral palettes, text colors, default color families, and semantic color scales.
- Never default to indigo as the brand/accent color: only use indigo if the project already uses it or the user explicitly requests it
- Never default to
gray-*orslate-*for neutral/text colors: only use them if the project already uses them or the user explicitly requests them; preferzinc-*orneutral-*instead
Semantic color scales
When defining a custom multi-step palette, assign each step a role so component states are derivable, not hand-picked. Steps should encode intent, not just lightness. For a 10-step scale (scale the mapping to the project's actual step count):
100background,200hover background,300active background400border,500hover border,600active border700solid fill (high contrast),800solid fill hover900secondary text and icons,1000primary text and icons
With roles assigned, derive states by stepping up the scale: a fill moves 700 to 800 on hover; a background moves 100 to 200 on hover and 300 on active; a border moves 400 to 500 to 600. Build the scale once, then reference roles instead of picking a new color per state.
Copywriting
Covers: headings, taglines, subtitles, descriptions, labels, list items, button text, and other UI copy.
- Headings: periods or no periods are both fine, but be consistent within a page
- Always use proper punctuation (ending period) on full sentences and paragraphs
- Use a period on any descriptive text that stands alone: taglines, subtitles, tier descriptions like "For professionals and growing teams.", single-line descriptions like "For organizations that need more power and control."
- Only omit periods on items in a list: e.g. feature bullet points in pricing cards
- Never use emojis anywhere: not in headings, descriptions, buttons, labels, or any other text
UI microcopy
- Name actions with a verb plus a noun ("Delete Member", "Deploy Project"), never bare "Confirm", "OK", or a lone verb
- Write errors as what happened plus what to do next: "Build failed. Bundle exceeds 50 MB. Reduce it or raise the limit."
- Toasts name the specific thing that changed, drop the trailing period, and never say "successfully": "Project deleted", not "Successfully deleted the project."
- Empty states point to the first action: "No deployments yet. Push to your Git repository to create one."
- In-progress states use the present participle plus an ellipsis: "Deploying...", "Saving..."
- Use Title Case for labels, buttons, titles, and tabs; sentence case for body, helper text, and toasts
Custom Fonts
Covers: loading custom fonts, registering font theme variables, and applying display/body font utilities.
- Always load custom fonts before using them: add
<link>tags in the HTML<head>(preferred); if no<head>is available, use@import url('…');at the top of the CSS file instead - Register frequently used custom fonts in the CSS
@themeblock: e.g.--font-display: "Oswald", sans-serif;; optionally set--font-display--font-feature-settingsand--font-display--font-variation-settingsfor fine-tuning - Register headline/display fonts as
--font-display(creates afont-displayutility): use--font-sansfor body/UI fonts and--font-displayfor fonts that are only used on headings and display text; applyfont-displayon headings alongsidefont-sanson the body
Dark Mode
Covers: dark-mode styling, light-to-dark conversion, dark-mode contrast audits, dark-mode images, and dark-mode SVGs.
Design Rules
- Dark mode is about maintaining the same contrast ratios as light mode, not simply inverting colors
- Dark mode doesn't need to preserve every detail of the light mode design: it just needs to look good
- Default dark mode to follow the operating system's
prefers-color-schemesetting (Tailwind's built-indark:behavior); only add a manual toggle when the user explicitly asks for one - Remove all shadows in dark mode: use
dark:shadow-none - On dark-mode-only sites, add the
scheme-only-darkclass to<html>or the top-level element: ensures native elements like scrollbars, form controls, andcolor-schemerender in dark mode
Component Rules
- Never keep large branded/colored panels in dark mode; instead use the same background color and add a light divider between sections
- Style cards only slightly lighter than the page background (e.g.
dark:bg-gray-900on adark:bg-gray-950page); add adark:inset-ring dark:inset-ring-white/5for definition - Make decorative quote marks in testimonials very faint (e.g.
dark:text-white/5) - Never use multiple heading text colors in dark mode (e.g. dark gray + brand color); use a single light color like
whiteorgray-100for all heading text
Raster Image Rules
- When adding or improving dark mode, audit the page for rasterized images that need dark-mode versions: photos, screenshots, product mockups, decorative backgrounds, textures, and rasterized illustrations
- Never use CSS filters (
invert,brightness,contrast,opacity) as the final dark-mode treatment for raster images; always create real dark-mode image files - Generate dark-mode raster image variants by following ../dark-mode-image.md, which requires the
imagegenskill before creating or editing any raster image assets
SVG Rules
- For inline
<svg>elements, style dark mode with Tailwinddark:*classes (e.g.dark:fill-*,dark:stroke-*,dark:text-*) - For external SVG files referenced via
<img>, always create a dark-mode version alongside the original (e.g.logo.svgandlogo-dark.svg); never substitute CSS filters (invert,brightness) or opacity adjustments for a true dark variant
Dashboards
Covers: dashboard layouts, stat grids, KPI cards, metric cards, admin panels, analytics views, and summary data.
Design Rules
- Never allow stat or metric card titles to wrap; use
truncateto keep them on a single line - Never put icons in stat/metric cards: use plain text labels and values only
Coding Rules
- Always use container queries for responsive dashboard widgets, not media queries
Description Lists
Covers: <dl>, <dt>, and <dd> content, term/detail pairs, metadata groups, and definition-style lists.
- Style
<dt>elements with higher contrast text color and a slightly heavier font weight (e.g.font-medium); style<dd>elements with regular font weight and a lower contrast color: this lets links inside<dd>elements use the higher contrast color to stand out
Feature Lists
Covers: feature grids, benefit lists, product feature sections, and any section listing multiple features with titles and descriptions.
- Use
<dl>,<dt>, and<dd>elements for feature sections that list multiple features: not<ul>/<li>or plain<div>groups
Flexbox Layout
Covers: flex containers, flexible children, fixed-size icons/images, truncation, sidebars, and layouts using flex-1, min-w-0, or shrink-0.
- Always add
min-w-0(ormin-width: 0) to flex children that need to shrink below their content size: flex items default tomin-width: autoand won't shrink past their content without it; applies at every scale, from page-level layouts (e.g. a fluid content area next to a fixed-width sidebar usingflex-1) down to small UI pieces (e.g. a truncated text label in a row, a flexible input next to a fixed button) - Always add
shrink-0to flex children that should never shrink: icons, SVGs, images, logos, avatars, and any element that would become visually distorted if compressed
Font Recommendations
Covers: optional font suggestions, type direction exploration, and font ideas for design variations.
These are optional recommendations for when the user asks for help choosing a font or wants to try different fonts across design variations. Never force these, only reference them when font selection is part of the task.
General Guidelines
- Default to Inter for body/UI text unless the user is specifically exploring other options
- Always recommend sans-serif fonts unless the user explicitly asks for serif/non-sans-serif, uses words like "sophisticated" or "editorial", or the project clearly calls for it (e.g. luxury brand, literary magazine, fashion editorial)
By Purpose
Body & UI
Fonts that work well for body copy, application interfaces, and general-purpose use. Most of these also work for headings.
Sans-serif:
- [DM Sans](#dm-sans): low-contrast geometric, large x-height, excellent small-text readability
- [Figtree](#figtree): friendly geometric with curved letterforms, warm and approachable
- [General Sans](#general-sans): compact rationalist, space-efficient, good for dense UI
- [Geist](#geist): Swiss-inspired, minimal and precise, built for UI
- [Host Grotesk](#host-grotesk): uniwidth (weight changes don't shift layout), good for nav/tabs/buttons
- [Inter](#inter): clean and highly legible, the default recommendation for screens
- [Instrument Sans](#instrument-sans): geometric neo-grotesque, clean and technical
- [Mona Sans](#mona-sans): GitHub's neo-grotesque, strong industrial feel
- [Satoshi](#satoshi): modernist with personality, double-storey
aandg
Serif:
- [Lora](#lora): well-balanced contemporary serif, good readability at body sizes, subtle brush-stroke contrast
Headlines & Display
Fonts best suited for headings and large display text. Many Body & UI fonts above also work well for headings, the fonts listed here are particularly strong choices for display use or are display-only.
Sans-serif:
- [DM Sans](#dm-sans): low-contrast geometric that scales up cleanly for headlines while staying readable at body sizes
- [Fixel Display](#fixel-display): geometric-humanist hybrid, display sizes only
- [Geist](#geist): Swiss-inspired precision that looks sharp and authoritative at headline sizes
- [Inter](#inter): clean and versatile with a Display optical size variant that activates automatically at larger sizes
- [Mona Sans (wide)](#mona-sans): Mona Sans with
"wdth"axis cranked up, strictly for headlines - [Satoshi](#satoshi): double-storey
aandggive headlines personality without losing modernist discipline
Serif:
- [Instrument Serif](#instrument-serif): high-contrast editorial serif, pairs with a sans-serif body for a premium feel
Monospace
For code snippets, inline code, or a technical/developer aesthetic.
- [Geist Mono](#geist-mono): Vercel's monospace, pairs naturally with Geist
- [IBM Plex Mono](#ibm-plex-mono): IBM's monospace, versatile and highly legible
---
Font Details
DM Sans
A low-contrast geometric with open apertures and a large x-height. Single-storey a and g, straight-legged R. Excellent small-text readability, works especially well as a body font paired with other headline fonts. Also works for headlines.
- Source: load from Google Fonts (
family=DM+Sans:opsz,wght@9..40,100..1000) - Registration: register in
@themeas--font-sans: "DM Sans", sans-serif; - Pairs with: Inter, Geist
Figtree
A friendly geometric with distinctive curved t, f, and y letterforms that give it warmth without being playful. Monolinear stroke. Good for friendly, approachable designs. Works for both headlines and body.
- Source: load from Google Fonts (
family=Figtree:wght@300..900) - Registration: register in
@themeas--font-sans: "Figtree", sans-serif; - Pairs with: Inter, Geist, DM Sans
Fixel Display
A geometric-humanist hybrid with open letterforms and wide proportions. Display variant optimized for larger sizes, use for headlines and display text only, never for body copy.
- Source: must be self-hosted: download from
https://fixel.macpaw.com - Registration: register in
@themeas--font-display: "Fixel Display", sans-serif; - Pairs with: Inter, Geist, DM Sans
Geist
A Swiss-inspired sans-serif by Vercel, minimal, precise, built for UI. Works for body copy, application UI, and headings.
- Source: load from Google Fonts (
family=Geist:wght@100..900) - Registration: register in
@themeas--font-sans: "Geist", sans-serif; - Pairs with: Inter, DM Sans
Geist Mono
A monospace font by Vercel. Good for technical/developer-oriented sites or for code snippets and inline code styling.
- Source: load from Google Fonts
- Registration: register in
@themeas--font-mono: "Geist Mono", monospace;
IBM Plex Mono
IBM's monospace typeface. Versatile and highly legible, works for code snippets, technical content, and developer-oriented sites.
- Source: load from Google Fonts (
family=IBM+Plex+Mono:wght@400;500;600;700) - Registration: register in
@themeas--font-mono: "IBM Plex Mono", monospace;
General Sans
A compact rationalist sans-serif with small apertures and a disciplined, closed feel. Space-efficient, good for dense UI and tight layouts. Works for both headlines and body.
- Source: load from Fontshare (
https://api.fontshare.com/v2/css?f[]=general-sans@200,300,400,500,600,700&display=swap) - Registration: register in
@themeas--font-sans: "General Sans", sans-serif; - Pairs with: Inter, Geist, DM Sans
Host Grotesk
A uniwidth sans-serif, letter widths stay consistent across all weights, so changing weight never shifts layout. Good for tabs, buttons, navigation, and anywhere weight changes must not cause reflow. Works for both headlines and body.
- Source: load from Google Fonts (
family=Host+Grotesk:wght@300..800) - Registration: register in
@themeas--font-sans: "Host Grotesk", sans-serif; - Pairs with: Inter, Geist, DM Sans
Instrument Sans
A geometric neo-grotesque built from straight lines and simple circles. Uniform strokes, straight terminals. Has 12 stylistic sets for alternate glyphs. Best suited for clean, technical interfaces. Works for both headlines and body.
- Weight restriction: only supports
font-normal(400): never usefont-medium,font-semibold, orfont-bold - Source: load from Google Fonts (
family=Instrument+Sans:wght@400..700) - Registration: register in
@themeas--font-sans: "Instrument Sans", sans-serif; - Pairs with: Inter, Geist, DM Sans
Instrument Serif
A high-contrast editorial serif for headlines and display text. Gives pages a premium, editorial feel when paired with a clean sans-serif body font, works especially well for marketing sites, landing pages, and brand-forward designs.
- Sizing: Instrument Serif is optically small: never use
text-4xlor smaller for headings; usetext-5xland up where other fonts would usetext-4xl - Source: load from Google Fonts
- Registration: register in
@themeas--font-display: "Instrument Serif", serif; - Pairs with: Inter, Geist, DM Sans
Inter
A clean, highly legible sans-serif designed for screens. Works well for body copy, application UI, and headings.
- Source: always load from
https://rsms.me/inter/inter.cssor self-host: never use the Google Fonts version, which lacks the Display optical size variant andfont-feature-settingssupport - Optical sizing: Inter includes a Display variant that automatically activates at larger sizes via
font-optical-sizing: auto; the Google Fonts build strips this out - Feature settings: turn on optional OpenType features to give Inter a more custom feel:
cv02(double-storya→single-story),cv03(open6/9),cv04(open4),cv11(single-storyl),ss01(open digits),ss03(round quotes) - Registration: register in
@themeas--font-sans: "InterVariable", sans-serif;with--font-sans--font-feature-settings: "cv02", "cv03", "cv04", "cv11";to enable features globally - Pairs with: Geist, DM Sans
Lora
A well-balanced contemporary serif with roots in calligraphy. Moderate contrast with subtle brush-stroke terminals, readable at body sizes while still feeling refined. Works for editorial content, blogs, and long-form reading. Also works for headlines.
- Source: load from Google Fonts (
family=Lora:wght@400..700) - Registration: register in
@themeas--font-serif: "Lora", serif; - Pairs with: Inter, Geist, DM Sans, Satoshi
Mona Sans
GitHub's neo-grotesque with an optical size axis that adjusts letterforms automatically at different sizes. Strong, industrial feel. Works for both headlines and body.
- Source: load from Google Fonts (
family=Mona+Sans:wght@200..900) - Width axis: has a
wdthvariable axis: use a wider value (e.g."wdth" 112.5) for headlines to give them a bolder, more expanded feel; the wide variant is strictly for headlines, never for body copy - Registration: register in
@themeas--font-sans: "Mona Sans", sans-serif;; when using the wide variant for headlines, also register--font-display: "Mona Sans", sans-serif;with--font-display--font-variation-settings: "wdth" 112.5; - Pairs with: Inter, Geist, DM Sans
Satoshi
A modernist sans-serif blending rounded shapes with sharp angular details. Double-storey a and g give it more personality than typical geometrics, lean into that for brand-forward designs. Works for both headlines and body.
- Source: load from Fontshare (
https://api.fontshare.com/v2/css?f[]=satoshi@300,400,500,700,900&display=swap) - Registration: register in
@themeas--font-sans: "Satoshi", sans-serif; - Pairs with: Inter, Geist, DM Sans
Footers
Covers: page footers, footer logos, footer navigation, footer links, and social media icons.
Design Rules
- Logo height between
h-5andh-7 - Use
font-normalfor footer links - Social media icons must be at least
text-gray-600: never usetext-gray-400or lighter
Coding Rules
- Always use the placeholder content logo endpoint when no logo file is provided: never create logos from scratch with HTML or icons
Form Controls
Covers: inputs, selects, textareas, checkboxes, radio buttons, toggles, search bars, checkout forms, auth forms, and input/button combos.
Design Rules
- Never pair
shadow-*with solid gray borders on any form control:
Don't:
<... class="border border-gray-300 shadow-* ..." /> <... class="border border-gray-950/10 shadow-* ..." />Do:
<... class="ring-1 ring-black/10 shadow-* ..." />- Use
max-w-xsfor compact, single-purpose forms like login, sign-up, or single-field inputs:max-w-smand wider is too spacious for focused UI - If a text input's font size is smaller than
16px, addmax-sm:text-base/{lh}to bump it to16pxon mobile - Never use
outline-offset-*on custom focus rings for<input>and<textarea>elements; useoutline-offset-0or omit the offset entirely - When using a 2px focus outline on
<input>or<textarea>, inset it with-outline-offset-1so it doesn't extend outside the element - Never use the conjoined input + button pattern where they share a border: use a gap between them or nest the button visually inside the input
Coding Rules
- Always include a
nameattribute on<input>,<select>, and<textarea>elements - Every
<input>,<select>, and<textarea>must have either a corresponding<label>associated viaid/for, or anaria-labelattribute - Always set an explicit
typeattribute on<button>elements:type="submit"inside forms,type="button"otherwise - Use
placeholderwitharia-labelinstead of visible<label>elements for ecommerce/checkout forms where the field purpose is obvious from context: still use section headings (e.g. "Shipping address", "Payment") to group related fields
Selects
- Use a custom chevron for consistent cross-browser styling: wrap only the
<select>and chevron ininline-grid grid-cols-[1fr_--spacing(8)](never the label); addcol-span-full row-start-1 appearance-none pr-8to the<select>; place an SVG chevron withpointer-events-none col-start-2 row-start-1 place-self-center
<svg
viewBox="0 0 8 5"
width="8"
height="5"
fill="none"
class="pointer-events-none col-start-2 row-start-1 place-self-center"
>
<path d="M.5.5 4 4 7.5.5" stroke="currentcolor" />
</svg>Checkboxes
- Use a native
<input type="checkbox"> - The styles are all applied in CSS based on the input state
- Never use JavaScript to toggle classes based on input state: use CSS states and variants exclusively
- Replace
{brand}with the appropriate brand color - Every class is required, do not omit any
- When a label is present, associate it with the input using
idandfor; otherwise give it anaria-label - To vertically center a checkbox with adjacent text, wrap it in an element with
h-lh items-centerand the matchingtext-{size}: never puth-lhon theinline-gridwrapper itself; never use top margins or manual alignment - Checkboxes should be larger on mobile: e.g.
size-5 sm:size-4
<span class="group inline-grid size-4 grid-cols-1">
<input
type="checkbox"
class="checked:border-{brand} checked:bg-{brand} indeterminate:border-{brand} indeterminate:bg-{brand} focus-visible:outline-{brand} dark:checked:border-{brand} dark:checked:bg-{brand} dark:indeterminate:border-{brand} dark:indeterminate:bg-{brand} dark:focus-visible:outline-{brand} col-start-1 row-start-1 appearance-none rounded-sm border border-gray-300 bg-white focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 dark:border-white/10 dark:bg-white/5 dark:disabled:border-white/5 dark:disabled:bg-white/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto"
/>
<svg
viewBox="0 0 14 14"
fill="none"
class="pointer-events-none col-start-1 row-start-1 size-7/8 self-center justify-self-center stroke-white group-has-disabled:stroke-gray-950/25 dark:group-has-disabled:stroke-white/25"
>
<path
d="M3 8L6 11L11 3.5"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="group-not-has-checked:opacity-0"
/>
<path
d="M3 7H11"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="group-not-has-indeterminate:opacity-0"
/>
</svg>
</span>Radio Buttons
- Use a native
<input type="radio"> - The styles are all applied in CSS based on the input state
- Never use JavaScript to toggle classes based on input state: use CSS states and variants exclusively
- Replace
{brand}with the appropriate brand color - Every class is required, do not omit any
- When a label is present, associate it with the input using
idandfor; otherwise give it anaria-label - To vertically center a radio button with adjacent text, wrap it in an element with
h-lh items-centerand the matchingtext-{size}: never puth-lhon theinline-gridwrapper itself; never use top margins or manual alignment - Radio buttons should be larger on mobile: e.g.
size-5 sm:size-4
<span class="group inline-grid size-4 grid-cols-1">
<input
type="radio"
class="checked:border-{brand} checked:bg-{brand} focus-visible:outline-{brand} dark:checked:border-{brand} dark:checked:bg-{brand} dark:focus-visible:outline-{brand} col-start-1 row-start-1 appearance-none rounded-full border border-gray-300 bg-white focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 dark:border-white/10 dark:bg-white/5 dark:disabled:border-white/5 dark:disabled:bg-white/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto"
/>
<span
class="pointer-events-none col-start-1 row-start-1 size-[round(down,40%,1px)] self-center justify-self-center rounded-full bg-white group-not-has-checked:opacity-0 group-has-disabled:bg-gray-400 dark:group-has-disabled:bg-white/25"
></span>
</span>Toggles
- Use a native
<input type="checkbox"> - The styles are all applied in CSS based on the input state
- Never use JavaScript to toggle classes based on input state: use CSS states and variants exclusively
- Replace
{brand}with the appropriate brand color - Replace
{gray}with the appropriate gray color - Every class is required, do not omit any
- Use
w-9as the default size; only adjust the width to make it larger or smaller - Toggles should be larger on mobile: e.g.
w-11 sm:w-9 - When a label is present, associate it with the input using
idandfor; otherwise give it anaria-label - Remove all
dark:classes if the site doesn't support dark mode; for always-dark sites, use only thedark:variant values as the base classes and remove thedark:prefixed versions
<div
class="group outline-{brand}-600 has-checked:bg-{brand}-600 dark:outline-{brand}-500 dark:has-checked:bg-{brand}-500 bg-{gray}-200 inset-ring-{gray}-900/5 relative inline-flex w-9 shrink-0 rounded-full p-0.5 inset-ring outline-offset-2 transition-colors duration-200 ease-in-out has-focus-visible:outline-2 dark:bg-white/5 dark:inset-ring-white/10"
>
<span
class="ring-{gray}-900/5 aspect-square w-1/2 rounded-full bg-white ring-1 shadow-xs transition-transform duration-200 ease-in-out group-has-checked:translate-x-full"
></span>
<input type="checkbox" class="absolute inset-0 size-full appearance-none focus:outline-hidden" />
</div>General
Covers: general markup rules and Tailwind CSS authoring rules that are not specific to one component.
Coding Rules
Markup
- Never apply
text-*(font size) orleading-*(line height) classes to inline elements like<span>,<a>,<strong>,<em>, or<code>: always apply them to containing block-level elements like<div>,<p>,<h1>,<h6>,<li>, or<td> - Never add redundant display classes that match an element's default display: e.g. no
blockon<div>,<p>,<h1>,<h6>; noinlineon<span>,<a>; noinline-blockon<input>,<button>,<select>; notableon<table>. This only applies to classes that don't change child layout,flex,grid,inline-flex,inline-gridare never redundant - Never apply conflicting classes for the same property on the same element without a distinguishing variant: e.g. no
outline-1 outline-2, nooutline-black/5 outline-white; keep only the intended value - Always add
role="list"to<ul>and<ol>elements unless alist-style-*class (e.g.list-disc,list-decimal) is applied
Tailwind CSS
- Always apply
antialiasedto the root element - Always apply
isolateto the main app container (the element that getsinertwhen dialogs open): prevents z-index conflicts with portalled elements - Place
@importstatements with remote URLs (http/https) orurl()at the very top of the CSS file, before@import "tailwindcss": but after@charsetif present - Add
tabular-numsto elements that display numbers, especially values that change over time (e.g. counters, timers, prices, stats): prevents layout shift as digits update - Never use
mt-*/mb-*/ml-*/mr-*/mx-*/my-*between flex/grid children: usegap-*on the parent instead - Prefer
size-{n}overh-{n} w-{n}when both values are the same - Prefer shorthand classes over split axis classes:
p-8notpx-8 py-8,inset-0notinset-x-0 inset-y-0; keep them split when a variant overrides one axis, e.g.p-8 md:px-10 - Use
--spacing(…)for arbitrary spacing values:--padding: --spacing(2)not--padding: 8px - Never use
calc(var(--spacing)*…): use--spacing(…)instead - Never use
theme(spacing.…): use--spacing(…)instead - Never use
theme()for colors or other tokens in arbitrary values: use CSS variables instead;[stop-color:var(--color-emerald-500)]not[stop-color:theme(colors.emerald.500)] - Use
remfor arbitrary font sizes:text-[0.8125rem]nottext-[13px] - Pixels are fine for properties that use pixels natively in Tailwind: e.g.
border-*,outline-* - Use theme variable references for arbitrary radii:
--radius: var(--radius-xl)not--radius: 16px - Never use named line-height values like
tight,snug,relaxed: not inleading-tight, not intext-6xl/tight; only use spacing scale values (e.g.leading-6,text-sm/5), and only when a custom line height is specifically required - Never use inline
styleattributes for static CSS properties that lack a utility class: use arbitrary property syntax instead;class="[animation-delay:300ms]"notstyle="animation-delay: 300ms" - Set CSS variables using arbitrary property syntax, not inline styles:
class="[--padding:--spacing(3)]"notstyle="--padding: --spacing(3)"(unless the value is dynamic) - For dynamic values, prefer CSS variables over setting CSS properties directly in
styleattributes:class="w-(--progress)" style="--progress: 72%"notstyle="width: 72%"; name the variable descriptively relative to the context - Prefer bare values over arbitrary values for integers and multiples of
0.25:z-999notz-[999] - Prefer bare opacity modifiers on color utilities:
bg-neutral-950/2notbg-neutral-950/[0.02]; use[…]only for non-0.25-increment values - Negate
hiddenwith a single conditional variant instead of settinghiddenand conditionally re-applying the display class:flex items-center gap-x-6 max-lg:hiddennothidden lg:flex lg:items-center lg:gap-x-6;not-dark:hiddennothidden dark:block - Prefer
not-*variants over setting a base value and conditionally overriding it:group-not-has-checked:opacity-0notgroup-has-checked:opacity-100 opacity-0; placenot-directly before the state being negated, notnot-group-has-checked:…(would trigger without agroupparent) orgroup-has-not-checked:…(would match any unchecked element) - Use bare values in variants over arbitrary values in variants:
data-closed:…notdata-[closed]:…,group-data-open:…notgroup-data-[open]:… - Always use classes like
min-h-dvh/svh/lvh, nevermin-h-screen(screenis deprecated) - Always use
bg-linear-*for gradients, neverbg-gradient-*(deprecated) - Use
shrink-*notflex-shrink-*,grow-*notflex-grow-*(deprecated) - Prefer whole-number ratios in arbitrary grid/flex values:
grid-cols-[21fr_19fr]notgrid-cols-[1.05fr_0.95fr]; multiply all values by the same factor to eliminate decimals - Prefer
@utility my-utility { … }over plain class selectors (.my-utility { … }) for reusable styles: utilities work with all Tailwind variants (hover:my-utility,lg:my-utility) - Use
@utility my-utility-* { … }with--value()and--modifier()for parameterized utilities that accept arguments - Use
@variant the-variant { … }inside@utilitydefinitions to apply an existing variant: don't manually write the media query or selector - Use
@custom-variantto define new custom variants when the built-in set doesn't cover the case - Never nest
@utilityinside another at-rule like@mediaor@supports: move the at-rule inside the@utilityblock instead
Headers
Covers: site headers, navigation bars, top bars, logos, mobile menus, hamburger menus, and header CTAs.
Design Rules
- Always wrap the main logo in an
<a href="/">witharia-label="Homepage" - Navbar button actions must always feel secondary to the hero's primary CTA: use ghost, outline, subtle, or a smaller solid button; matching the hero's color is fine if the navbar button is noticeably smaller
Heading Groups
Covers: headline, subheadline, and optional eyebrow groups at the top of marketing or landing page sections.
A heading group is a headline and subheadline (and optional eyebrow) at the top of a marketing or landing page section, e.g. the title and description above a feature grid, team grid, pricing table, testimonial section, CTA, or hero. These rules apply to promotional/marketing page sections only, not to blog posts, articles, documentation, or editorial content.
- Never constrain the width of a heading group wrapper: no
max-w-*, nomax-lg:max-w-*, no width constraints of any kind on the wrapper<div>. Always constrain each text element (headline, subheadline) individually withmax-w-[*ch]directly on the element,text-base→max-w-[56ch],text-lg→max-w-[48ch],text-xl→max-w-[40ch],text-2xl,text-3xl→max-w-[40ch],text-4xl→max-w-[35ch],text-5xl→max-w-[30ch],text-6xl→max-w-[24ch],text-7xl→max-w-[20ch].
Example:
<div class="/* never add a max width here */">
<h2 class="mx-auto max-w-[35ch] text-4xl font-semibold tracking-tight text-balance">…</h2>
<p class="mx-auto mt-6 max-w-[48ch] text-lg text-pretty text-gray-600">…</p>
</div>- Always use a left-aligned layout for heading groups when the subheadline exceeds ~120 characters (~3 lines when centered)
- ⚠️ ask-user if a centered layout is requested but the subheadline exceeds ~120 characters: offer a rewritten version that fits; only center if the user accepts the shorter copy
Icons
Covers: SVG icons, Heroicons, inline checkmarks, icon buttons, icon sizing, and icon alignment with text.
Design Rules
- Never generate raw SVG icons: import from the project's existing icon library, or use Heroicons if no library is established
- Never wrap icons in decorative containers (colored squares, circles with backgrounds): use the icon directly
- Never scale icons:
viewBox="0 0 24 24"always usessize-6,viewBox="0 0 20 20"usessize-5,viewBox="0 0 16 16"usessize-4; if the icon looks too small, use a different icon set, don't increase the size class - Always use 16px/micro icons (
size-4) when inline withtext-smtext: checklists, feature items, comparison tables, inline labels; only use 20px/mini icons (size-5) for navigation list icons - Icons next to a text group (label + supporting text): align the icon with the first line/label using
items-startoritems-baseline, neveritems-centeron the group - Application UIs (dashboards, settings, admin, sidebar nav, forms): only use Heroicons Micro (16px,
size-4); never use 20px/mini or 24px/outline icons in application UIs
Coding Rules
- Use
size-{n} h-lhon SVG icons to vertically center them with adjacent text; set thefont-sizeon a wrapper element instead of using top margins or manual alignment - Use
fill-{color}for filled icons andstroke-{color}for stroked icons: never usetext-{color}withcurrentColor(legacy v2 hack) - Always add
shrink-0to icons inside flex containers
Images
Covers: photos, thumbnails, screenshots, app mockups, product images, media frames, and image borders/outlines.
Design Rules
- Never use borders on photos or thumbnails: use
outline-1 -outline-offset-1 outline-black/5oroutline-black/10if the image needs a visible edge - Use
outline-1 -outline-offset-1 outline-black/5oroutline-black/10on light surfaces; useoutline-white/10on dark surfaces for screenshots and app UI mockups
Coding Rules
- Use
alt=""on images when the subject is identified by adjacent visible text
Interactivity
Covers: hover states, transitions, animations, active states, and behavior on clickable and non-clickable elements.
- Never add
hover:*states to non-interactive elements: reserve for buttons, links, and other clickable elements - Never add
transition-*for hover color/background changes: reserve transitions for elements that move or transform
Landing Pages
Covers: landing pages, marketing pages, stacked page sections, heroes, CTAs, pricing sections, feature sections, and full-page consistency.
- Reuse the same primary/secondary button styling across the entire page: if the hero uses a link-style secondary, every other section with a secondary action (CTA, pricing, etc.) must also use a link-style secondary
- Reuse the same font treatment (size, weight, color) when the same or similar idea appears multiple times on a page: match the existing instance exactly
- Use the same container style across the entire page: once a container style is established (outline, tinted, etc.), all subsequent containers should match
- Use the same border radius for all containers at the same level: panels, cards, and other sibling containers on a page should share a consistent radius
- Use the same column
gap-*value across all multi-column page sections: card grids, split layouts, and any other two-column or multi-column section must share the same gap; check existing sections before adding a new one and match the value already in use - Never place a centered/center-constrained layout directly below a left-aligned layout: use left-aligned instead, unless: the section above ends with full-width containers that create a natural divide, a background color change separates them, or a visible divider sits between
- Never have more centered heading groups than left-aligned ones on a landing page: centered headings work best for hero sections, CTAs, and sections with symmetrical content beneath (e.g. centered pricing cards, logo clouds); default to left-aligned for feature grids, split layouts, and content-heavy sections
Login Pages
Covers: login, sign-in, sign-up, authentication, password reset, and account access pages.
- Never use light gray or other light-tinted backgrounds (e.g.
bg-gray-50,bg-gray-100,bg-slate-50) on login/sign-in pages: use solid white (bg-white) or dark (bg-gray-900,bg-gray-950,bg-black), unless the form content is wrapped in a distinct panel or card
Logo Clouds
Covers: logo grids, customer logos, partner logos, trust bars, client rows, and collections of brand marks.
- Always distribute logos evenly across rows when wrapping: never allow an unbalanced last row (e.g. 5 on one row and 1 on the next); use a grid or layout that splits logos as evenly as possible across all rows (e.g. 3+3 instead of 5+1 for 6 logos)
- Logo clouds directly beneath a hero are an extension of the hero: match the hero's alignment; left-aligned hero → left-aligned logo cloud label and logos
Navigation
Covers: sidebar nav, header nav, mobile menus, tabs, tab bars, vertical menus, active states, and current-page indicators.
- Every app must have a mobile navigation menu on small screens, regardless of whether the desktop nav is in a header or sidebar: use a dialog or disclosure panel with a hamburger toggle; hide the desktop nav with
hidden lg:flex(header) orhidden lg:block(sidebar) and show the mobile menu belowlg: - Never use a high-contrast or primary-color background for active nav items: use darker text color, a soft/muted background, or both
- Never change
font-weightbetween nav item states (default, hover, active): use color and background changes only - Horizontal menus (tabs, tab bars, pill navs) must never overflow the parent container: use horizontal scrolling when items don't fit
- Never use icons in top header horizontal navigation links: use text-only links
- When centering nav links on the page (not just between side items), use a three-section flex layout:
<div class="flex flex-1 items-center">for the left section (logo), the nav links in their natural width (noflex-1), and<div class="flex flex-1 items-center justify-end">for the right section (actions). The matchingflex-1gutters force the centered group to the true page center. Apply the same pattern when centering a logo: keep the logo in its natural width and useflex-1on the side sections to center it on the page rather than between the surrounding items.
Pagination
Covers: pagination, page number links, previous/next buttons, and paged navigation controls.
- Hide page numbers on mobile when pagination includes both page numbers and previous/next buttons
Related skills
FAQ
What does the ui-design skill control?
ui-design steers agent-generated interfaces toward consistent typography, spacing, color, hierarchy, and component choices. The goal is polished, accessible, on-brand screens instead of default unstyled markup.
When should developers invoke ui-design?
ui-design fits frontend build tasks where agent output needs visual polish—new dashboards, forms, or landing sections—before code review or when refactoring rough UI into a coherent design language.
Does ui-design replace a frontend framework skill?
ui-design complements framework skills by focusing on visual design decisions. Routing, state management, and API integration still belong to frontend or backend skills in the same agent session.