app-design — A Downloadable Skill for Designing Apps from Scratch

A complete Claude skill that takes you from "I have an app idea" to a structured design plan: brief, screen list, user flows, and a full design token set. All files inline below — copy, paste, restart, ready in 2 minutes. No zip.

app-design takes you from “I have an app idea” to a structured design plan in one prompt: a filled brief, a screen list, the top user flows, and a full set of design tokens (color ramps, type scale, spacing, radius). The output is markdown + JSON you can hand to a developer or a designer without any further translation.

This page contains every file the skill ships with. Copy each block into the matching path under ~/.claude/skills/app-design/, restart Claude Code, and the skill auto-fires the next time you ask Claude to design an app. Every code block has a Copy button.

At a glance

Field Value
Name app-design
Version 1.0.0
Author GHStudio
License MIT
Files 6 files, ~8 KB total
Runtime Python 3.8+ (for token generator)
Triggers on “design an app”, “design system for…”, “wireframes for…”, “what screens does my app need”, “design tokens from this color”
Does NOT trigger on logo design, illustration generation, app code generation

Folder layout

text
~/.claude/skills/app-design/
├── SKILL.md
├── README.md
├── scripts/
│   └── generate-tokens.py
├── templates/
│   ├── design-brief.md
│   └── screen-spec.md
└── reference/
    └── principles.md

Step 1 — Create the folders

macOS / Linux:

bash
mkdir -p ~/.claude/skills/app-design/{scripts,templates,reference}

Windows (PowerShell):

powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\skills\app-design\scripts","$env:USERPROFILE\.claude\skills\app-design\templates","$env:USERPROFILE\.claude\skills\app-design\reference" | Out-Null

Step 2 — Paste each file

SKILL.md

Path: ~/.claude/skills/app-design/SKILL.md

markdown
---
name: app-design
description: Use this skill whenever the user wants to design a new mobile or web app — producing a design brief, listing screens, mapping user flows, or generating design tokens (colors, type, spacing) from a primary color or brand. Trigger on phrases like "design an app", "design system for", "wireframes for", "user flow for", "what screens does my app need", "design tokens from this color". Do NOT use for visual asset generation (logos, illustrations) or for writing the actual app code.
version: 1.0.0
---

# app-design

Helps the user go from "I have an app idea" to a structured design plan: a brief, a screen list, user flows, and a complete design token set.

## When invoked

