# Generate Design

> Produce design-spec.json (per-format layout-mappings + palette + fonts + asset placements) from content.md. Shared content-pipeline sub-skill, solo-invokable.

- Skill: `jokerman89/generate-design` (Agent Skill)
- Install (CLI): `npx skillmds@latest add jokerman89/generate-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jokerman89/generate-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: jokerman89 (https://skillmd.com/u/jokerman89)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jokerman89/generate-design

---


You are the `generate-design` skill — third stage of the v3.5 shared content pipeline. Produces design-spec.json from content.md.

## What this skill does

Reads content.md (with HTML-comment annotations for type + voice + key_message) → produces design-spec.json with per-target-format layout-mappings, palette references, font hints, logo placements, and per-format design-pass hooks for format-builders.

This is the "shared design baseline." Format-builders (`generate-ppt`, `generate-web`, `generate-word`) read design-spec.json + apply their own format-specific design-pass (e.g., `PPTNarrativeArchitect` for PPT slide-narrative, `WebExperienceCritic` for web hero/flow, `WordTechnicalEditor` for word headings/style). The shared baseline gives them consistency; the per-format pass gives them format-fidelity.

Used by `generate` orchestrator as Step 5, or solo when operator wants to re-design existing content for different formats or different brand-palette.

## When to use

- Third step of `/li:generate` orchestrator chain (after write)
- Operator wants to retarget existing content to different formats
- Brand-palette swap (re-design with `--palette nordic-minimal` vs `default`)
- A/B-test layout strategies for same content

## When NOT to use

- Operator has no content.md — invoke `/li:generate-write` first
- Pure visual mockup without content — use HTML wireframe sketch instead
- Format-specific design tweaks — those happen in format-builder's design-pass hook, not here

## Inputs

- Required `--content <path>` — content.md from generate-write
- Required `--target-formats <ppt,web,word,...>` — per-format spec generated for each
- Optional `--palette <name>` — palette JSON name (default: `default`)
- Optional `--brand-templates-dir <path>` — `~/.lintel/brand/` (default)
- Optional `--logo <path>` — explicit logo override
- Optional `--out <path>` — output path (default: `${run_dir}/design-spec.json`)

## Design-spec.json schema

```json
{
  "version": "1.0",
  "generated_at": "<iso-8601>",
  "source_content_hash": "<sha256 of content.md>",
  "palette": {
    "name": "default",
    "primary": "#0078D4",
    "secondary": "#50E6FF",
    "accent": "#FFB900",
    "text_dark": "#1B1B1B",
    "text_light": "#FFFFFF",
    "background": "#FFFFFF"
  },
  "fonts": {
    "heading": "Segoe UI Semibold",
    "body": "Segoe UI",
    "code": "Cascadia Code",
    "heading_size": 28,
    "body_size": 14
  },
  "logo": {
    "path": "~/.lintel/brand/logos/default.png",
    "position": "top-right"
  },
  "per_format": {
    "ppt": {
      "template_path": "~/.lintel/brand/ppt-templates/default.pptx",
      "layouts": [
        {
          "section_ref": "§1",
          "layout_name": "Title Slide",
          "layout_index": 0,
          "elements": [
            {"placeholder": "title", "content_field": "Title", "font_override": null},
            {"placeholder": "subtitle", "content_field": "Subtitle", "font_override": null}
          ],
          "animation": "dissolve",
          "design_pass_hook": "PPTNarrativeArchitect"
        }
      ]
    },
    "web": {
      "template_path": "~/.lintel/brand/web-templates/single-file-default.html",
      "sections": [
        {
          "section_ref": "§1",
          "block_type": "hero",
          "elements": [
            {"slot": "h1", "content_field": "Title"},
            {"slot": "tagline", "content_field": "Subtitle"}
          ],
          "design_pass_hook": "WebExperienceCritic"
        }
      ]
    },
    "word": {
      "template_path": "~/.lintel/brand/word-templates/customer-summary.docx",
      "sections": [
        {
          "section_ref": "§1",
          "heading_level": 1,
          "elements": [
            {"slot": "heading", "content_field": "Title"},
            {"slot": "body", "content_field": "Body"}
          ],
          "design_pass_hook": "WordTechnicalEditor"
        }
      ]
    }
  }
}
```

Key contract points:
- `palette` + `fonts` are shared across all target formats (consistency)
- `per_format.<format>` is format-specific layout-mapping
- `design_pass_hook` names the format-specific agent that applies fidelity-pass at format-builder level (not invoked by generate-design directly)
- `section_ref` ties back to content.md `§N` sections for traceability

## Workflow

### Step 1 — Read content.md + parse annotations

Parse content.md frontmatter + per-section HTML-comment annotations (`<!-- type: ... -->`, `<!-- voice: ... -->`, `<!-- key_message: ... -->`). Build per-section lookup table.

### Step 2 — Load palette + brand templates

Resolve `--palette` to `~/.lintel/brand/palettes/<name>.json`. Read palette. If missing: fall back to `default` palette (in-repo).

For each format in `--target-formats`: locate template at `~/.lintel/brand/<format>-templates/<default>.<ext>`. Surface staleness warning if template > 90 days old. Fall back to blank if missing and `--use-defaults` set.

### Step 3 — Per-section layout-mapping

For each content.md section (§N):
- Per requested format, choose appropriate layout/block-type based on section's `type` annotation
- Map content fields (Title, Subtitle, Body, Bullets) to format placeholders/slots
- Assign `design_pass_hook` (PPT → PPTNarrativeArchitect, web → WebExperienceCritic, word → WordTechnicalEditor)
- Apply palette + fonts (no overrides unless content explicitly differs)

### Step 4 — Validate

- Every §N section has a layout-mapping for every target format
- No layout used > 3 times consecutively (rotation rule)
- Font sizes within palette min/max
- Logo placement consistent across all sections

### Step 5 — Write design-spec.json + return path

Write to `--out`. Surface summary (per-format layout count, palette used, font baseline) to operator.

## Status protocol

- **DONE** — design-spec.json written, all sections mapped, validation passed
- **DONE_WITH_CONCERNS** — written but some validation warnings (layout-rotation, palette-staleness)
- **BLOCKED** — content.md missing or malformed, palette resolution failed, no template + no `--use-defaults`
- **NEEDS_CONTEXT** — `--target-formats` empty or unparseable

## Pause-points

- Palette missing for `--palette <custom>` name: offer fallback to default or surface upload-instruction
- Layout-mapping ambiguous for §N (multiple valid layouts): surface options + recommendation

## Integration

**Reads:**
- `content.md` (from generate-write)
- `~/.lintel/brand/palettes/<palette>.json`
- `~/.lintel/brand/<format>-templates/<default>.<ext>` per target format

**Writes:**
- `design-spec.json` to `--out`

**Consumed by:**
- `/li:generate` orchestrator (Step 5)
- `/li:generate-ppt`, `/li:generate-web`, `/li:generate-word` (canonical format-builders read design-spec.json + apply per-format design-pass)
- `/li:generate-pdf`, `/li:generate-xlsx`, `/li:generate-visio` (⚠ slots — AI generates content at invocation using design-spec.json as scaffold)

## Anti-patterns

- **Apply per-format design fidelity in generate-design** — that's the design_pass_hook's job (format-builder-owned). Generate-design produces the baseline only.
- **Override palette per-section** — palette is shared across all sections + formats. Per-section overrides only if explicitly requested.
- **Hard-code template path** — always pull from `~/.lintel/brand/<format>-templates/<default>` or operator-specified path.
- **Skip `design_pass_hook` field** — format-builders depend on it to know which agent to invoke for format-fidelity pass.

## Failure recovery

- Palette resolution fails on `--palette <name>`: fall back to default, flag in design-spec frontmatter
- Template missing + no `--use-defaults`: exit BLOCKED with instruction to drop template in `~/.lintel/brand/<format>-templates/`
- Validation rotation-rule violation: regenerate affected sections with varied layouts, flag if repeats

## Recommended next steps after invocation

- For full chain: orchestrator triggers format-builders next (Step 7)
- For solo-iteration: operator inspects design-spec.json, tweaks layout assignments manually, then invokes format-builder
- For palette A/B-test: re-invoke with different `--palette` + diff the two design-spec.json files

