Best for
- Activation Triggers
- Use Cases
- When NOT to Use
MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory/.opencode/skills/sk-design/SKILL.md
Designs, builds and reviews UI from fixed value scales, interaction guidelines, motion principles and a WCAG review pass.
Decision brief
Visual design is not talent. It is a small set of systems decisions made once, plus a handful of techniques for building hierarchy, a set of interaction details that make a screen behave correctly, and a motion model that keeps it feeling human.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory --skill ".opencode/skills/sk-design"Inspect the Agent Skill "sk-design" from https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory/blob/3d386ee21366523774d89c0aff3ebbbc8fa7ff10/.opencode/skills/sk-design/SKILL.md at commit 3d386ee21366523774d89c0aff3ebbbc8fa7ff10. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Review the “Phase Detection” section in the pinned source before continuing.
Seven steps govern the order of work on something new: start from a feature rather than a layout, work in grayscale first, treat low-fidelity artifacts as disposable, build the smallest useful version, choose each value by elimination against its two neighbours on the scale, sta…
Use when the task involves: - Building or styling any interface — web page, app screen, dashboard, landing page, single component. - Picking a concrete value: font size, spacing, padding, color, shadow, border radius, border width, opacity, duration. - Designing a color palette,…
Use when the task involves: - Building or styling any interface — web page, app screen, dashboard, landing page, single component. - Picking a concrete value: font size, spacing, padding, color, shadow, border radius, border width, opacity, duration. - Designing a color palette,…
Building new UI. The systems in Section 3 replace every ad hoc value decision; the interaction and motion references cover the behavior the values do not.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 96/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 34 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Visual design is not talent. It is a small set of systems decisions made once, plus a handful of techniques for building hierarchy, a set of interaction details that make a screen behave correctly, and a motion model that keeps it feeling human.
The single biggest cause of amateur-looking UI is picking values ad hoc — 17px here, #3B82F6 there, lighten(5%) for a hover state, 400ms because it seemed smooth. Design from a scale, always.
Boundary. This skill decides values and behavior when UI is being built, fixed, or reviewed. It is prescriptive and emits CSS. It does not measure an existing site —
sk-design-md-generatorextracts a live surface's real CSS into a measured Style Reference, and when such a reference exists its measured values win over the defaults here. See Section 7.
Use when the task involves:
Keyword Triggers: the routing vocabulary is the keyword comment above the title; it is the single list, so it is not restated here.
Skip this skill when:
sk-design-md-generator.sk-code.The dominant split is build, improve, or review, because it decides which reference loads first.
WHAT IS THE STARTING POINT?
|
+- Nothing yet -> BUILD. Systems (Section 3) + procedure. Add color-system.md for a palette,
| interaction-craft.md when implementing, motion-principles.md when animating.
|
+- A complaint -> IMPROVE. Load references/diagnosis-table.md FIRST, map symptom to cause, then apply.
|
+- Existing code -> REVIEW. Load references/review-checklist.md and run the severity-tiered pass.
A second signal decides depth: a request naming one property ("what shadow?") needs only the relevant scale, while "make this look designed" needs the hierarchy technique in Section 3 and usually the diagnosis table.
UI TASK
|
+- STEP 0: Detect build / improve / review
+- STEP 1: Score intents (top-2 when scores are close)
+- Phase 1: Choose values from the fixed scales
+- Phase 2: Establish hierarchy (weight and color before size)
+- Phase 3: Implement behavior (focus, keyboard, touch, motion)
+- Phase 4: Verify against the hard rules and contrast minimums
references/ design and behavior knowledge, loaded on intent
assets/ copy-paste starting values
references/ holds one document per routed intent; Section 5 lists them.assets/ holds tokens.css, a complete contrast-verified token set to copy in and retune.| Level | When to Load | Resources |
|---|---|---|
| ALWAYS | Every skill invocation | The scales and hard rules in this file |
| CONDITIONAL | If intent signals match | build-procedure.md, diagnosis-table.md, hierarchy.md, color-system.md, depth-and-detail.md, interaction-craft.md, motion-principles.md, ux-laws.md, review-checklist.md |
| ON_DEMAND | Only on explicit request | assets/tokens.css, assets/token-starter-set.md |
from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/diagnosis-table.md"
INTENT_MODEL = {
"DIAGNOSE": {"keywords": [("looks off", 4), ("looks amateur", 4), ("feels cheap", 4),
("cluttered", 3), ("feels plain", 3), ("unfinished", 3),
("make this look better", 4), ("improve", 2)]},
"REVIEW": {"keywords": [("review", 4), ("audit", 4), ("accessibility", 4), ("wcag", 4),
("aria", 3), ("findings", 3), ("critique", 3), ("check this ui", 4)]},
"PALETTE": {"keywords": [("color palette", 4), ("shade", 3), ("hsl", 3), ("swatch", 3),
("design tokens", 3), ("contrast ratio", 4), ("dark mode", 4),
("accent color", 3)]},
"MOTION": {"keywords": [("animation", 4), ("animate", 4), ("transition", 3), ("easing", 4),
("spring", 4), ("duration", 3), ("stagger", 3), ("motion", 3)]},
"INTERACTION": {"keywords": [("focus ring", 4), ("keyboard", 4), ("touch target", 4),
("hit area", 4), ("input", 3), ("form", 3), ("tooltip", 3),
("dropdown", 3), ("hover state", 3), ("mobile", 2)]},
"HIERARCHY": {"keywords": [("hierarchy", 4), ("draws the eye", 4), ("competing", 3),
("de-emphasize", 4), ("primary action", 4), ("destructive", 3),
("emphasis", 3), ("label", 3), ("stand out", 3)]},
"DEPTH": {"keywords": [("shadow", 4), ("drop shadow", 4), ("elevation", 4), ("depth", 3), ("raised", 3),
("inset", 3), ("typeface", 3), ("letter-spacing", 3),
("image", 3), ("photo", 3), ("grid", 3)]},
"UX_LAWS": {"keywords": [("too many options", 4), ("overwhelming", 4), ("cognitive load", 4),
("fitts", 4), ("hick", 4), ("miller", 4), ("doherty", 4),
("progressive disclosure", 4), ("feels slow", 3), ("onboarding", 2)]},
"PROCEDURE": {"keywords": [("where do i start", 4), ("design a new", 4), ("from scratch", 3),
("grayscale", 4), ("wireframe", 3), ("mockup", 3),
("how much white space", 4), ("which value", 3)]},
"SCALES": {"keywords": [("spacing", 4), ("font size", 4), ("type scale", 4),
("padding", 3), ("border radius", 3), ("line-height", 3),
("font weight", 3)]},
}
RESOURCE_MAP = {
"DIAGNOSE": ["references/diagnosis-table.md"],
"REVIEW": ["references/review-checklist.md"],
"PALETTE": ["references/color-system.md", "assets/token-starter-set.md"],
"MOTION": ["references/motion-principles.md"],
"INTERACTION": ["references/interaction-craft.md"],
"DEPTH": ["references/depth-and-detail.md"],
"HIERARCHY": ["references/hierarchy.md"],
"UX_LAWS": ["references/ux-laws.md"],
"PROCEDURE": ["references/build-procedure.md"],
"SCALES": [], # the scales live in SKILL.md Section 3; no extra load needed
}
LOAD_LEVELS = {
"DIAGNOSE": "STANDARD", "REVIEW": "STANDARD", "PALETTE": "STANDARD",
"MOTION": "STANDARD", "INTERACTION": "STANDARD", "DEPTH": "STANDARD",
"HIERARCHY": "STANDARD", "UX_LAWS": "STANDARD", "PROCEDURE": "STANDARD",
"SCALES": "MINIMAL",
}
UNKNOWN_FALLBACK_CHECKLIST = [
"Confirm whether the UI is being built, improved, or reviewed",
"Confirm which surface is in scope (page, screen, or one component)",
"Name the specific complaint or the specific value that needs deciding",
"Confirm whether an existing design system or measured reference already fixes values",
]
AMBIGUITY_DELTA = 1
def _guard_in_skill(relative_path: str) -> str:
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() != ".md":
raise ValueError(f"Only markdown resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def discover_markdown_resources() -> set[str]:
docs = []
for base in RESOURCE_BASES:
if base.exists():
docs.extend(path for path in base.rglob("*.md") if path.is_file())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def get_routing_key(task, intents: list[str]) -> str:
override = str(getattr(task, "routing_key", "")).strip().lower()
if override:
return override
return (intents[0] if intents else "unknown").lower()
def classify_intents(user_request, task=None):
text = (user_request or "").lower()
scores = {intent: 0 for intent in INTENT_MODEL}
for intent, cfg in INTENT_MODEL.items():
for keyword, weight in cfg["keywords"]:
if keyword in text:
scores[intent] += weight
ranked = sorted(scores.items(), key=lambda pair: pair[1], reverse=True)
primary, primary_score = ranked[0]
if primary_score == 0:
return ("SCALES", None, scores)
secondary, secondary_score = ranked[1]
if secondary_score > 0 and (primary_score - secondary_score) <= AMBIGUITY_DELTA:
return (primary, secondary, scores)
return (primary, None, scores)
def route_ui_craft_resources(user_request, task=None):
inventory = discover_markdown_resources()
primary, secondary, scores = classify_intents(user_request, task)
intents = [primary] + ([secondary] if secondary else [])
routing_key = get_routing_key(task, intents)
loaded, seen = [], set()
def load_if_available(relative_path: str):
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
if max(scores.values() or [0]) < 0.5:
load_if_available(DEFAULT_RESOURCE)
return {
"routing_key": routing_key,
"intents": intents,
"intent_scores": scores,
"load_level": "UNKNOWN_FALLBACK",
"needs_disambiguation": True,
"disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
"resources": loaded,
}
for intent in intents:
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
return {
"routing_key": routing_key,
"intents": intents,
"intent_scores": scores,
"load_level": LOAD_LEVELS.get(primary, "STANDARD"),
"resources": loaded,
}
Pick from these lists. Never invent a value that is not on one.
Base 16px, built from factors and multiples of it:
4 8 12 16 24 32 48 64 96 128 192 256 384 512 640 768
Tight at the small end, spreading out at the large end. No two adjacent values may be closer than about 25% — that is what makes the choice obvious. A linear "multiples of 4" scale fails, because it does not help anyone decide between 120px and 124px.
Use it for margin, padding, width, height, icon sizes and border width — everything spatial. Fix a small set of opacity values too (.05 .1 .2 .4 .6 .8) for disabled states, overlays and hover tints, rather than eyeballing a slider each time. Same logic as the other scales: decide once, reuse everywhere.
12 14 16 18 20 24 30 36 48 60 72
Not a modular scale built from a ratio. Ratios produce fractional pixel values that round inconsistently across browsers, and they are too sparse for interface density. Hand-picked values, chosen for how they feel, win instead.
Units: px or rem only. Never em. em is relative to the current font size, so .875em inside a 1.25em parent computes to 17.5px — a value not on the scale. The scale silently stops existing.
Two weights is enough:
Nothing below 400 in UI. To de-emphasize, use a lighter color or a smaller size, never a lighter weight. Weight must also not change on hover or selection, because the width change shifts the layout.
A five-swatch palette generator gives nowhere near enough colors.
Name them 100 (lightest) through 900 (darkest), base 500.
Build the scale in this order: pick 500 first; for a primary or accent it should be a shade that works as a button background. Then find the edges — 900 is usually the text color and 100 a background tint, and an alert component uses both, so design one and read the two values off it. Then fill 700 and 300 as the perfect compromise between their neighbours, then 800 600 400 200 the same way.
Write colors as HSL, not hex. hsl(220, 95%, 34%) and hsl(220, 65%, 61%) are visibly related; #03369E and #507DD7 are not.
Never generate shades at runtime with lighten() or darken(). That is how a project ends up with 35 slightly different blues.
Full construction method — base selection, saturation at the ends, hue rotation, dark mode, contrast escape hatches — is in references/color-system.md.
0 1px 3px hsla(0,0%,0%,.2) /* barely raised - buttons */
0 4px 6px hsla(0,0%,0%,.2) /* dropdowns */
0 5px 15px hsla(0,0%,0%,.2)
0 10px 24px hsla(0,0%,0%,.2)
0 15px 35px hsla(0,0%,0%,.2) /* modals */
Choose by asking where on the z-axis does this sit?, not what shadow looks nice?. Closer to the user means more attention. Shrinking a button's shadow on :active makes it feel pressed. Growing a list item's shadow when it is picked up for drag-to-reorder does the reverse — it reads as "now above its siblings" and doubles as the drag affordance.
Every shadow in a project shares one offset direction, because there is one light source. references/depth-and-detail.md carries two refined alternatives — a two-part cast-plus-contact scale and a layered three-part set — plus the rule for tinting shadow color on non-white surfaces and the full six-layer button anatomy. The three systems are parallel and not compatible: pick one per project and never mix them, or elevation stops being readable.
Line-height is inversely proportional to font size, and proportional to line width:
1.5 to 21 is fineLine length: 45 to 75 characters, which is max-width: 20em to 35em. This applies to the paragraph even when its container is wider. Mixed widths in one content area look more polished, not less.
em is correct here — measure should scale with the text it wraps. The "never em" rule is scoped to the type scale, where em compounds through nesting. Do not "fix" this.
Pick one and stay consistent. Small radius reads neutral, large reads playful, none reads serious or formal. Mixing square and rounded corners in one interface always looks worse. For nested elements, inner radius equals outer radius minus the padding between them.
Timing is a scale like the others, and consistency across it outranks the perfect value for any one element.
120-180ms press, hover, direct feedback
180-260ms small state change: toggle, dropdown, tooltip, tab
up to 500ms layout transition: modal, drawer, accordion
300ms is the ceiling for anything the user initiated. Similar elements use identical values. The full model — easing curves, springs, staging, and when not to animate at all — is in references/motion-principles.md.
Seven steps govern the order of work on something new: start from a feature rather than a layout, work in grayscale first, treat low-fidelity artifacts as disposable, build the smallest useful version, choose each value by elimination against its two neighbours on the scale, start with too much white space and trim, and design at about 400px before relaxing to a large screen.
Full steps with their reasoning: references/build-procedure.md. Load it when starting something new; a value question does not need it.
Everything on screen sits in a pyramid: primary, secondary, tertiary. When everything competes, the UI reads as noise. This is what makes a design look designed, not styling.
Four rules carry most of it:
The full method — action and destructive treatment, label suppression, the weight-versus-contrast trade, and why visual hierarchy may disagree with document hierarchy — is references/hierarchy.md.
Correct values do not make a screen behave correctly. Three references carry the rest, and each has an always-true core worth holding in mind before loading it.
| Reference | Always-true core |
|---|---|
build-procedure.md | Feature before layout, grayscale before color, mobile before desktop, and every value chosen against its two neighbours. |
hierarchy.md | Rank every element before styling any of them. Soften the competition rather than amplifying the primary. |
interaction-craft.md | Focus rings are box-shadow, not outline. Guard hover with @media (hover: hover). Inputs are 16px minimum or iOS zooms. No dead space between adjacent targets. |
motion-principles.md | Entrances ease-out, exits ease-in, gestures use springs, linear is only for progress. One focal point at a time. Some things should not animate at all. |
ux-laws.md | Respond within 400ms or fake it honestly. Chunk into groups of five to nine. Expand hit areas with padding, not a bigger box. One element may be the exception. |
review-checklist.md | Accessibility findings first, every finding with a file, a line and a fix. |
:active state needs a scale transform, or the element feels unresponsive under a finger.diagnosis-table.md for an improve task, review-checklist.md for a review. Changing UI from a vague complaint without mapping it to a cause is a guess.em for the type scale. px or rem. em compounds through nesting and silently produces values that are not on the scale. The exception is line length (max-width in em), where measure should scale with its own text.lighten() or darken(). Define every shade up front, or the palette drifts into dozens of near-identical colors.max-width and shrink only when the screen is actually smaller — a login card must not be wider at medium screens than at large.outline: none with no visible replacement is a serious accessibility defect. Replace it with a box-shadow ring, which respects border radius.references/color-system.md, but changing a brand color is the operator's decision.tokens.css, how to retune it, and the rule that components reference roles rather than raw ramps.A UI task is complete when:
DESIGN.md Style Reference. Any of these outranks this skill's defaults.sk-design-md-generator measures a live site's real CSS into a v3 Style Reference. It is the reading half of the pair; this skill is the writing half. When a Style Reference exists for the surface, its measured values are ground truth and this skill supplies only what the reference left undecided.sk-code implements the result. Hand it the chosen values, not adjectives.system-spec-kit owns packet documentation and continuity when the work is tracked.sk-design-md-generator/references/design-knowledge/numeric-design-laws.md records type ratios, a short spacing scale and motion bands as targets for reading a measured surface. This skill decides those values for a surface that does not exist yet, and on three of them the two would appear to disagree if direction were ignored.
They do not. That document reports; this one decides; a measurement outranks a default for the surface it covers. Both sides now state the reconciliation — its Section 1, and references/motion-principles.md Section 5 here.
Section 2 governs what loads. This skill ships no scripts: every decision is a judgment, not an automated transform. Related skills are named in Section 7.
Original notes derived from four public sources, captured 2026-08-28. None of their text is reproduced verbatim.
Frequently asked questions
Visual design is not talent. It is a small set of systems decisions made once, plus a handful of techniques for building hierarchy, a set of interaction details that make a screen behave correctly, and a motion model that keeps it feeling human.
The source record exposes this install command: npx skills add https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory --skill ".opencode/skills/sk-design". Inspect the command and pinned source before running it.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
prowler-cloud/prowler
PostgreSQL indexing best practices for Prowler: index design, partial indexes, partitioned table indexing, EXPLAIN ANALYZE validation, concurrent operations, monitoring, and maintenance. Trigger: When creating or modifying PostgreSQL indexes, analyzing query performance with EXPLAIN, debugging slow queries, reviewing index usage statistics, reindexing, dropping indexes, or working with partitioned table indexes. Also trigger when discussing index strategies, partial indexes, or index maintenance
oaustegard/claude-skills
Generate hierarchical _FEATURES.md files that describe what a codebase DOES from a user/consumer perspective, anchored to source symbols via tree-sitting. Supports large complex codebases through feature-driven decomposition into sub-feature files. Uses a multi-pass synthesis: orientation → detail → overview rewrite. Use when someone says "what does this do", "document features", "feature inventory", "_FEATURES.md", or needs to understand a codebase's purpose before modifying it. Complements tre