--- name: layout-extract description: Extract structural layout information from reference images or text prompts using Claude analysis with variant generation or refinement mode argument-hint: [--design-id ] [--session ] [--images ""] [--prompt ""] [--targets ""] [--variants ] [--device-type ] [--interactive] [--refine] allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), AskUserQuestion(*), Task(ui-design-agent), mcp__exa__web_search_exa(*) --- # Layout Extraction Command ## Overview Extract structural layout information from reference images or text prompts using AI analysis. Supports two modes: 1. **Exploration Mode** (default): Generate multiple contrasting layout variants 2. **Refinement Mode** (`--refine`): Refine a single existing layout through detailed adjustments This command separates the "scaffolding" (HTML structure and CSS layout) from the "paint" (visual tokens handled by `style-extract`). **Strategy**: AI-Driven Structural Analysis - **Agent-Powered**: Uses `ui-design-agent` for deep structural analysis - **Dual Mode**: Exploration (multiple contrasting variants) or Refinement (single layout fine-tuning) - **Output**: `layout-templates.json` with DOM structure, component hierarchy, and CSS layout rules - **Device-Aware**: Optimized for specific device types (desktop, mobile, tablet, responsive) - **Token-Based**: CSS uses `var()` placeholders for spacing and breakpoints ## Execution Process ``` Input Parsing: ├─ Parse flags: --design-id, --session, --images, --prompt, --targets, --variants, --device-type, --interactive, --refine └─ Decision (mode detection): ├─ --refine flag → Refinement Mode (variants_count = 1) └─ No --refine → Exploration Mode (variants_count = --variants OR 3) Phase 0: Setup & Input Validation ├─ Step 1: Detect input, mode & targets ├─ Step 2: Load inputs & create directories └─ Step 3: Memory check (skip if cached) Phase 1: Layout Concept/Refinement Options Generation ├─ Step 0.5: Load existing layout (Refinement Mode only) ├─ Step 1: Generate options (Agent Task 1) │ └─ Decision: │ ├─ Exploration Mode → Generate contrasting layout concepts │ └─ Refinement Mode → Generate refinement options └─ Step 2: Verify options file created Phase 1.5: User Confirmation (Optional) └─ Decision (--interactive flag): ├─ --interactive present → Present options, capture selection └─ No --interactive → Skip to Phase 2 Phase 2: Layout Template Generation ├─ Step 1: Load user selections or default to all ├─ Step 2: Launch parallel agent tasks └─ Step 3: Verify output files ``` ## Phase 0: Setup & Input Validation ### Step 1: Detect Input, Mode & Targets ```bash # Detect input source # Priority: --images → image | --prompt → text # Detect refinement mode refine_mode = --refine OR false # Set variants count # Refinement mode: Force variants_count = 1 (ignore user-provided --variants) # Exploration mode: Use --variants or default to 3 (range: 1-5) IF refine_mode: variants_count = 1 REPORT: "🔧 Refinement mode enabled: Will generate 1 refined layout per target" ELSE: variants_count = --variants OR 3 VALIDATE: 1 <= variants_count <= 5 REPORT: "🔍 Exploration mode: Will generate {variants_count} contrasting layout concepts per target" # Resolve targets # Priority: --targets → prompt analysis → default ["page"] IF --targets: targets = split(--targets, ",") ELSE IF --prompt: # Extract targets from prompt using pattern matching # Looks for keywords: "page names", target descriptors (login, dashboard, etc.) # Returns lowercase, hyphenated strings (e.g., ["login", "dashboard"]) targets = extract_from_prompt(--prompt) ELSE: targets = ["page"] # Resolve device type device_type = --device-type OR "responsive" # desktop|mobile|tablet|responsive # Determine base path with priority: --design-id > --session > auto-detect if [ -n "$DESIGN_ID" ]; then # Exact match by design ID relative_path=$(find .workflow -name "${DESIGN_ID}" -type d -print -quit) elif [ -n "$SESSION_ID" ]; then # Latest in session relative_path=$(find .workflow/active/WFS-$SESSION_ID -name "design-run-*" -type d -printf "%T@ %p\n" 2>/dev/null | sort -nr | head -1 | cut -d' ' -f2) else # Latest globally relative_path=$(find .workflow -name "design-run-*" -type d -printf "%T@ %p\n" 2>/dev/null | sort -nr | head -1 | cut -d' ' -f2) fi # Validate and convert to absolute path if [ -z "$relative_path" ] || [ ! -d "$relative_path" ]; then echo "❌ ERROR: Design run not found" echo "💡 HINT: Run '/workflow:ui-design:list' to see available design runs" exit 1 fi base_path=$(cd "$relative_path" && pwd) bash(echo "✓ Base path: $base_path") ``` ### Step 2: Load Inputs & Create Directories ```bash # For image mode bash(ls {images_pattern}) # Expand glob pattern Read({image_path}) # Load each image # For text mode # Validate --prompt is non-empty # Create output directory bash(mkdir -p {base_path}/layout-extraction) ``` ### Step 3: Memory Check ```bash # 1. Check if inputs cached in session memory IF session_has_inputs: SKIP Step 2 file reading # 2. Check if output already exists bash(find {base_path}/layout-extraction -name "layout-*.json" -print -quit | grep -q . && echo "exists") IF exists: SKIP to completion ``` --- **Phase 0 Output**: `input_mode`, `base_path`, `variants_count`, `targets[]`, `device_type`, loaded inputs ## Phase 1: Layout Concept or Refinement Options Generation ### Step 0.5: Load Existing Layout (Refinement Mode) ```bash IF refine_mode: # Load existing layout for refinement existing_layouts = {} FOR target IN targets: layout_files = bash(find {base_path}/layout-extraction -name "layout-{target}-*.json" -print) IF layout_files: # Use first/latest layout file for this target existing_layouts[target] = Read(first_layout_file) ``` ### Step 1: Generate Options (Agent Task 1 - Mode-Specific) **Executor**: `Task(ui-design-agent)` **Exploration Mode** (default): Generate contrasting layout concepts **Refinement Mode** (`--refine`): Generate refinement options for existing layouts ```javascript // Conditional agent task based on refine_mode IF NOT refine_mode: // EXPLORATION MODE Task(ui-design-agent): ` [LAYOUT_CONCEPT_GENERATION_TASK] Generate {variants_count} structurally distinct layout concepts for each target SESSION: {session_id} | MODE: explore | BASE_PATH: {base_path} TARGETS: {targets} | DEVICE_TYPE: {device_type} ## Input Analysis - Targets: {targets.join(", ")} - Device type: {device_type} - Visual references: {loaded_images if available} ${dom_structure_available ? "- DOM Structure: Read from .intermediates/layout-analysis/dom-structure-*.json" : ""} ## Analysis Rules - For EACH target, generate {variants_count} structurally DIFFERENT layout concepts - Concepts must differ in: grid structure, component arrangement, visual hierarchy - Each concept should have distinct navigation pattern, content flow, and responsive behavior ## Generate for EACH Target For target in {targets}: For concept_index in 1..{variants_count}: 1. **Concept Definition**: - concept_name (descriptive, e.g., "Classic Three-Column Holy Grail") - design_philosophy (1-2 sentences explaining the structural approach) - layout_pattern (e.g., "grid-3col", "flex-row", "single-column", "asymmetric-grid") - key_components (array of main layout regions) - structural_features (list of distinguishing characteristics) 2. **Wireframe Preview** (simple text representation): - ascii_art (simple ASCII box diagram showing layout structure) - Example: ┌─────────────────┐ │ HEADER │ ├──┬─────────┬────┤ │ L│ MAIN │ R │ └──┴─────────┴────┘ ## Output Write single JSON file: {base_path}/.intermediates/layout-analysis/analysis-options.json Use schema from INTERACTIVE-DATA-SPEC.md (Layout Extract: analysis-options.json) CRITICAL: Use Write() tool immediately after generating complete JSON ` ELSE: // REFINEMENT MODE Task(ui-design-agent): ` [LAYOUT_REFINEMENT_OPTIONS_TASK] Generate refinement options for existing layout(s) SESSION: {session_id} | MODE: refine | BASE_PATH: {base_path} TARGETS: {targets} | DEVICE_TYPE: {device_type} ## Existing Layouts ${FOR target IN targets: "- {target}: {existing_layouts[target]}"} ## Input Guidance - User prompt: {prompt_guidance if available} - Visual references: {loaded_images if available} ## Refinement Categories Generate 8-12 refinement options per target across these categories: 1. **Density Adjustments** (2-3 options per target): - More compact: Tighter spacing, reduced whitespace - More spacious: Increased margins, breathing room - Balanced: Moderate adjustments 2. **Responsiveness Tuning** (2-3 options per target): - Breakpoint behavior: Earlier/later column stacking - Mobile layout: Different navigation/content priority - Tablet optimization: Hybrid desktop/mobile approach 3. **Grid/Flex Specifics** (2-3 options per target): - Column counts: 2-col ↔ 3-col ↔ 4-col - Gap sizes: Tighter ↔ wider gutters - Alignment: Different flex/grid justification 4. **Component Arrangement** (1-2 options per target): - Navigation placement: Top ↔ side ↔ bottom - Sidebar position: Left ↔ right ↔ none - Content hierarchy: Different section ordering ## Output Format Each option (per target): - target: Which target this refinement applies to - category: "density|responsiveness|grid|arrangement" - option_id: unique identifier - label: Short descriptive name (e.g., "More Compact Spacing") - description: What changes (2-3 sentences) - preview_changes: Key structural adjustments - impact_scope: Which layout regions affected ## Output Write single JSON file: {base_path}/.intermediates/layout-analysis/analysis-options.json Use refinement schema: { "mode": "refinement", "device_type": "{device_type}", "refinement_options": { "{target1}": [array of refinement options], "{target2}": [array of refinement options] } } CRITICAL: Use Write() tool immediately after generating complete JSON ` ``` ### Step 2: Verify Options File Created ```bash bash(test -f {base_path}/.intermediates/layout-analysis/analysis-options.json && echo "created") # Quick validation bash(cat {base_path}/.intermediates/layout-analysis/analysis-options.json | grep -q "layout_concepts" && echo "valid") ``` **Output**: `analysis-options.json` with layout concept options for all targets --- ## Phase 1.5: User Confirmation (Optional - Triggered by --interactive) **Purpose**: - **Exploration Mode**: Allow user to select preferred layout concept(s) per target - **Refinement Mode**: Allow user to select refinement options to apply per target **Trigger Condition**: Execute this phase ONLY if `--interactive` flag is present ### Step 1: Check Interactive Flag ```bash # Skip this entire phase if --interactive flag is not present IF NOT --interactive: SKIP to Phase 2 IF refine_mode: REPORT: "ℹ️ Non-interactive refinement mode: Will apply all suggested refinements" ELSE: REPORT: "ℹ️ Non-interactive mode: Will generate all {variants_count} variants per target" # Interactive mode enabled REPORT: "🎯 Interactive mode: User selection required for {targets.length} target(s)" ``` ### Step 2: Load and Present Options (Mode-Specific) ```bash # Read options file options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) # Branch based on mode IF NOT refine_mode: # EXPLORATION MODE layout_concepts = options.layout_concepts ELSE: # REFINEMENT MODE refinement_options = options.refinement_options ``` ### Step 2: Present Options to User (Per Target) For each target, present layout concept options and capture selection: ``` 📋 Layout Concept Options for Target: {target} We've generated {variants_count} structurally different layout concepts for review. Please select your preferred concept for this target. {FOR each concept in layout_concepts[target]: ═══════════════════════════════════════════════════ Concept {concept.index}: {concept.concept_name} ═══════════════════════════════════════════════════ Philosophy: {concept.design_philosophy} Pattern: {concept.layout_pattern} Components: {FOR each component in concept.key_components: • {component} } Features: {FOR each feature in concept.structural_features: • {feature} } Wireframe: {concept.wireframe_preview.ascii_art} ═══════════════════════════════════════════════════ } ``` ### Step 3: Capture User Selection and Update Options File (Per Target) **Interaction Strategy**: If total concepts > 4 OR any target has > 3 concepts, use batch text format: ``` 【目标[N] - [target]】选择布局方案 [key]) Concept [index]: [concept_name] [design_philosophy] [key]) Concept [index]: [concept_name] [design_philosophy] ... 请回答 (格式: 1a 2b 或 1a,b 2c 多选): User input: "[N][key] [N][key] ..." → Single selection per target "[N][key1,key2] [N][key3] ..." → Multi-selection per target ``` Otherwise, use `AskUserQuestion` below. ```javascript // Use AskUserQuestion tool for each target (multi-select enabled) FOR each target: AskUserQuestion({ questions: [{ question: "Which layout concept(s) do you prefer for '{target}'?", header: "Layout for " + target, multiSelect: true, // Multi-selection enabled (default behavior) options: [ {FOR each concept in layout_concepts[target]: label: "Concept {concept.index}: {concept.concept_name}", description: "{concept.design_philosophy}" } ] }] }) // Parse user response (array of selections) selected_options = user_answer // Check for user cancellation IF selected_options == null OR selected_options.length == 0: REPORT: "⚠️ User canceled selection. Workflow terminated." EXIT workflow // Extract concept indices from array selected_indices = [] FOR each selected_option_text IN selected_options: match = selected_option_text.match(/Concept (\d+):/) IF match: selected_indices.push(parseInt(match[1])) ELSE: ERROR: "Invalid selection format. Expected 'Concept N: ...' format" EXIT workflow // Store selections for this target (array of indices) selections[target] = { selected_indices: selected_indices, // Array of selected indices concept_names: selected_indices.map(i => layout_concepts[target][i-1].concept_name) } REPORT: "✅ Selected {selected_indices.length} layout(s) for {target}" // Calculate total selections across all targets total_selections = sum([len(selections[t].selected_indices) for t in targets]) // Update analysis-options.json with user selection (embedded in same file) options_file = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) options_file.user_selection = { "selected_at": "{current_timestamp}", "selection_type": "per_target_multi", "session_id": "{session_id}", "total_selections": total_selections, "selected_variants": selections // {target: {selected_indices: [...], concept_names: [...]}} } // Write updated file back Write({base_path}/.intermediates/layout-analysis/analysis-options.json, JSON.stringify(options_file, indent=2)) ``` ### Step 4: Confirmation Message ``` ✅ Selections recorded! Total: {total_selections} layout(s) {FOR each target, selection in selections: • {target}: {selection.selected_indices.length} layout(s) selected {FOR each index IN selection.selected_indices: - Concept {index}: {layout_concepts[target][index-1].concept_name} } } Proceeding to generate {total_selections} detailed layout template(s)... ``` **Output**: `analysis-options.json` updated with embedded `user_selection` field ## Phase 2: Layout Template Generation (Agent Task 2) **Executor**: `Task(ui-design-agent)` × `Total_Selected_Templates` in **parallel** ### Step 1: Load User Selections or Default to All ```bash # Read analysis-options.json which may contain user_selection options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) layout_concepts = options.layout_concepts # Check if user_selection field exists (interactive mode) IF options.user_selection AND options.user_selection.selected_variants: # Interactive mode: Use user-selected variants selections_per_target = options.user_selection.selected_variants total_selections = options.user_selection.total_selections ELSE: # Non-interactive mode: Generate ALL variants for ALL targets (default behavior) selections_per_target = {} total_selections = 0 FOR each target in targets: selections_per_target[target] = { "selected_indices": [1, 2, ..., variants_count], # All indices "concept_names": [] # Will be filled from options } total_selections += variants_count # Build task list for all selected concepts across all targets task_list = [] FOR each target in targets: selected_indices = selections_per_target[target].selected_indices # Array concept_names = selections_per_target[target].concept_names # Array FOR i in range(len(selected_indices)): idx = selected_indices[i] concept = layout_concepts[target][idx - 1] # 0-indexed array variant_id = i + 1 # 1-based variant numbering task_list.push({ target: target, variant_id: variant_id, concept: concept, output_file: "{base_path}/layout-extraction/layout-{target}-{variant_id}.json" }) total_tasks = task_list.length REPORT: "Generating {total_tasks} layout templates across {targets.length} targets" ``` ### Step 2: Launch Parallel Agent Tasks Generate layout templates for ALL selected concepts in parallel: ```javascript FOR each task in task_list: Task(ui-design-agent): ` [LAYOUT_TEMPLATE_GENERATION_TASK #{task.variant_id} for {task.target}] Generate detailed layout template based on user-selected concept. Focus ONLY on structure and layout. DO NOT concern with visual style (colors, fonts, etc.). SESSION: {session_id} | BASE_PATH: {base_path} TARGET: {task.target} | VARIANT: {task.variant_id} DEVICE_TYPE: {device_type} USER SELECTION: - Selected Concept: {task.concept.concept_name} - Philosophy: {task.concept.design_philosophy} - Pattern: {task.concept.layout_pattern} - Key Components: {task.concept.key_components.join(", ")} - Structural Features: {task.concept.structural_features.join(", ")} ## Input Analysis - Target: {task.target} - Device type: {device_type} - Visual references: {loaded_images if available} ${dom_structure_available ? "- DOM Structure Data: Read from .intermediates/layout-analysis/dom-structure-{task.target}.json - USE THIS for accurate layout properties" : ""} ## Generation Rules - Develop the user-selected layout concept into a detailed template - Use the selected concept's key_components as foundation - Apply the selected layout_pattern (grid-3col, flex-row, etc.) - Honor the structural_features defined in the concept - Expand the concept with complete DOM structure and CSS layout rules ${dom_structure_available ? ` - IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties - Use DOM data as primary source for layout properties - Extract real flex/grid configurations (display, flexDirection, justifyContent, alignItems, gap) - Use actual element bounds for responsive breakpoint decisions - Preserve identified patterns from DOM structure ` : ""} ## Template Generation 1. **DOM Structure**: - Semantic HTML5 tags:
,