Ask three questions in one turn (don't drag the user through Q&A):

1. What does the app do? (one paragraph)
2. Who's the user, and what's their primary context?
3. Brand color or aesthetic? (hex code or vibe)

Then produce, in this order:

### 1. Design brief
Read templates/design-brief.md. Fill every field from the user's input. Where information is missing, write `TBD: <specific question>` rather than guessing. Confirm with user before continuing.

### 2. Screen list
For the use cases in the brief, list 5-10 screens. Format each line as:

    screen-name → primary action → entry from / exit to

Order by user journey, not alphabetically.

### 3. User flows
For the top 2 user goals, write 5-7 step ordered lists referencing screens by name from step 2. Note branches inline.

### 4. Design tokens
Run: `python scripts/generate-tokens.py --primary "{hex}" --style "{minimal|playful|professional}"`
Save the JSON output as tokens.json. Default style is `minimal` if unclear.

### 5. Output
Save all four artifacts to `<app-slug>/` in the working directory:
- brief.md
- screens.md
- flows.md
- tokens.json

Print folder path. Offer next steps: per-screen specs (templates/screen-spec.md) or hand-off to a frontend skill.

## When NOT to use
- Logos / illustrations / asset generation
- Writing app code
- UX research / interviews
- Redesigning from screenshots

For deeper rationale, the agent reads reference/principles.md on demand.

scripts/generate-tokens.py

Path: ~/.claude/skills/app-design/scripts/generate-tokens.py

python
#!/usr/bin/env python3
"""Generate a complete design token set from a primary hex color + style preset.

Usage:
    python generate-tokens.py --primary "#3B82F6" --style minimal
    python generate-tokens.py --primary "#FF6B6B" --style playful --accent-override "#4ECDC4"
"""
import argparse, colorsys, json, sys


def hex_to_rgb(h):
    h = h.lstrip("#")
    if len(h) != 6:
        raise ValueError(f"Expected 6-digit hex, got: {h!r}")
    return tuple(int(h[i:i+2], 16) / 255 for i in (0, 2, 4))


def rgb_to_hex(r, g, b):
    return "#{:02X}{:02X}{:02X}".format(
        max(0, min(255, int(round(r * 255)))),
        max(0, min(255, int(round(g * 255)))),
        max(0, min(255, int(round(b * 255)))),
    )


def color_ramp(hex_color):
    r, g, b = hex_to_rgb(hex_color)
    h, _, s = colorsys.rgb_to_hls(r, g, b)
    targets = [
        (50,  0.97, 0.30), (100, 0.93, 0.45), (200, 0.85, 0.55),
        (300, 0.74, 0.65), (400, 0.62, 0.78), (500, 0.50, 0.90),
        (600, 0.42, 0.85), (700, 0.34, 0.75), (800, 0.26, 0.65),
        (900, 0.18, 0.55), (950, 0.11, 0.50),
    ]
    out = {}
    for step, target_l, sat_factor in targets:
        nr, ng, nb = colorsys.hls_to_rgb(h, target_l, min(1.0, s * sat_factor + 0.05))
        out[str(step)] = rgb_to_hex(nr, ng, nb)
    return out


def complement(hex_color):
    r, g, b = hex_to_rgb(hex_color)
    h, l, s = colorsys.rgb_to_hls(r, g, b)
    nr, ng, nb = colorsys.hls_to_rgb((h + 0.5) % 1.0, l, s)
    return rgb_to_hex(nr, ng, nb)


NEUTRAL = {
    "50":"#FAFAFA","100":"#F4F4F5","200":"#E4E4E7","300":"#D4D4D8",
    "400":"#A1A1AA","500":"#71717A","600":"#52525B","700":"#3F3F46",
    "800":"#27272A","900":"#18181B","950":"#09090B",
}

TYPE_SCALES = {
    "minimal": {"xs":"12px","sm":"14px","base":"16px","lg":"18px","xl":"20px","2xl":"24px","3xl":"30px","4xl":"36px","5xl":"48px"},
    "playful": {"xs":"13px","sm":"15px","base":"17px","lg":"20px","xl":"24px","2xl":"30px","3xl":"38px","4xl":"48px","5xl":"60px"},
    "professional": {"xs":"11px","sm":"13px","base":"15px","lg":"17px","xl":"20px","2xl":"24px","3xl":"30px","4xl":"36px","5xl":"48px"},
}

SPACING = {"0":"0","1":"4px","2":"8px","3":"12px","4":"16px","5":"20px","6":"24px","8":"32px","10":"40px","12":"48px","16":"64px","20":"80px","24":"96px"}
RADIUS  = {"none":"0","sm":"4px","md":"8px","lg":"12px","xl":"16px","2xl":"24px","full":"9999px"}


def main():
    p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    p.add_argument("--primary", required=True, help="Primary hex color, e.g. #3B82F6")
    p.add_argument("--style", default="minimal", choices=list(TYPE_SCALES))
    p.add_argument("--accent-override", default=None)
    a = p.parse_args()

    accent_seed = a.accent_override or complement(a.primary)
    out = {
        "$meta": {"primary": a.primary.upper(), "style": a.style, "accent": accent_seed.upper(), "version": "1.0.0"},
        "color": {"primary": color_ramp(a.primary), "accent": color_ramp(accent_seed), "neutral": NEUTRAL},
        "type": TYPE_SCALES[a.style], "spacing": SPACING, "radius": RADIUS,
    }
    json.dump(out, sys.stdout, indent=2, ensure_ascii=False)
    sys.stdout.write("\n")


if __name__ == "__main__":
    main()

templates/design-brief.md

Path: ~/.claude/skills/app-design/templates/design-brief.md

markdown
# {{app_name}} — Design Brief

## What it is
{{one-paragraph product description}}

## Primary user
{{persona: role, context, the constraint they work under}}

## Top 3 jobs the user comes to do
1. {{job 1 — verb + object + outcome}}
2. {{job 2}}
3. {{job 3}}

## Out of scope for v1
- {{thing we're explicitly not building yet}}

## Brand
- **Vibe:** {{minimal | playful | professional | other}}
- **Primary color:** {{hex}}
- **Accent color:** {{optional hex}}

## Platforms
{{ios | android | web | desktop}}

## Constraints
- **Accessibility:** WCAG {{AA | AAA}}
- **Performance:** {{N seconds to first interaction}}
- **Localisation:** {{single | multi}}
- **Offline:** {{required | nice-to-have | not needed}}

## Success metric
{{the one number that says v1 worked}}

templates/screen-spec.md

Path: ~/.claude/skills/app-design/templates/screen-spec.md

markdown
# {{screen_name}}

**Purpose.** {{one sentence}}
**Entry from.** {{screen-name(s)}}
**Primary action.** {{the single thing this screen makes easy}}
**Secondary actions.** {{up to 3}}

**Key elements.**
- Header: {{title, back button, action}}
- Body: {{content shape}}
- Footer: {{nav, CTA}}

**States.**
- Default: {{loaded data}}
- Empty: {{no data + CTA to create}}
- Error: {{cause + next step}}
- Loading: {{skeleton ≥ 300ms or spinner < 300ms}}

**Exit to.** {{screen-name(s) by action}}
**A11y notes.** {{tab order, aria-labels, touch targets}}

reference/principles.md

Path: ~/.claude/skills/app-design/reference/principles.md

markdown
# Design heuristics — read on demand

## Hierarchy
- One primary action per screen. If two compete, one is wrong.
- Type scale ratio ≥ 1.2x between adjacent sizes.
- Body text contrast ≥ 4.5:1 (AA), ≥ 7:1 (AAA).

## Spacing
- 8px base unit. All padding/margin = multiples of 8 (or 4 for fine work).
- Default to one step MORE spacing than feels right; tighten only if disconnected.

## States — every screen has 4
1. Default
2. Empty (CTA, never just "nothing here")
3. Error (name cause + give next step)
4. Loading (skeleton ≥ 300ms; spinner < 300ms; nothing < 100ms)

## Mobile
- Touch targets ≥ 44x44 (Apple) / 48x48dp (Android)
- Bottom sheets, not modal overlays
- Primary CTAs in lower 60% of screen

## Forms
- One column. Always.
- Labels above inputs, not inline placeholders.
- Errors adjacent to the field, not at the top.
- Validate on blur, not on every keystroke.

## Cognitive load
- Max 7 ± 2 items per choice list.
- Progressive disclosure for advanced options.
- Sensible defaults for everything optional.

## A11y floor (non-negotiable)
- Visible focus indicator on every interactive element
- Programmatic labels on all form fields
- Alt text on all images (or `alt=""` for decorative)
- Exactly one `<h1>`; heading levels never skip
- Color is never the sole carrier of meaning

Step 3 — Restart Claude Code

Skills register on session start. Quit and re-open Claude Code (or run /clear if your CLI version supports skill reload mid-session).

Step 4 — Try it

In a fresh chat:

text
Design an app for casual runners to track outdoor workouts.
The user is on their phone, often with one hand, sometimes
in cold weather with gloves. Brand color #FF6B6B, playful vibe.

Claude routes to app-design, asks no further questions (you gave it everything), and produces brief, screen list, flows, and a tokens.json with the FF6B6B ramp + cyan accent — all in one folder, ready to commit.

The token generator on its own

Useful even outside the skill flow. Pipe its output into your project’s CSS variables:

bash
python ~/.claude/skills/app-design/scripts/generate-tokens.py \
  --primary "#3B82F6" \
  --style minimal > my-app/tokens.json

Three style presets: minimal, playful, professional. Use --accent-override if you don’t want auto-complement.

Customising

  • Pin a default brand. Edit step 4 of SKILL.md — hard-code --primary and --style so the skill stops asking.
  • Extra tokens. Open generate-tokens.py — add elevation/shadow scales, motion durations, breakpoints. The output JSON shape is documented at the top of the file.
  • Fork it. Drop the folder back as app-design-acme/ with a different name: in the frontmatter so they don’t collide.

For the underlying mechanics: Anatomy of a Skill, Writing Skill Descriptions, How Skill Trigger Matching Actually Works, Bundling Scripts and Reference Docs.