You are the frontend-design orchestrator skill — entrypoint for production-ready frontend design e2e per v3.7 frontend-* family.
What this skill does
Orchestrates design-director-decisions (typography + motion + shader thesis + component-library-pick) → produces frontend-design-spec.json → calls rendering-engine (generate-web single-file/Next.js or generate-app full-vite/svelte/next-monorepo — Phase B) for file-output.
The skill OWNS design-decisions. It does NOT own HTML/Next.js-file-generation (that's the generate-* family per the v3.7 design-doc-boundary).
Reads operator brief → dispatches typography + motion sub-skills in parallel → synthesizes frontend-design-spec.json → calls rendering-engine.
When to use
- "A landing page for our legal-research assistant" — full end-to-end mode for production-ready design
- Customer demo that must look Awwwards-grade
- Internal microsite where visual quality affects adoption
- Multi-format engagement where /li:cycle BUILD-phase produces an app + design must match the pitch
When NOT to use
- Wireframe-only sketch →
/li:design-html(existing skill) - Single design-decision-axis (just typography or just motion) → solo sub-skill
/li:frontend-typographyor/li:frontend-motion - Pure file-gen without design-direction →
/li:generate-webdirectly with--brief - Re-render existing run →
/li:generate-web --from-frontend-design <existing-run-dir>
Inputs
- Required
<brief>— design brief text or path to brief.md - Optional
--pattern <vault-name>— select from~/.lintel/brand/design-patterns/<name>/(Phase A2 enables canonical pattern) - Optional
--target-format <single-file|nextjs|app>— default:single-file.apptriggers generate-app (Phase B) - Optional
--customer-share— sets CUSTOMER_SHARE=1, triggers compliance-gate + voice-gate - Optional
--out <path>— output path (default:~/.lintel/frontend-runs/<run-id>/) - Optional
--skip-shader— Phase A1 default (frontend-shader skill ships in A2)
Workflow
Step 1 — Parse invocation + warm context
brief="${1:-}"
pattern="${PATTERN:-}"
target_format="${TARGET_FORMAT:-single-file}"
customer_share="${CUSTOMER_SHARE:-}"
out_dir="${OUT:-$HOME/.lintel/frontend-runs/$(date +%Y%m%d-%H%M%S)-${RANDOM}}"
[ -z "$brief" ] && { echo "Usage: /li:frontend-design <brief> [--pattern <name>] [--target-format <single-file|nextjs|app>]"; exit 2; }
mkdir -p "$out_dir"
Voice-tier resolution: default internal. If --customer-share → run the active pack's voice gate (resolve_pack_field compliance.hooks; none by default) first. Per L-001-discipline: skill body preserves contract, agent at invocation produces actual content.
Step 1.5 — Design DNA pass (REQUIRED — ADR-0015/0016)
Retrieval before generation. Resolve the active design profile and search the corpus BEFORE any design decision:
dna="${LINTEL_SKILLS_DIR:-skills}/design-dna" # LINTEL_SKILLS_DIR = this skill's base-dir parent (plugin installs)
source "${LINTEL_SOURCE_ROOT:-${LINTEL_REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null)}}/lib/pack-resolver.sh" 2>/dev/null \
|| source "$HOME/.lintel/lib/pack-resolver.sh" 2>/dev/null
profile="$(resolve_pack_field design.profile 2>/dev/null)"
[ -z "$profile" ] || [ "$profile" = "null" ] && profile="anthropic-default"
python3 "$dna/scripts/search.py" "<product> <industry> <tone keywords from brief>" \
--design-system -f markdown -p "<project>" > "$out_dir/design-dna.md"
Resolver unsourceable → surface it before defaulting (a pack's declared profile is never silently ignored).
Precedence: brief > profile ($dna/profiles/$profile.yaml) > corpus hit — the profile is the
house default (anthropic-default: warm ink-and-paper); the corpus recommendation fills what the
profile doesn't pin (style pattern, landing structure, product-specific palette when the brief
asks for one); the brief's own words always win. Both design-dna.md and the profile feed
Step 2-4 dispatch and Step 5 synthesis. No python3 → use the grep fallback documented in
skills/design-dna/SKILL.md (the corpus is plain CSV).
Step 2-4 — Parallel sub-skill dispatch (M-4 resolution)
Run typography + motion sub-skills CONCURRENTLY (single-batch Agent-tool dispatch). They are independent — both take the brief as input, neither depends on the other.
Concurrent dispatch:
├─ /li:frontend-typography --brief "$brief" --out "$out_dir/typography.json"
└─ /li:frontend-motion --brief "$brief" --out "$out_dir/motion.json"
(Phase A2 adds parallel /li:frontend-shader → $out_dir/shader.json)
Both sub-skills receive $out_dir/design-dna.md + the active profile as context (Step 1.5
outputs): typography starts from the profile's font roles + the corpus pairing hits; motion
starts from the profile's duration/easing tokens. They deviate only where the brief demands it.
Wallclock budget: ~60s concurrent (vs ~180s sequential). Wait for both to complete before Step 5.
Step 5 — Synthesize frontend-design-spec.json
Read typography.json + motion.json (+ shader.json if A2). Synthesizes into frontend-design-spec.json:
{
"schema_version": 1,
"generated_at": "<iso-8601>",
"brief_hash": "<sha256 of brief>",
"source": "frontend-design",
"target_format": "single-file | nextjs | app",
"typography": { /* embedded from typography.json */ },
"motion": { /* embedded from motion.json */ },
"shader": null,
"component_libraries": [
{"name": "shadcn", "kind": "primitive"},
{"name": "<aceternity|magic-ui|park-ui>", "kind": "motion-enhanced"}
],
"layout_grammar": {
"max_width": "1200px",
"section_spacing": "var(--space-section)",
"grid": "12-col"
},
"interaction_signature": {
"scroll_smoothing": true,
"hover_intent": "subtle",
"page_transitions": "fade-or-slide"
},
"palette": {
"source_profile": "anthropic-default",
"tokens": { "<semantic-name>": "<hex>" },
"contrast_verified": true
},
"style": {
"name": "<chosen style from design-dna search>",
"anti_patterns": ["<from the corpus reasoning rule>"]
},
"design_dna": {
"profile": "anthropic-default",
"search_query": "<the Step 1.5 query>",
"search_ref": "design-dna.md"
},
"visual_thesis": "<one-paragraph synthesis>",
"voice_tier": "internal | customer-share"
}
palette, style and design_dna are additive optional fields (ADR-0015) — schema_version
stays 1; readers tolerate their absence (minor-additive per the schema-evolution policy below).
Schema-version discipline (M-5 resolution): ALL Lintel frontend-* contract-JSON files include "schema_version": 1. generate-web/generate-app readers log+reject on unknown major version. Schema-evolution policy: minor changes additive (new fields tolerated), major changes require new version + migration-path.
source-discriminator: "source": "frontend-design" distinguishes from pipeline's design-spec.json "source": "pipeline" (M-1 resolution — different filenames + explicit discriminator field).
Step 6 — Call rendering-engine
case "$target_format" in
single-file|nextjs)
/li:generate-web --from-frontend-design "$out_dir"
;;
app)
/li:generate-app --from-frontend-design "$out_dir" # Phase B skill
;;
esac
Phase A1 NOTE: --from-frontend-design mode in generate-web ships in the Phase B PR. Phase A1 stops at frontend-design-spec.json emission + the minimum-viable roundtrip test verifies the contract is consumable.
Step 7 — Quality gate (MANDATORY — ADR-0015)
The gate is no longer optional. Two parts, in order:
# 1. Mechanical validator on every rendered HTML artifact (exit 1 blocks).
# Spec-only runs have no HTML yet — the guard defers validation to generate-*.
if compgen -G "$out_dir/*.html" > /dev/null; then
python3 "$dna/scripts/validate_design.py" "$out_dir"/*.html \
--profile "$dna/profiles/$profile.yaml" || status=BLOCKED
fi
# 2. Six-dimension audit
/li:frontend-design-review "$out_dir"
Validator errors → BLOCKED (fix and re-render; never ship over a red gate). No rendered HTML yet (spec-only run) → validator runs in generate-web/generate-app instead; the review still runs on the spec. python3 absent → run the review with the design-dna non-negotiables checklist explicitly in scope.
Step 8 — Output paths + recommendation
FRONTEND-DESIGN RUN COMPLETE
══════════════════════════════════════════════════════════════════
Run dir: $out_dir
Typography spec: $out_dir/typography.json
Motion spec: $out_dir/motion.json
Frontend design spec: $out_dir/frontend-design-spec.json
Voice tier: $voice_tier
Target format: $target_format
Next:
Render: /li:generate-web --from-frontend-design $out_dir (Phase B)
Review: /li:frontend-design-review $out_dir (Phase A2)
Extract as pattern: /li:frontend-style-extract $out_dir/* (Phase A2)
Voice tier behavior
voice: mixed. Default internal. --customer-share triggers the active pack's compliance-gate + voice-gate (resolve_pack_field compliance.hooks; none by default).
Status protocol
- DONE — both sub-skills returned, frontend-design-spec.json written, schema-validation passed
- DONE_WITH_CONCERNS — sub-skill returned with warnings (e.g., font-license unclear)
- BLOCKED — sub-skill failed, OR brief unparsable, OR customer-share check failed
- NEEDS_CONTEXT — brief too vague (no audience, no purpose, no aesthetic-direction)
Integration
Reads:
<brief>argument (path or inline text)~/.lintel/brand/design-patterns/<name>/(if--patternflag set; Phase A2 enables)~/.lintel/profile.yaml(mode → voice-tier)
Writes:
~/.lintel/frontend-runs/<run-id>/typography.json(via frontend-typography sub-skill)~/.lintel/frontend-runs/<run-id>/motion.json(via frontend-motion sub-skill)~/.lintel/frontend-runs/<run-id>/frontend-design-spec.json(Step 5 synthesis)- Audit-log:
.claude/runtime/audit/frontend-design-runs.jsonl
Calls into:
/li:design-dnasystem search + profile resolution (Step 1.5, required) + validator (Step 7)/li:frontend-typography(sub-skill, parallel)/li:frontend-motion(sub-skill, parallel)/li:generate-web --from-frontend-design <run-dir>(Phase B)- the active pack's voice gate (
resolve_pack_field compliance.hooks; none by default — if customer-share) /li:compliance-gate(existing, if customer-share)
Boundary with the generate- family:*
frontend-design is the DESIGN-DIRECTOR-LAYER (decisions). generate-web/generate-app are the RENDERING-ENGINE-LAYER (file-output). Frontend-design CALLS into generate-* for rendering. Not vice versa. Sharp boundary per the v3.7 design-doc family-separation-table.
Brand-asset-slots (Phase A1 documents paths; folders lazy-created):
~/.lintel/brand/design-patterns/— Phase A2 ships canonicalultra-modern-lovable-style/~/.lintel/brand/motion-libraries/— operator-tested GSAP/Lenis-combos~/.lintel/brand/shader-snippets/— operator-curated GLSL (Phase A2 + frontend-shader)
Anti-patterns
- Generating HTML inside frontend-design — that's generate-web's job (boundary-violation per L-002). Use
--from-frontend-designchain. - Sequential sub-skill dispatch — Workflow Step 2-4 explicitly PARALLEL per M-4. Sequential breaks 10-min budget.
- Pre-baking canonical patterns — Phase A1 ships slot-bootstrapping only. Canonical hand-curation deferred to A2 after schema validates against operator-real briefs.
- Bundling commercial fonts/libraries — Lintel ships scaffolding. Operator licenses Pangram + installs GSAP/OGL/Aceternity via npm.
Failure recovery
- Sub-skill timeout (>120s): mark sub-skill output as STUB + continue with partial synthesis; surface to operator with "partial-spec" warning
- Brief unparsable: BLOCKED, return to operator with prompt-improvement-suggestions
- Schema-validation failure on frontend-design-spec.json: BLOCKED, log diff between produced + expected schema
- Voice-gate fail (customer-share): BLOCKED, surface voice-check output verbatim
Recommended next steps after invocation
- Phase A1: hand off
$out_dir/frontend-design-spec.jsonto generate-web manually for now (Phase B automatic chain) - Phase A2: pair with
/li:frontend-design-reviewfor 6-dimension audit - Phase A2+: extract successful design via
/li:frontend-style-extract $out_dir/*→ adds to vault - Cycle-integration: defer to Phase D after operator dogfood validates real-engagement flow
L-001/L-002/L-003 application
- L-001 (scaffolding-not-content): skill body is contract. Agent at invocation produces actual typography choices, motion language, shader thesis. Canonical pattern deferred to A2. Operator-extracted patterns dominate vault long-term.
- L-002 (grep-first): the generate-* family is preserved. Frontend-* family = identity-anchor + design-director layer, NOT a replacement. Boundary-table-row added to the design-doc.
- L-003 (verify-claims): schema_version field on every contract JSON. generate-web reader verifies before consuming. Don't trust stale schemas.