Taste Skill: 13 anti-slop frontend skills that turn AI tells into countable rules
Leonxlnx/taste-skill
One MIT repo holding 13 skills: ten that output code and three that output reference images only, all installed into Claude Code / Codex / Cursor with a single npx skills add. The default design-taste-frontend v2 (experimental) is a 1,228-line SKILL.md: first the model must emit a one-line "design read", then it sets three dials (DESIGN_VARIANCE / MOTION_INTENSITY / VISUAL_DENSITY), then it implements against 14 chapters of hard rules - install the official package for corporate briefs, label aesthetic borrowings in comments, zero em-dashes anywhere on the page, eyebrow quota computed from section count, bento cells equal to content items, and finally a 50-plus box pre-flight check. The repo also ships research/laziness, a literature directory using controlled studies to explain why models cut output short.
Editor's takeThe lesson worth stealing is rules expressed as countable mechanical tests: eyebrow count ≤ ceil(sections/3), bento cells equal to content items, zero em-dashes on the page, palette families rotated across projects. Each one aims straight at the model repeating itself instead of stopping at an adjective. The repo is equally honest about its edges: v2 self-declares experimental and is still moving, §13 explicitly excludes dashboards, data tables, multi-step wizards, code editors and native mobile, and the only test in the repo guards the source-invocation semantics of the skill.sh shell helper rather than the design rules.
npx skills add https://github.com/Leonxlnx/taste-skillThirteen skills in one repo: ten write code, three only produce images
taste-skill (MIT, ~95k stars / 6.4k forks, by Leonxlnx, site tasteskill.dev) is not a single skill but a repo of thirteen: ten "implementation" skills that output code and three "image-gen" skills that output reference images only. They all live under skills/, one SKILL.md per directory, and the name: field in the frontmatter is the install name (it differs from the directory name). The npx skills add CLI scans that directory and installs them uniformly, so the code skills and the image-gen skills share one install command.
| Directory | Install name | What it does |
|---|---|---|
taste-skill | design-taste-frontend | The default main skill (v2 experimental): reads the brief, infers a design language, sets three dials, then 14 chapters of hard rules plus a pre-flight check |
taste-skill-v1 | design-taste-frontend-v1 | v1 kept as-is; pin it only if you depend on its exact behaviour |
gpt-tasteskill | gpt-taste | A stricter GPT/Codex-oriented variant: simulated Python randomisation of layouts, AIDA page structure, hard GSAP constraints |
image-to-code-skill | image-to-code | Image-first pipeline: generate a site reference image, analyse it deeply, then build the frontend to match |
redesign-skill | redesign-existing-projects | Existing projects: audit the UI first, then fix layout, spacing, hierarchy and styling without tearing it down |
soft-skill | high-end-visual-design | Soft premium feel: low contrast, whitespace, premium type, spring motion |
output-skill | full-output-enforcement | Anti-laziness: complete output, no placeholder comments, clean resumable breakpoints at the token ceiling |
minimalist-skill | minimalist-ui | Editorial product UI (Notion/Linear feel): restrained palette, clear structure |
brutalist-skill | industrial-brutalist-ui | Hard mechanical language: Swiss typography, extreme scale contrast, experimental layout (Beta) |
stitch-skill | stitch-design-taste | Google Stitch-compatible semantic design rules, including the optional DESIGN.md export format |
imagegen-frontend-web | imagegen-frontend-web | Images only: website comps (hero, landing, multi-section); the hard rule is one separate horizontal image per section |
imagegen-frontend-mobile | imagegen-frontend-mobile | Images only: iOS/Android/cross-platform screens and flows, with multi-screen consistency first |
brandkit | brandkit | Images only: brand kit boards (logo directions, palettes, type, identity applications) |
The default install name design-taste-frontend now points at v2 (experimental): v1 stays untouched in skills/taste-skill-v1/, and the CHANGELOG says plainly that you should pin it only when you depend on v1's exact behaviour. The v2 SKILL.md runs 1,228 lines across 14 main chapters plus three appendices; it is the densest file in the repo, and every hard rule discussed below comes from it.
Read the brief first, then set three dials
§0 requires the model to emit a one-line "design read" before touching code: state what page type this is, which audience it serves, what temperament language to use, and which design system or aesthetic family it leans toward. The read consumes six signal classes: page type; the temperament words the user actually typed (minimalist, Linear-style, brutalist, Apple-y, editorial); reference links and screenshots; audience (a B2B procurement review, design-sensitive consumers, or a recruiter scanning a portfolio); existing brand assets (in a redesign these are starting material, not optional input); and "quiet constraints" - accessibility-first audiences, public sector, regulated industries, trust-first commerce, children's products - which override aesthetic preference. When the brief genuinely forks, ask exactly one question, never a questionnaire; if context allows inference, state the read and move on. §0.D also lists what the model must not reach for by default: AI purple gradients, a centred hero on a dark mesh, three equal feature cards, glassmorphism on everything, infinite-loop micro-animations everywhere, Inter plus slate-900.
§1 defines three dials on a 1-10 scale, baseline DESIGN_VARIANCE: 8 / MOTION_INTENSITY: 6 / VISUAL_DENSITY: 4, with two tables. The first maps read to dials (minimalist/calm/editorial lands 5-6/3-4/2-3, premium consumer/Apple-y lands 7-8/5-7/3-4, playful/Awwwards/experimental lands 9-10/8-10/3-4, trust-first/public sector lands 3-4/2-3/4-5, and redesign-preserve is "match existing / +1 / match existing"). The second gives per-use-case presets (mainstream SaaS landing 7/6/4, agency landing 9/8/3, designer portfolio 8/7/3, editorial/blog 6/4/3). Every layout, motion and density decision in the whole document is expressed in these three variable names; inventing aliases such as LAYOUT_VARIANCE or ANIM_LEVEL is forbidden.
§2 brief-to-design-system map: if an official package exists, use it
This section splits briefs in two. If the brief reads like a corporate design system, install the official package: Microsoft/enterprise reads Fluent UI; a Google flavour reads @material/web plus Material 3 tokens; an IBM-flavoured B2B brief reads Carbon; a Shopify admin reads Polaris; Atlassian/Jira reads Atlaskit; GitHub-flavoured developer tooling reads Primer; UK public sector reads govuk-frontend; US public sector reads USWDS; a local-business quick MVP reads Bootstrap 5.3; a modern SaaS with its own components reads shadcn/ui or Tailwind v4. Three honesty clauses apply: never hand-roll a CSS replica of an official system, never import its tokens and then override nine tenths of them, and only one system per project (no Fluent React mixed with Carbon, no shadcn components dropped into a Material 3 app). If the brief reads as an aesthetic rather than a system (glassmorphism, bento, brutalism, editorial/magazine, dark tech, aurora gradients, kinetic type, Apple Liquid Glass), use native CSS plus Tailwind plus a maintained component library, and label the borrowings honestly in code comments. Appendix C is devoted to Apple Liquid Glass: Apple documents it only for Apple platforms, no official liquid-glass.css exists, every web implementation is an approximation built from backdrop-filter, layered borders and specular highlights, it must be marked as an approximation, and it needs a solid fallback for prefers-reduced-transparency.
Hard rules: pin each "AI tell" down, and make it countable where possible
The core change from v1 to v2 is that rules moved from "advice" to "hard rules with a mechanical test", where failing the test means the work is not done. The ten most representative:
| Rule | Mechanical test |
|---|---|
| Hero must fit the first viewport | Headline ≤2 lines, subcopy ≤20 words and ≤4 lines, CTA visible without scrolling, top padding ≤ pt-24, total hero text elements ≤4 (either an eyebrow or a brand strip, headline, subcopy, CTA) |
| Eyebrow quota | Count every uppercase tracking micro-label: ≤ ceil(sections/3), hero counts as 1; over quota fails Pre-Flight |
| Bento cell count | N pieces of content = N cells (3 items means 1+2 or 2+1); no empty cells in mid or tail sections, an empty cell means the plan was wrong |
| No layout-family repetition | A given layout family appears at most once per page; 8 sections need at least 4 families; consecutive left-image/right-text zigzags cap at 2 |
| Colour consistency lock | One accent colour used consistently across the page; premium-consumer briefs ban the beige+brass+espresso hex families (backgrounds #f5f1ea/#f7f5f1, accents #b08947/#b6553a, text #1a1714 and friends) and offer six rotating alternatives - a family used on the previous project must be swapped out on this one |
| Shape consistency lock | One corner system per page: all square, all 12-16px, or all-pill for interactive elements; mixing requires a written-down rule that is obeyed everywhere |
| Button and form contrast | Every CTA passes WCAG AA 4.5:1; white-on-white and transparent borderless buttons are banned; CTA labels must not wrap on desktop; one label per CTA intent per page ("Get in touch" next to "Let's talk" fails) |
| Em-dash ban | Zero em-dashes anywhere visible on the page; en-dash as a separator is equally banned; ranges use a hyphen |
| Long lists change component | More than 5 items must not use <ul> with divide-y; switch to two-column grouping, card grids, tabs, scroll-snap pills, carousel or marquee. A spec table with row-by-row border-b is the laziest default |
| Real images first | If an image-gen tool is available, generate first; otherwise use picsum seeds; otherwise leave commented placeholder slots and list the missing image positions at the end of the reply. Fake screenshots built from divs, hand-drawn decorative SVG as a default, and "text-only minimalism" are all banned |
The type rules carry the same opinionated stance: Inter is not a default (consider Geist, Outfit, Cabinet Grotesk, Satoshi, or a brand-appropriate serif first); serif is a "strongly discouraged default", "feels creative/premium/editorial" is not a reason, and the two LLM favourites Fraunces and Instrument_Serif are banned outright; emphasising a word in a headline may only use italic or bold from the same family, never a serif word inside a sans headline; when an italicised word contains y g j p q, leading-none clips the descenders, so start at leading-[1.1] and add pb-1 of clearance. Logo walls use real SVG from Simple Icons or devicon, or a generated simple monogram for a fictional brand, and they carry logos only - no industry captions such as "Vercel / hosting" printed underneath.

§9.G the em-dash ban: one binary rule
The hardest line in the document: zero em-dashes in any visible position on the page (headlines, eyebrows, pills, buttons, body copy, quotes, attributions, captions, alt text), en-dash as a separator is equally banned, date ranges (2018-2026) and money ranges (€40-80k) use a hyphen, and quote attribution uses " - " or a line break plus a smaller name. The CHANGELOG explains why this is binary rather than "use sparingly": in pre-v2 production testing the em-dash was the single most frequent AI signature, and wording like "use sparingly" was reliably ignored by models, so the rule grants no allowance at all - one occurrence in the output means the whole thing gets rewritten.
Motion discipline: Motion is the default, GSAP is only for pin and scrub
§3 sets the animation library as Motion (motion/react, the renamed Framer Motion package; the old name survives only as a legacy alias). Continuous values (pointer position, scroll progress, magnetic hover) must not be tracked with useState; they go through useMotionValue / useTransform / useScroll, because useState re-renders the entire React tree on every change and collapses on mobile. §5 ships three "canonical skeleton" code blocks: Sticky-Stack (start: "top top", pin: true, everything pinned except the last card, scale and opacity driven by the next card's ScrollTrigger scrub, useId scoping the class so two stacks cannot select each other, pin the outer element and transform the inner one, fall back to a plain list under reduced-motion), Horizontal-Pan (end: "+=" + distance, scrub: 1), and a lighter Motion-only Scroll-Reveal Stagger. §5.D bans three patterns outright: window.addEventListener('scroll'), hand-computed scroll values in React state, and requestAnimationFrame loops that touch React state. Two further rules are about attitude: "motion claimed, motion shown" - if MOTION_INTENSITY is declared above 4 the page must actually move, and if it cannot, drop the dial to 3 and ship a clean static page rather than half-broken animation; and "motion must be motivated" - every animation must be explainable in one sentence as hierarchy, narrative, feedback or state change, otherwise delete it, because "GSAP everywhere because GSAP is available" is amateur work.
§11 the redesign protocol: audit first, SEO is the top risk
A redesign starts by picking a mode: Greenfield, Redesign-Preserve (modernise without breaking the brand), or Redesign-Overhaul (new visual language over existing content); ask once if it is ambiguous. Before touching anything, record the current state: brand tokens, information architecture and the key conversion paths, which content blocks are pulling weight and which are filler, the signature interactions and copy voice to keep, the slop and performance traps to retire, the current three-dial readings of the existing site (that is the starting point, not the baseline), and the SEO baseline: pages that currently rank, meta titles, structured data, OG cards - the text says "SEO migration is the #1 redesign risk". Modernisation levers are ordered by priority and you stop as soon as the brief is satisfied: type refresh (best risk-adjusted return) → spacing and vertical rhythm → colour recalibration → motion layer → hero and key-section rebuild → wholesale replacement (only when nothing else can save it). If IA, content and SEO are all healthy, go for targeted evolution - roughly seventy per cent of the value at forty per cent of the risk; rebuild the whole site only when the visual debt is structural. URL structure, primary navigation labels, form field names and order (they break analytics and autofill), the brand wordmark, and legal/consent/cookie copy are never changed without explicit approval.
§14 the pre-flight check: 50-plus checkboxes as the last gate
Before emitting code the model must run the whole check matrix, and any box it cannot honestly tick means the work is not done. The mechanical items can literally be counted: zero em-dashes; eyebrow count ≤ ceil(sections/3); hero text elements ≤4 and top padding ≤ pt-24; navigation single-line and ≤80px on desktop; no repeated layout families; bento cells equal to content count; at most one marquee per page; no <ul> with divide-y for lists over 5 items; viewports use min-h-[100dvh] rather than h-screen; icons come only from Phosphor / HugeIcons / Radix / Tabler; motion is isolated in leaf components carrying 'use client'; useEffect animations have strict cleanup; empty, loading and error states are all present; Core Web Vitals are credibly met (LCP < 2.5s, INP < 200ms, CLS < 0.1). Attitude items sit in the same table: a one-sentence motivation for every animation, copy self-checked for broken grammar and LLM faux-profundity, and the declared motion actually moving.
The other twelve skills: one skill, one job
Three deserve their own paragraph. full-output-enforcement (output-skill) defines laziness as a hard failure: // ..., // rest of code, // TODO and // similar to above in code; "let me know if you want me to continue", "for brevity" and "the rest follows the same pattern" in prose; and structurally, "a skeleton when a full implementation was asked for" or "the head and tail with the middle skipped" are all banned. The execution flow is to count and lock the number of deliverables first, generate each one completely, then reconcile against the original request before output. Near the token ceiling it neither compresses nor skips: write to a clean breakpoint (end of a function, end of a file, end of a section) and emit [PAUSED - X of Y complete. Send "continue" to resume from: ...]. The first hard output rule of imagegen-frontend-web is "one separate horizontal image per section, always": an 8-section landing page gets 8 images, a landing page with no stated section count defaults to 6 sections and 6 images, and multiple sections are never compressed into one frame. stitch-design-taste translates the anti-slop rules into Google Stitch's semantic design language and produces a DESIGN.md as the single source of truth for Stitch screen generation; the repo ships a sample DESIGN.md. Among the rest, gpt-taste uses "simulated Python randomisation" to force the model off its first choice, high-end-visual-design is a combination engine of three temperament archetypes times three layout archetypes, and industrial-brutalist-ui makes you pick one of two archetypes - Swiss print or CRT terminal - and commit to it all the way.

research/laziness: the evidence base behind output-skill
The repo carries a research/ directory on the question "why do LLMs produce incomplete output". Four root-cause pieces: how RLHF and compute economics create a systematic brevity bias; how placeholder patterns in human code travel into models through training data; cognitive shortcuts on complex tasks; and context-window asymmetry plus consumer-tier truncation mechanics. The conclusions cite three results from a December 2025 controlled study: in a multi-part instruction-compliance experiment no model satisfied both the length requirement and all sub-instructions at once; a decoding-suboptimality experiment showed truncated outputs align closely with the model's highest-confidence solution, meaning truncation is a behavioural choice, not a decoding failure; and a 200-turn context-degradation experiment showed models retain key facts and instructions far better than assumed, so context loss is not the main cause. It also cites Microsoft Research prompt-stimulus controls: a monetary-incentive framing ("$200 tip") raised output quality and length by 45 per cent, "take a deep breath" lifted accuracy on logical tasks from 34 to 80 per cent, a stakes framing added 10 per cent, and combined stimuli reached up to 115 per cent. One further statistical analysis found a measurable December dip in output length, correlated with reduced holiday-season production in the training data. This is the literature that lets output-skill write "complete output" as a contract rather than a request.
Assessment and boundaries
The strengths are clear: rules come with mechanical tests instead of adjectives; there is an explicit rotation-memory requirement (palette families, serif faces) recording what the previous project used, which attacks the model's own repetition tendency directly; official-package-first plus "label aesthetics honestly" separates design systems from aesthetic trends and stops trends being sold as official standards; the redesign protocol names the SEO baseline as the number one risk, an engineering awareness rare in skills of this kind; and the research directory gives the anti-laziness rules a literature base. The boundaries deserve the same honesty: v2 self-declares as experimental and is still iterating, so rules will move and the API only locks at v2.0.0 stable; the declared scope is landing, portfolio and marketing pages, and §13 says outright that dashboards, data tables, multi-step wizards, code editors, native mobile and realtime collaborative UI are out of scope - when those come up the skill is supposed to say so and point at the right tools (Fluent, Carbon, TanStack, Monaco); the repo has no behavioural tests for the design rules, and the only test, tests/skill_test.sh, guards the source-invocation semantics of the skill.sh shell helper (help/list/path lookup/unknown-name return codes); the "Python-driven true randomisation" in gpt-taste is in fact a deterministic simulation seeded from prompt character count, whose job is to break the model's first choice rather than to be random; and its icon-library preference (lucide allowed only when the user names it or the project already depends on it) is a stance, not an industry consensus - where it conflicts with a project's own conventions, the project wins.
Install
# All thirteen skills in the repo at once
npx skills add https://github.com/Leonxlnx/taste-skill
# Only the default v2
npx skills add https://github.com/Leonxlnx/taste-skill --skill "design-taste-frontend"
# Pin v1 when you trust only its exact behaviour
npx skills add https://github.com/Leonxlnx/taste-skill --skill "design-taste-frontend-v1"
# Claude Code plugin marketplace: skills carry the taste-skill: namespace, so they never collide with local skills
/plugin marketplace add Leonxlnx/taste-skill
/plugin install taste-skill@taste-skill
# Or symlink install: git pull then updates every installed skill
./install.sh --codex # links into ~/.codex/skills
./install.sh --all-agents # links for both Claude Code and Codex
./install.sh --list # shows the install-name to directory mapping