3.8 KiB
Anti-AI-slop rules
Concrete, checkable rules that distinguish "designed by a human who has
shipped product" from "default LLM output." Several rules below are
auto-enforced by the daemon's lint-artifact linter — failing an
enforced rule is not a style preference, it is a regression. The
rest are guidance for agents and reviewers and are flagged inline as
"(guidance, not auto-checked)" so the contract with the linter stays
honest.
Adapted from refero_skill (MIT), tightened to match Open Design's lint surface.
The seven cardinal sins
These are the patterns the linter blocks at P0 (must-fix):
- Default Tailwind indigo as accent — exactly
#6366f1,#4f46e5,#4338ca,#3730a3,#8b5cf6,#7c3aed,#a855f7. The activeDESIGN.mdprovides--accent; use it. Indigo is the textbook AI tell. (The daemon'slint-artifactflags any of these as a solid accent; keep this list in sync withAI_DEFAULT_INDIGOinapps/daemon/src/lint-artifact.ts.) - Two-stop "trust" gradient on the hero — purple→blue, blue→cyan, indigo→pink. A flat surface + intentional type beats this every time.
- Emoji as feature icons —
✨,🚀,🎯,⚡,🔥,💡inside<h*>,<button>,<li>, orclass*="icon". Use 1.6–1.8px-stroke monoline SVG withcurrentColor. - Sans-serif on display text when the seed binds a serif — h1/h2
must use
var(--font-display), not a hardcoded Inter / Roboto /system-ui. - Rounded card with a colored left-border accent — the canonical "AI dashboard tile" shape. Drop either the radius or the left border.
- Invented metrics — "10× faster", "99.9% uptime", "3× more productive". Either pull from a real source or use a labelled placeholder.
- Filler copy —
lorem ipsum,feature one / two / three,placeholder text,sample content. An empty section is a design problem to solve with composition, not by inventing words.
Soft tells (P1 — should fix)
- Standard "Hero → Features → Pricing → FAQ → CTA" sequence with no variation (guidance, not auto-checked). This is the AI-template skeleton; introduce at least one unconventional section (testimonial wall as full-bleed quote, pricing as comparison-against-status-quo, an inline mini-product-demo).
- External placeholder image CDNs (
unsplash.com,placehold.co,placekitten.com,picsum.photos). Fragile and obvious. Use the shipped.ph-imgplaceholder class. - More than ~12 raw hex values outside
:root. Tokens were not honoured. var(--accent)used 6+ times in the rendered body. Cap at 2 visible uses per screen.
Polish tells (P2 — nice to fix)
- Sections without
data-od-id— comment mode can't target them. - Decorative blob / wave SVG backgrounds (guidance, not auto-checked) — meaningless geometry.
- Perfect symmetric layout with no visual tension (guidance, not auto-checked) — alternating density (one tight section, one breathing section) reads as intentional.
How to add soul without breaking the rules
Aim for ~80% proven patterns + ~20% distinctive choice. The 20% should live in:
- One bold visual move — a typography choice, a single color decision, an unexpected proportion.
- Voice and microcopy — a button that says "Start tracking" beats one that says "Get started".
- One micro-interaction the user will remember — a button press that moves 2px, a number that counts up.
- One detail that could only have been put there by someone who used the product (a subtle kbd shortcut hint, a status badge with product-specific phrasing).
If a reviewer screenshots the artifact and someone outside the project can identify which product it's from — you have soul. If not, you shipped a template.