Перевод: оболочка страницы на русском; тело навыка (SKILL.md) пока на английском — это исходные инструкции агента.
Design Variant Picker
Generate 3 HTML design previews before site build.
Метаданные навыка
| Источник | Встроенный (установлен по умолчанию) |
| Путь | skills/creative/design-variant-picker |
| Версия | 1.0.0 |
| Автор | VibeOS |
| Лицензия | MIT |
| Платформы | linux, macos, windows |
| Теги | design, variants, preview, landing, creative, html, tokens, gallery |
| Связанные навыки | claude-design, popular-web-designs, design-to-code-loop, internet-starter, design-md, desktop-local-preview |
Справка: полный SKILL.md
Ниже полное определение навыка, которое VibeOS загружает при активации. Это инструкции, которые видит агент.
Design Variant Picker Skill
When a user loudly and clearly asks for a site (“landing for a coffee shop”,
“SaaS like Linear”, “calm yoga studio, lots of air”), do not scaffold a full
Next app first. Normalize the brief, generate three visually different HTML
preview stubs + tokens, let the user pick A/B/C, then lock DESIGN.md and
design/tokens.css before internet-starter / design-to-code-loop.
This skill owns procedure + scripts + templates. Brief Architect owns
references/briefs.yaml + references/tone-brand-map.md (8 loud scenarios +
tone→brand families). Fixture & QA owns fixtures/ and
tests/skills/test_design_variant_picker.py. Do not edit those paths from here.
Load canonical scenarios when normalizing a brief or writing offline tests:
skill_view(name="design-variant-picker", file_path="references/briefs.yaml")
and the mapping table in references/tone-brand-map.md.
When to Use
- User asks for a new landing / marketing site / portfolio with taste expectations
- Request names a brand mood (“like Stripe”, “not dark”, “no purple”)
- You need side-by-side design directions before committing to scaffold
- Desktop Design rail will read
manifest.json(phase 2); skill path works without UI
Prerequisites
claude-designfor taste and HTML artifact rulespopular-web-designswhen brief maps to a known brand familydesign-to-code-loopafter selection (not during variant generation)internet-starterafter selection if no app exists yetdesktop-local-previewor/previewto openpreview.html- Write access under project or profile home for
.vibeos/design-variants/
How to Run
End-to-end (operator):
- Normalize user text →
normalize_brief.py→ runbrief.md(+ optional JSON) - Generate variants A, B, C (default N=3; fourth only if brief is wide or user asks)
- Write
manifest.json; run validation + diversity gate - User picks variant →
select_variant.pylocks choice into project - Then scaffold / apply tokens — never before step 4
Scripts (from repo root):
python3 skills/creative/design-variant-picker/scripts/normalize_brief.py \
--text "Сделай лендинг для уютной кофейни, без неона" \
--out .vibeos/design-variants/run-<id>/brief.md \
--json-out .vibeos/design-variants/run-<id>/brief.json
python3 skills/creative/design-variant-picker/scripts/normalize_brief.py \
--seed-id local_coffee_salon \
--out .vibeos/design-variants/run-<id>/brief.md
python3 skills/creative/design-variant-picker/scripts/validate_manifest.py \
--manifest .vibeos/design-variants/run-<id>/manifest.json
python3 skills/creative/design-variant-picker/scripts/diversity_gate.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/select_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--variant B \
--project-dir ./my-site
python3 skills/creative/design-variant-picker/scripts/ensure_variant_tokens.py \
--run-dir .vibeos/design-variants/run-<id>/
python3 skills/creative/design-variant-picker/scripts/latest_run.py \
--project-dir ./my-site
Quick Reference
| Artifact | Purpose |
|---|---|
brief.md | Normalized brief for this run |
manifest.json | Variant list + metadata for UI / scripts |
A/preview.html | Self-contained hero + 1–2 sections |
A/tokens.css | :root CSS variables |
A/direction.md | Title, why, layout keyword, anti-patterns |
A/thumb.png | Optional gallery thumbnail |
selected.json | { "variant": "B", "locked_at": "…" } after pick |
design/tokens.css | Copied into project on select |
DESIGN.md | Copied from chosen direction.md on select |
| Script | Exit | Role |
|---|---|---|
normalize_brief.py | 0/1 | Loud text or --seed-id → brief.md / JSON |
validate_manifest.py | 0/1 | Schema + files exist |
diversity_gate.py | 0/1 | Variants differ enough |
ensure_variant_tokens.py | 0/1 | tokens.css + colors[] fallback (no screenshot) |
latest_run.py | 0/1 | Newest run-* with manifest under project |
select_variant.py | 0/1 | Lock + copy to project |
| Default | Value |
|---|---|
| Variant count N | 3 (A, B, C) |
| Run folder | .vibeos/design-variants/run-<timestamp>/ |
| Post-select tokens | <project>/design/tokens.css |
| Post-select direction | <project>/DESIGN.md |
Procedure
1. Create run directory
.vibeos/design-variants/
run-<timestamp>/
brief.md
manifest.json
A/ preview.html tokens.css direction.md [thumb.png]
B/ …
C/ …
selected.json # after user picks
Use ISO-ish run id: run-20260721T120000Z. Paths in manifest.json are
relative to the run folder.
2. Normalize brief
Run normalize_brief.py on the user's loud request (or --seed-id for offline
seeds in references/briefs.yaml). Writes brief.md from templates/brief.md
and optional JSON with structured fields. Required fields:
| Field | Notes |
|---|---|
| industry | e.g. coffee shop, B2B SaaS, portfolio |
| audience | who lands on the page |
| tone | calm / bold / luxury / playful / technical |
| primary_cta | one main action |
| must_sections | hero + blocks user expects |
| forbid | hard negatives — colors, dark mode, card soup |
| reference_brands | Stripe, Linear, etc. if named |
| locale | ru / en |
Good: “Calm yoga studio, light only, no purple, hero = one headline + book class.”
Bad: Dropping forbid list; vague “modern and clean” with no industry.
If user named a brand: one variant should brand-match; others are mood
neighbors, not clones (see Agent A references/tone-brand-map.md when present).
3. Generate variants (default N=3)
For each id in A, B, C:
- Copy
templates/direction.md→<id>/direction.md(fill title, why, layout_keyword, fonts, palette) - Write
<id>/tokens.csswith--color-*,--font-*, spacing tokens - Write
<id>/preview.html— self-contained HTML+CSS; hero + one follow section max - Optional: screenshot →
<id>/thumb.png; else ensurecolors[]in manifest (≥3 hex swatches). Runensure_variant_tokens.pyto backfill missingtokens.cssorcolors[]without network or Playwright.
Do not run internet-starter, create app/page.tsx, or full Next scaffold
for each variant. Previews are lightweight HTML stubs only.
Load popular-web-designs templates when brand_ref is set. Load
claude-design for process and anti-slop. Use read_file / patch for files;
use browser_navigate or desktop /preview to verify previews open.
4. Hero budget (first screen)
One job on the hero — no clutter:
| Allow (pick one each) | Forbid in hero |
|---|---|
| Brand mark or wordmark | Fake metrics / “10k+ users” stats |
| One headline (H1) | Pill badge clusters |
| One primary CTA | Feature card grid |
| One visual anchor (photo, product, abstract shape) | Stock-photo clichés with overlay stickers |
| Optional one line of supporting copy | Purple/pink AI gradient blobs |
| Dashboard mockups with invented numbers | |
| More than two type sizes above the fold |
Sections after hero may add proof/features; keep preview.html short (hero + 1 block).
5. Anti-slop rules (all variants)
Across A/B/C you must vary direction, not just hue:
- No four “AI purple gradient” clones
- No glassmorphism-by-default, rainbow palettes, emoji decor unless brand uses them
- No left-border accent callout cards as the only layout idea
- No generic labels (“Insights”, “Scale”, “Optimize”) without real copy
- Respect
forbid[]from brief literally (if “no dark theme”, no variant is dark) - Layout keywords must differ across variants when possible:
editorial,split,full-bleed,centered,asymmetric,grid,stacked
6. Write manifest.json
Minimal shape (full schema: templates/manifest.schema.json):
{
"run_id": "run-20260721T120000Z",
"brief_path": "brief.md",
"created_at": "2026-07-21T12:00:00Z",
"variants": [
{
"id": "A",
"title": "Quiet Editorial",
"why": "Calm tone and airy type fit a wellness brief.",
"brand_ref": "original",
"preview_path": "A/preview.html",
"tokens_path": "A/tokens.css",
"direction_path": "A/direction.md",
"colors": ["#f7f5f2", "#2a2520", "#8b7355"],
"fonts": { "heading": "Fraunces", "body": "Source Sans 3" },
"layout_keyword": "editorial"
}
]
}
Each variant needs colors[] (≥3 hex for gallery swatches) or thumb_path.
Offline runs use colors[] only — no screenshot required. Validate:
python3 skills/creative/design-variant-picker/scripts/validate_manifest.py \
--manifest .vibeos/design-variants/run-<id>/manifest.json
7. Ensure tokens + colors (offline fallback)
Before validation or when thumbs are skipped:
python3 skills/creative/design-variant-picker/scripts/ensure_variant_tokens.py \
--run-dir .vibeos/design-variants/run-<id>/
Repairs missing/empty tokens.css from manifest colors[] + fonts, adds
--color-* when absent, and restores colors[] (≥3 hex) from existing CSS.
No network; thumb.png is optional when colors[] is present.
8. Diversity gate
Before showing the gallery to the user:
python3 skills/creative/design-variant-picker/scripts/diversity_gate.py \
--run-dir .vibeos/design-variants/run-<id>/
If exit 1: regenerate the closest variant (change layout_keyword + palette +
font stack), re-run gate. Thresholds are in diversity_gate.py --help.
8b. Desktop bridge (after variants exist)
After writing run artifacts and diversity_gate.py exits 0, tell the user
how to open the gallery — do not scaffold Next or call internet-starter
yet.
- Resolve the run directory (absolute path):
python3 skills/creative/design-variant-picker/scripts/latest_run.py \
--project-dir /path/to/project
- Print in chat (one short block):
- Absolute path to the run directory
- Suggest opening the Design tab in Desktop, or slash:
/designor/design load <absolute-run-dir> - One machine-parseable marker line (Desktop may parse later):
VIBEOS_DESIGN_VARIANTS_RUN=/absolute/path/to/run-20260721T120000Z
Example assistant message:
Three design directions are ready (A/B/C). Open the Design tab in the right
rail, or run `/design load /Users/you/my-site/.vibeos/design-variants/run-20260721T120000Z`.
VIBEOS_DESIGN_VARIANTS_RUN=/Users/you/my-site/.vibeos/design-variants/run-20260721T120000Z
Hard rule: no internet-starter, no app/page.tsx, no full Next scaffold
until the user selects a variant (select_variant.py or Desktop Select).
9. User selection → lock
After explicit user choice (chat, Desktop Design tab, or slash):
python3 skills/creative/design-variant-picker/scripts/select_variant.py \
--run-dir .vibeos/design-variants/run-<id>/ \
--variant B \
--project-dir /path/to/project
Writes selected.json, updates manifest.selected, copies:
<variant>/tokens.css→<project>/design/tokens.css<variant>/direction.md→<project>/DESIGN.md
Re-running select is idempotent (overwrites lock and project files).
10. After lock only
- If no app:
internet-starterscaffold - Merge tokens via
design-to-code-loop/extract_design_tokens.pypatterns - Optional formal spec:
design-md - Polish motion via
cinematic-webif appropriate - Verify with
desktop-local-preview,browser_navigate, orsite-page-analyze
Pitfalls
- Scaffolding Next×3 before pick — expensive, slow, violates product contract
- Ignoring forbid[] — user said “no dark”; all variants must comply
- Same layout + font + palette — diversity gate exists; fix before user sees gallery
- Full page in preview.html — hero + one section is enough for comparison
- Skipping manifest validation — Desktop rail and tests expect stable schema
- Editing Agent A/C paths — briefs.yaml, fixtures, tests are out of scope here
- Mid-conversation cache break — defer
/design variantsskill load to turn boundary when possible; do not swap toolsets mid-turn for variant generation
Verification
- Run folder matches layout in section 1;
brief.mdfilled - Exactly 3 variants by default (A/B/C) unless user asked for more
- Each
preview.htmlopens locally (file or static server) and shows distinct direction -
validate_manifest.pyexits 0 -
diversity_gate.pyexits 0 - After generation: chat shows run path +
/designhint +VIBEOS_DESIGN_VARIANTS_RUN=… -
latest_run.py --project-dir …exits 0 when a run exists -
select_variant.pywritesselected.json+ projectdesign/tokens.css+DESIGN.md - No full Next scaffold created before select
- Brief
forbidconstraints visible in all previews - Agent C tests pass when fixtures land:
scripts/run_tests.sh tests/skills/test_design_variant_picker.py -q