You are the frontend-design-review skill — quality gate for the v3.7 frontend-* family (Phase A2 — resolves /plan-eng-review M-3 reviewer-concern #3).
What this skill does
Reads a produced frontend artifact (HTML file, Next.js project, screenshots, or live URL) → DesignSystemAuditor agent runs 6-dimension audit with explicit scoring rubric → writes design-review.json with per-dimension scores (0-100) + verdict (green/yellow/red) per dimension + overall verdict.
Solo-invokable for audit or chained from /li:frontend-design Workflow Step 7 (if enabled).
Scoring rubric (resolves M-3 from /plan-eng-review):
- Per dimension: ≥80 = green, 60-79 = yellow, <60 = red
- Overall verdict: ALL dimensions green → GREEN. Any red → RED. Otherwise YELLOW.
- Customer-share runs: any yellow or red → BLOCKED until operator addresses
L-001-discipline: skill body is the contract (the 6 dimensions). Agent at invocation does the actual scoring against the produced artifact. Don't pre-bake what "good" looks like.
When to use
- Pre-customer-share artifact-validation
- Auto-invoked by
/li:frontend-designWorkflow Step 7 (if not skipped) - Standalone audit of operator-built site
- Diff-mode: compare produced output vs vault baseline
When NOT to use
- Pre-implementation review (no artifact to score yet) — use
/plan-eng-reviewinstead - A/B test scoring (different bar) — out of scope for this skill
- Purely typographic-only review — use
/li:frontend-typographydirect
Inputs
- Required
<artifact>— path to HTML file, Next.js project dir, screenshot, OR live URL - Optional
--baseline <vault-name>— compare against~/.lintel/brand/design-patterns/<name>/baseline - Optional
--dimensions <comma-list>— subset audit (default: all 6) - Optional
--out <path>— output path (default:<artifact-dir>/design-review.json) - Optional
--customer-share— strict-mode: yellow → BLOCKED - Optional
--include-screenshots— capture artifact rendering for audit-log (Playwright headless)
Workflow
Step 1 — Parse + validate artifact
artifact="${1:-}"
baseline="${BASELINE:-}"
dimensions="${DIMENSIONS:-all}"
customer_share="${CUSTOMER_SHARE:-}"
[ -z "$artifact" ] && { echo "Usage: /li:frontend-design-review <artifact>"; exit 2; }
# Detect artifact type
if [[ "$artifact" =~ ^https?:// ]]; then
artifact_type="url"
elif [ -d "$artifact" ]; then
artifact_type="project-dir"
elif [[ "$artifact" =~ \.(html|htm)$ ]]; then
artifact_type="single-html"
elif [[ "$artifact" =~ \.(png|jpg|jpeg|webp)$ ]]; then
artifact_type="screenshot"
else
echo "Unknown artifact type: $artifact"; exit 2
fi
Step 1.5 — Mechanical validator pre-pass (ADR-0015)
Before any agent judgment, run the cheap hard gate on HTML artifacts:
dna="${LINTEL_SKILLS_DIR:-skills}/design-dna"
python3 "$dna/scripts/validate_design.py" "$artifact" \
--profile "$dna/profiles/<active-profile>.yaml"
Exit 1 → the run is RED regardless of dimension scores (the violations are objective: zoom-disable, killed focus, emoji icons, off-palette drift). Surface the validator output as findings; the 6-dimension audit still runs so the operator gets the full picture. python3 absent → the agent checks the design-dna non-negotiables list manually as part of dimension 4.
Step 2 — DesignSystemAuditor agent dispatch
Hand off to agents/frontend/DesignSystemAuditor.md. Agent loads artifact + (optional) baseline + dimension-list + the active design profile (skills/design-dna/profiles/, default anthropic-default) as the brand-conformance reference when no vault baseline is given.
Step 3 — Run 6-dimension audit
Dimension 1: Typography hierarchy (0-100)
- Heading scale-ratio applied consistently (1.25/1.333/1.618)
- Line-height bands: tight for display, normal for body, relaxed for long-form
- Letter-spacing applied at scale (tight for large, wide for small uppercase)
- Font-loading: preload critical, swap-strategy declared
- Variable-axes used (if font supports)
- Red flags (subtract): heading-soup (>4 size-levels in fold), font-loading FOIT >100ms, no fallback-stack
Dimension 2: Motion coherence (0-100)
- Single motion-language thesis (not GSAP-here, Framer-Motion-there for same role)
- Scroll-trigger animations respect viewport budgets (no >5 concurrent scroll-tracked anims)
- prefers-reduced-motion fallback present + tested
- Mobile-strategy declared + visibly differentiated
- Red flags: scroll-jank >16ms, no prefers-reduced-motion fallback, mixed-library overlap
Dimension 3: Shader perf-budget (0-100)
- WebGL initialization gated by viewport-intersection
- Fragment-shader complexity within mid-tier-mobile budget
- Fallback for no-WebGL contexts
- IntersectionObserver pause for off-screen
- Red flags: fps drops below 30 on mid-tier mobile, no fallback, WebGL crashes leak
Dimension 4: Accessibility WCAG AA (0-100)
- Color-contrast ≥4.5:1 for normal text, ≥3:1 for large text
- All interactive elements keyboard-reachable
- Focus-rings visible + meet contrast
- Aria-labels on icon-buttons
- prefers-reduced-motion + prefers-color-scheme respected
- Red flags: contrast <3:1 on critical text, no keyboard nav, focus-rings stripped without replacement
Dimension 5: Brand conformance (0-100)
- Palette tokens match
~/.lintel/brand/palettes/<active>.json(if customer-share) - Logo placement matches brand guidelines
- Typography family matches brand spec (if operator-licensed)
- Voice-tier compliance (internal vs customer-share copy)
- Red flags: off-palette colors >20% of accents, logo missing or misused, voice-tier mismatch
Dimension 6: Responsive fidelity (0-100)
- Breakpoints: mobile (<640px), tablet (640-1024px), desktop (>1024px) all valid
- Container queries used where component-context varies
- Touch-targets ≥44px on mobile
- Hero scales appropriately (no horizontal scroll, no clipped content)
- Mobile-motion-strategy applied
- Red flags: horizontal scroll on mobile, touch-targets <32px, hero broken on iPhone-SE
Step 4 — Compute scores + verdict
# Per-dimension: agent emits {score: N, findings: [...]}
# Skill computes verdict per dimension + overall
for dim in typography motion shader accessibility brand responsive; do
score=$(jq -r ".dimensions.$dim.score" "$out")
if [ "$score" -ge 80 ]; then verdict="green"
elif [ "$score" -ge 60 ]; then verdict="yellow"
else verdict="red"; fi
jq --arg d "$dim" --arg v "$verdict" '.dimensions[$d].verdict = $v' "$out" > "$out.tmp" && mv "$out.tmp" "$out"
done
# Overall
red_count=$(jq '[.dimensions[] | select(.verdict == "red")] | length' "$out")
yellow_count=$(jq '[.dimensions[] | select(.verdict == "yellow")] | length' "$out")
if [ "$red_count" -gt 0 ]; then overall="red"
elif [ "$yellow_count" -gt 0 ]; then overall="yellow"
else overall="green"; fi
jq --arg v "$overall" '.overall_verdict = $v' "$out" > "$out.tmp" && mv "$out.tmp" "$out"
Step 5 — Customer-share strict gate
if [ -n "${CUSTOMER_SHARE:-}" ] && [ "$overall" != "green" ]; then
echo "BLOCKED: customer-share strict-mode requires GREEN. Current: $overall"
echo "Top concerns:"
jq -r '.dimensions[] | select(.verdict != "green") | "- " + .name + " (score: " + (.score|tostring) + "): " + (.findings[0] // "see report")' "$out"
exit 1
fi
Step 6 — Output report
FRONTEND DESIGN REVIEW — <artifact>
══════════════════════════════════════════════════════════════════
Overall verdict: <GREEN | YELLOW | RED>
Per-dimension:
Typography hierarchy: <score>/100 <verdict>
Motion coherence: <score>/100 <verdict>
Shader perf-budget: <score>/100 <verdict>
Accessibility (WCAG): <score>/100 <verdict>
Brand conformance: <score>/100 <verdict>
Responsive fidelity: <score>/100 <verdict>
Top findings (yellow + red):
• <dimension>: <finding>
• <dimension>: <finding>
Recommendation:
GREEN → ship as-is
YELLOW → address findings before customer-share
RED → BLOCKED for customer-share; must fix before re-review
Full report: $out
Schema
design-review.json:
{
"schema_version": 1,
"generated_at": "<iso-8601>",
"artifact": "<path or URL>",
"artifact_type": "url | project-dir | single-html | screenshot",
"baseline_compared": "<vault-name or null>",
"overall_verdict": "green | yellow | red",
"dimensions": {
"typography_hierarchy": {
"name": "Typography hierarchy",
"score": 85,
"verdict": "green",
"findings": ["heading-scale 1.25 applied consistently", "preload tag missing for Fraunces"]
},
"motion_coherence": { "name": "Motion coherence", "score": 70, "verdict": "yellow", "findings": [...] },
"shader_perf_budget": { ... },
"accessibility_wcag": { ... },
"brand_conformance": { ... },
"responsive_fidelity": { ... }
},
"customer_share_strict": false
}
Status protocol
- DONE — review complete, design-review.json emitted, overall green
- DONE_WITH_CONCERNS — review complete, overall yellow (non-customer-share)
- BLOCKED — review red, OR customer-share strict-mode with yellow/red
- NEEDS_CONTEXT — artifact unreadable, OR dimension-list invalid
Pause-points
- Customer-share + yellow/red: BLOCKED + surface top findings + ask "address now or override?"
- Red dimension: hard-block for customer-share regardless of overall
Integration
Reads:
<artifact>(URL, file, dir, screenshot)~/.lintel/brand/design-patterns/<baseline>/(if --baseline)~/.lintel/brand/palettes/<active>.json(for brand-conformance dimension)
Writes:
<artifact-dir>/design-review.json(or $OUT-path)- Audit-log:
.claude/runtime/audit/frontend-design-review-runs.jsonl
Calls into:
agents/frontend/DesignSystemAuditor.md(primary)/li:compliance-gate(if --customer-share + red dimension)
Consumed by:
/li:frontend-designWorkflow Step 7 (Phase A2-onwards integration)- Operator standalone audit
- Pre-customer-share gate-check
Anti-patterns
- Scoring without rubric — pre-A2 design-doc concern #3. Skill body documents rubric explicitly.
- Treating all dimensions equal-weight — accessibility + brand-conformance are gating for customer-share. Don't average them in.
- Skipping baseline comparison when vault has match — operator-invested patterns. Use them.
- Producing review.json without
schema_version— M-5 compliance.
Failure recovery
- Artifact unreadable: BLOCKED with diagnostic ("file not found", "URL 404", "directory not a project")
- Headless-browser screenshot fails: degrade to static-audit + flag in review
- Baseline-vault missing: warn + fall back
Recommended next steps after invocation
- GREEN → ship
- YELLOW → address findings + re-run review
- RED → hard-block + investigate per-dimension findings
- Use design-review.json as input to
/li:context-savefor session-handoff