前端

Open Design

作者 nexu-io93,546

🎨 Best DeepSeek Harness Design Plugin. The open-source Claude Design alternative. 🖥️ Local-first desktop app. 🖼️ Your coding agent becomes the design engine: prototypes, landing pages, dashboards, slides, images & video — real files, HTML/PDF/PPTX/MP4 export. 🤖 Claude Code / Codex / Cursor / DeepSeek Harness / OpenCode & 20+ CLIs via BYOK.

agent-skillsai-designbyokclaude-code-for-designclaude-designcodex-design
安装命令
npx skills add nexu-io/open-design
在 GitHub 打开
支持的客户端
Claude CodeCursorVS Code CopilotWindsurf

Skill 详情

<h1 align="center">OpenDesign: The open-source Claude Design alternative</h1>

OpenDesign Cloud — the official model service. One recharge to use both agent and image models inside OpenDesign: GPT, Claude, and DeepSeek for agents; GPT Image 2.0, Seedream 5.0 Pro, and Nano Banana 2.0 for images.

🚀 DeepSeek V4 Flash and V4 Pro are now available. Put top-tier intelligence to work across prototypes, decks, design systems, and everyday agent tasks. OpenDesign members can use both models without limits for two weeks, directly inside the app.

🧩 DeepSeek Harness is now supported. Connect DeepSeek's official dsh agent harness to OpenDesign as a native runtime, with structured thinking, tool calls, model discovery, cancellation, and session resume. Generated files stay in the OpenDesign workflow for live preview and delivery.

<p align="center"> <img src="https://repo-assets.open-design.ai/resources/images/hero.png" alt="OpenDesign hero banner — the headline &quot;The open-source Claude Design alternative&quot; over a classical scene of columns and robed figures on a digital-code backdrop, with stat cards for design systems, plugins, coding agents, and media providers" width="100%" /> </p> <p align="center"> <a href="https://open-design.ai/?utm_source=github&utm_medium=referral&utm_content=readme_website">Website</a> · <a href="https://open-design.ai/?utm_source=github&utm_medium=referral&utm_content=readme_download">Download</a> · <a href="https://open-design.ai/cloud/?utm_source=github&utm_medium=referral&utm_content=readme_cloud">OpenDesign Cloud</a> · <a href="https://discord.gg/mHAjSMV6gz">Discord</a> · <a href="https://x.com/OpenDesignHQ">Follow @OpenDesignHQ</a> </p> <p align="center"> <a href="https://github.com/nexu-io/open-design/releases"><img alt="release" src="https://img.shields.io/github/v/release/nexu-io/open-design?style=flat&color=blueviolet&label=release&include_prereleases&display_name=tag" /></a> <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat" /></a> <a href="https://discord.gg/mHAjSMV6gz"><img alt="discord" src="https://img.shields.io/discord/1479002485040480266?style=flat&logo=discord&logoColor=white&label=discord&color=5865F2&cacheSeconds=3600" /></a> <a href="QUICKSTART.md"><img alt="quickstart" src="https://img.shields.io/badge/quickstart-3%20commands-green?style=flat" /></a> </p> <p align="center"><b>English</b> · <a href="docs/i18n/README.es.md">Español</a> · <a href="docs/i18n/README.pt-BR.md">Português</a> · <a href="docs/i18n/README.de.md">Deutsch</a> · <a href="docs/i18n/README.fr.md">Français</a> · <a href="docs/i18n/README.zh-CN.md">简体中文</a> · <a href="docs/i18n/README.zh-TW.md">繁體中文</a> · <a href="docs/i18n/README.ko.md">한국어</a> · <a href="docs/i18n/README.ja-JP.md">日本語</a> · <a href="docs/i18n/README.ar.md">العربية</a> · <a href="docs/i18n/README.ru.md">Русский</a> · <a href="docs/i18n/README.uk.md">Українська</a> · <a href="docs/i18n/README.tr.md">Türkçe</a> · <a href="docs/i18n/README.th.md">ภาษาไทย</a></p>

What is OpenDesign

🎨 The open-source Claude Design alternative.  🖥️ Local-first native desktop app for macOS and Windows.  ⚡ Composable skills, brand-grade DESIGN.md design systems, and ready-to-use plugins.  🖼️ Generates web · desktop · mobile prototypes, live dashboards / artifacts, decks, images, video, plus HyperFrames motion graphics. 🔒 Sandboxed iframe preview · HTML / PDF / PPTX / MP4 export.  🤖 Runs on DeepSeek Harness (dsh) · Claude Code · OpenClaw · Codex · Cursor · OpenCode · Qwen · Copilot · Amp · Hermes · Kimi · Antigravity and 26 distinct local CLI executables, or any OpenAI-compatible endpoint via BYOK.

OpenDesign is what you get when the agent-native loop Anthropic shipped with Claude Design — discover the brief, lock the direction, stream the artifact, critique, deliver — stops being closed and becomes a filesystem of functional skills, rendering design templates, design systems, and plugins that the coding agents already on your laptop can read, write, and remix. Your CLI becomes the design engine, your laptop becomes the studio, and your team's DESIGN.md becomes the brand contract.

It's also the Figma alternative for the agent era — instead of pushing pixels on a canvas, it delivers single-page artifacts in real CSS, real fonts, real components, exported straight to HTML / PDF / PPTX / MP4 — already shaped by your design system, already runnable inside the agent you use every day.


Product tour

A quick look at the core OpenDesign workflow. Start from Home with a brief, explore reusable skills in Plugins, and turn brand references into a Design System. Then enter a project's Studio to create and refine prototypes, decks, mobile apps, images, documents, and HyperFrames in one place.

Core pages

<table> <tr> <td valign="top"> <img src="docs/screenshots/product-tour/home.png" alt="OpenDesign Home page with artifact types, brief composer, model picker, and examples" /><br/> <sub><b>Home</b> — choose an artifact type, enter a brief, and set the design system, working directory, and model before you start.</sub> </td> </tr> </table> <table> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/plugins.png" alt="OpenDesign Plugins page showing the official skills catalog" /><br/> <sub><b>Plugins</b> — browse official skills by category, search the catalog, and launch a workflow with <code>Try it</code>.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/design-system.png" alt="Shopify design system preview inside OpenDesign Studio" /><br/> <sub><b>Design System</b> — extract and refine a brand's visual language, preview the result, and create with it in the same workspace.</sub> </td> </tr> </table>

Studio — many artifact types in one project

Inside a project's Studio, the conversation, generated files, and live preview stay together across six artifact types:

<table> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-prototype.png" alt="Web prototype preview in OpenDesign Studio" /><br/> <sub><b>Prototype</b> — generate or reconstruct web experiences, inspect the rendered page, and iterate with the agent in place.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-deck.png" alt="Multi-slide deck preview in OpenDesign Studio" /><br/> <sub><b>Deck</b> — create multi-slide presentations, review thumbnails and speaker notes, and export when ready.</sub> </td> </tr> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-mobile-app.png" alt="Mobile app artifact preview in OpenDesign Studio" /><br/> <sub><b>Mobile app</b> — generate and polish mobile interfaces in a device preview, with the conversation, output files, and next-step actions beside it.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-image.png" alt="Generated image preview in OpenDesign Studio" /><br/> <sub><b>Image</b> — generate visual assets from the project conversation, preview the result at full size, then download or open it.</sub> </td> </tr> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-document.png" alt="Multi-page document preview in OpenDesign Studio" /><br/> <sub><b>Document</b> — create polished, multi-page guides and editorial documents, inspect the rendered layout, and export or share when ready.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/product-tour/studio-hyperframe.png" alt="HyperFrame motion graphic preview in OpenDesign Studio" /><br/> <sub><b>HyperFrame</b> — build code-driven motion graphics, preview the animation inside Studio, and export the finished video.</sub> </td> </tr> </table>

Platform Compatibility

OpenDesign connects to mainstream coding agents in two ways: skills, CLI, and MCP for agents that consume OD, plus native runtime adapters for agents that OD launches directly. DeepSeek Harness is a first-class native runtime through the official dsh CLI, with structured streaming, model discovery, cancellation, and session resume.

Coding agent / platform         Status   Quick setup                   
Claude Code✅ Supportedod mcp install claude
Claude Desktop✅ Supported¹od mcp install claude-desktop
Codex CLI✅ Supportedod mcp install codex
DeepSeek Reasonix✅ Supportedod mcp install reasonix
DeepSeek Harness✅ Native runtimeod agent setup deepseek-harness
Raven✅ Supportedod mcp install raven
Cursor✅ Supportedod mcp install cursor
VS Code + GitHub Copilot✅ Supportedod mcp install copilot
GitHub Copilot CLI✅ Supportedod mcp install copilot
OpenCode✅ Supportedod mcp install opencode
OpenClaw✅ Supportedod mcp install openclaw
Antigravity✅ Supportedod mcp install antigravity
Cline✅ Supportedod mcp install cline
Trae✅ Supportedod mcp install trae
Kimi CLI✅ Supportedod mcp install kimi
Kiro✅ Supportedod mcp install kiro
Pi Agent✅ Supportedod mcp install pi
Mistral Vibe CLI✅ Supportedod mcp install vibe
Hermes Agent✅ Supportedod mcp install hermes

For DeepSeek Harness, install the official dsh CLI first, then select it in OpenDesign or run od agent setup deepseek-harness to install/repair OD's connection component. For MCP integrations: od mcp install <agent> --print for a dry-run preview · --uninstall to remove · full list with od mcp install --help.

¹ Automatic MCP configuration for Claude Desktop is currently supported on macOS and Windows only.

<p align="center"> <img src="https://repo-assets.open-design.ai/resources/images/coding-agents.png" alt="The 26 coding-agent CLIs OpenDesign supports — DeepSeek Harness · Claude Code · Codex · OpenCode · Hermes · Antigravity · Vela · Grok Build · Kimi · Cursor Agent · Qwen · Qoder · GitHub Copilot · Pi · Kiro · Kilo · Mistral Vibe · DeepSeek · Reasonix · Aider · Amp · CodeBuddy · Mimo · AtomCode · Devin · Trae" width="100%" /> </p>

No CLI installed? The BYOK proxy at POST /api/proxy/{anthropic,openai,azure,google,ollama,senseaudio}/stream gives you the same loop (no process spawn) — paste baseUrl + apiKey + model, with presets for OpenAI, Atlas Cloud, Anthropic, Azure OpenAI, Google Gemini, Ollama, LM Studio, vLLM, or any OpenAI-compatible endpoint. Atlas Cloud uses https://api.atlascloud.ai/v1 with your own key and OpenAI-compatible model ids such as qwen/qwen3.5-flash. Per-target SSRF protection blocks internal IPs / link-local / CGNAT at the daemon edge.

Runtime definitions live in apps/daemon/src/runtimes/defs/, with registration and shared stream handling under apps/daemon/src/runtimes/. See docs/agent-adapters.md for the adapter contract.


Demo

Four core product categories, all rendered by a coding agent running on your laptop. Click a thumbnail to see the real example.

1 · Prototypes — web · desktop · mobile

The default output surface. Single-page HTML artifacts that read your DESIGN.md and render in a sandboxed iframe.

<table> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/skills/dating-web.png" alt="Web prototype dating-web" /><br/> <sub><b>Web prototype</b> — an editorial dashboard with scrollbars, KPIs, and charts. Rendered straight from <code>design-templates/dating-web/</code>.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/skills/gamified-app.png" alt="Gamified app" /><br/> <sub><b>Mobile app prototype</b> — a three-screen gamified flow with XP ribbons and quest detail. Hand off straight to Cursor / Codex / Claude Code to turn into React/Next/Vue.</sub> </td> </tr> </table>

2 · Live artifacts & dashboards

Live dashboards, decision rooms, KPI walls — single-page artifacts that pull data through a tweaks panel and stay editable in place.

<table> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/skills/live-dashboard.png" alt="Live dashboard" /><br/> <sub><b>Live dashboard</b> — an editable KPI wall whose tweaks panel surfaces the parameters worth nudging. The agent emits a manifest, and the iframe re-renders without a reload.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/skills/research-decision-room.png" alt="Decision room" /><br/> <sub><b>Decision room</b> — a multi-source briefing artifact for product / research / ops meetings.</sub> </td> </tr> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/skills/github-dashboard.png" alt="GitHub dashboard" /><br/> <sub><b>GitHub-style dashboard</b> — repo metrics presented as a live artifact.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/skills/flowai-live-dashboard-template.png" alt="Flow live dashboard" /><br/> <sub><b>Flow live-dashboard template</b> — a domain-specific KPI template, branded through the active <code>DESIGN.md</code>.</sub> </td> </tr> </table>

3 · Decks — magazine decks, weekly updates, pitches

<table> <tr> <td width="50%" valign="top"> <img src="docs/screenshots/07-magazine-deck.png" alt="Magazine deck (guizang-ppt)" /><br/> <sub><b>Deck mode (guizang-ppt)</b> — magazine layouts, WebGL hero, P0/P1/P2 checklists. Bundled verbatim from <a href="https://github.com/op7418/guizang-ppt-skill"><code>op7418/guizang-ppt-skill</code></a> with its original license preserved.</sub> </td> <td width="50%" valign="top"> <img src="docs/screenshots/skills/deck-swiss-international.png" alt="Swiss deck" /><br/> <sub><b>Swiss International-style deck</b> — grid-anchored, monochrome accents. One of <b>15 deck templates</b> and <b>36 themes</b> under <code>design-templates/html-ppt-*/</code>.</sub> </td> </tr> </table>

Every deck exports to HTML (single file, inlined assets), PDF (browser print, deck-aware), PPTX (agent-driven skill), ZIP (archive), or Markdown.

4 · Images — gpt-image-2, ImageRouter, custom API

<table> <tr> <td width="20%" valign="top"><img src="https://cms-assets.youmind.com/media/1776662673014_nf0taw_HGRMNDybsAAGG88.jpg" alt="Illustrated city food map" /><br/><sub><b>Illustrated city food map</b><br/>Hand-drawn editorial travel poster</sub></td> <td width="20%" valign="top"><img src="https://cms-assets.youmind.com/media/1777453149026_gd2k50_HHCSvymboAAVscc.jpg" alt="Cinematic elevator scene" /><br/><sub><b>Cinematic elevator scene</b><br/>Single-frame editorial still</sub></td> <td width="20%" valign="top"><img src="https://cms-assets.youmind.com/media/1777453164993_mt5b69_HHDoWfeaUAEA6Vt.jpg" alt="Cyberpunk anime portrait" /><br/><sub><b>Cyberpunk portrait</b><br/>Profile avatar — neon face text</sub></td> <td width="20%" valign="top"><img src="https://cms-assets.youmind.com/media/1776661968404_8a5flm_HGQc_KOaMAA2vt0.jpg" alt="3D stone staircase evolution" /><br/><sub><b>3D stone staircase</b><br/>Hewn-stone infographic</sub></td> <td width="20%" valign="top"><img src="https://cms-assets.youmind.com/media/1777453184257_vb9hvl_HG9tAkOa4AAuRrn.jpg" alt="Glamorous portrait" /><br/><sub><b>Glamorous portrait</b><br/>Editorial studio shot</sub></td> </tr> </table>

93 ready-to-replicate prompts live in prompt-templates/ — preview thumbnails, full prompt body, target model, aspect ratio, and source attribution. One click drops a brief into the composer.

5 · Video & HyperFrames — agent-native motion graphics

HyperFrames is HeyGen's open-source, agent-native video framework, integrated as a first-class citizen in OpenDesign. The agent writes HTML + CSS + GSAP, and HyperFrames renders it to a deterministic MP4 via headless Chrome + FFmpeg. Pair it with Seedance 2.0 for cinematic t2v / i2v, Veo 3 / Sora 2 / Kling 2 for routed model variants, and Suno v5 / Lyria 2 for the audio layer.

<table> <tr> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-saas-product-promo-30s.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/app-showcase.png" alt="SaaS promo" /></a><br/><sub><b>30s SaaS product promo</b> · 16:9 · UI 3D reveals</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-tiktok-karaoke-talking-head.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/tiktok-follow.png" alt="TikTok karaoke" /></a><br/><sub><b>TikTok karaoke talking-head</b> · 9:16 · TTS + word-synced captions</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-brand-sizzle-reel.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/logo-outro.png" alt="Brand sizzle reel" /></a><br/><sub><b>30s brand sizzle reel</b> · 16:9 · audio-reactive kinetic type</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-data-bar-chart-race.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/data-chart.png" alt="Bar chart race" /></a><br/><sub><b>Bar chart race</b> · 16:9 · NYT-style data infographic</sub></td> </tr> <tr> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-flight-map-route.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/nyc-paris-flight.png" alt="Flight map" /></a><br/><sub><b>Flight map</b> · 16:9 · Apple-style route reveal</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-logo-outro-cinematic.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/logo-outro.png" alt="Logo outro" /></a><br/><sub><b>4s cinematic logo outro</b> · 16:9 · piece-by-piece assembly + bloom</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-money-counter-hype.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/apple-money-count.png" alt="Money counter" /></a><br/><sub><b>$0 → $10K money counter</b> · 9:16 · Apple-style hype</sub></td> <td width="25%" valign="top"><a href="prompt-templates/video/hyperframes-website-to-video-promo.json"><img src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/instagram-follow.png" alt="Website to video" /></a><br/><sub><b>Website-to-video</b> · 16:9 · captures the site at 3 viewports</sub></td> </tr> </table>

11 HyperFrames templates + 39 Seedance prompts ship with the repo. Catalog thumbnails © HeyGen; the framework is Apache-2.0. The OD-specific render workflow (composition cache, sandbox-exec workaround, MP4-as-chip) is detailed in design-templates/hyperframes/.


Why OpenDesign

In April 2026, Anthropic released Claude Design — the first time an LLM stopped writing prose and started delivering design artifacts directly. It went viral. But it stayed closed-source, paid-only, cloud-only, locked to Anthropic's model, Anthropic's skills, Anthropic's surface. No checkout, no self-host, no Vercel deploy, no swap-in-your-own-agent.

OpenDesign (OD) is the open-source alternative. Same loop, same artifact-first mental model, none of the lock-in:

  • 🤖 Agent-native, model-agnostic. We don't ship an agent. The claude / codex / cursor-agent / copilot / hermes / kimi already on your PATH are the design engine. Swap with one click.
  • 🧠 Brand-grade by default. Every render reads the active package's DESIGN.md as the core brand contract. 151 design-system packages ship with the repo; legacy packages may be DESIGN.md-only, while newer packages can add manifest.json, tokens.css, components, assets, and provenance. Drop a folder in, the picker finds it.
  • 🖥️ Local-first, BYOK at every layer. Native desktop apps for macOS (Apple Silicon + Intel) and Windows (x64). Linux AppImage on the optional release lane. Product analytics and session replay are consent-gated; scrubbed safety and reliability telemetry is always on. Before describing daemon data paths, contributors and operators MUST read AGENTS.mdDaemon data directory contract. This README MUST NOT restate it.
  • 🌍 Composable on four planes. Plugins carry runnable workflows · functional skills carry agent behavior · design templates carry rendering blueprints · design systems carry the brand. All four use portable, versionable directories that anyone can author and publish.
  • 🔁 Refresh an existing codebase. Hand a git repo + DESIGN.md to the agent and it refactors your real components to the brand spec. Dedicated plugins migrate Figma / Pencil workflows into React / Next.js / Vue code.
  • 🔒 Privacy by conviction. Everything runs where your data lives — your laptop, your team's server, your Vercel project. When the network is needed, the BYOK proxy is SSRF-guarded.

Comparison

Claude DesignFigmaLovable / v0 / BoltOpenDesign
Open source✅ Apache-2.0
Self-host / desktop✅ macOS + Windows + Docker + Vercel web
Agent-native (runs in your CLI)Anthropic onlyCloud agent only✅ 25 CLIs + BYOK
Brand-grade DESIGN.mdProprietaryTheme JSONLimited tokens✅ 151 systems shipped
Skills / plugins / templatesClosedPlugin storeClosed✅ 100+ functional skills · rendering templates · 277 plugins
HyperFrames (HTML→MP4)✅ First-class
Refresh an existing repo to brand✅ via agent + DESIGN.md
Minimum billingPro / Max / TeamPro / OrgPro / TeamBYOK · any compatible endpoint

Quick start

🖥️ Download the desktop app (recommended — zero config)

The fastest way to use OpenDesign. No Node, no pnpm, no clone.

After install: the app auto-detects every coding-agent CLI on your PATH, loads 100+ functional skills, the separate rendering-template catalog, and 151 design systems, and lets you type a brief in the entry view.

🤖 Install into your coding agent


hyperframes


name: hyperframes description: Create video compositions, animations, title cards, overlays, captions, voiceovers, audio-reactive visuals, and scene transitions in HyperFrames HTML. Use when asked to build any HTML-based video content, add captions or subtitles synced to audio, generate text-to-speech narration, create audio-reactive animation (beat sync, glow, pulse driven by music), add animated text highlighting (marker sweeps, hand-drawn circles, burst lines, scribble, sketchout), or add transitions between scenes (crossfades, wipes, reveals, shader transitions). Covers composition authoring, timing, media, and the full video production workflow. For CLI commands (init, lint, preview, render, transcribe, tts) see the hyperframes-cli skill. triggers:

  • "hyperframes"
  • "html video"
  • "video composition"
  • "interactive video"
  • "captions"
  • "tts video"
  • "kinetic typography"
  • "html in canvas"
  • "drawElementImage"
  • "html shader"
  • "vfx-iphone-device"
  • "vfx-liquid-glass"
  • "vfx-portal" od: mode: video surface: video scenario: video preview: type: html design_system: requires: false example_prompt: | A 5-second product reveal: a minimal high-end product on a clean cream surface, soft side light, slow camera push-in, restrained motion, no text overlays.

HyperFrames

HTML is the source of truth for video. A composition is an HTML file with data-* attributes for timing, a GSAP timeline for animation, and CSS for appearance. The framework handles clip visibility, media playback, and timeline sync.

OpenDesign integration (load-bearing for this surface)

When this skill runs inside OpenDesign (i.e. $OD_PROJECT_DIR is set), the output flow is fixed: only the rendered .mp4 should land in the project root. Composition source files (hyperframes.json, meta.json, index.html, assets) belong inside a hidden cache directory so they don't clutter the user's FileViewer or the chat's "produced files" chips.

Render workflow inside OD — fast path:

For most OD requests ("test video", "5s product reveal", "demo clip"), do NOT write the composition HTML from scratch. Use Open Design's deterministic scaffold and edit only what the prompt actually changes. The "author from scratch" path costs minutes of model output and silent chat-tool time; the scaffold path costs seconds.

# 1. Pick a hidden cache slot. Dotfile prefix → OD's project file
#    listing skips it, so the source files never clutter the chat.
COMP_REL=".hyperframes-cache/$(date +%s)-$(openssl rand -hex 2)"
COMP="$OD_PROJECT_DIR/$COMP_REL"

# 2. Get an immediately-renderable scaffold (hyperframes.json,
#    meta.json, index.html with GSAP CDN + window.__timelines.main
#    already registered). Open Design writes these files itself; it does
#    not run `hyperframes init`, consult an npx cache, or install global skills.
"$OD_NODE_BIN" "$OD_BIN" media scaffold \
  --project "$OD_PROJECT_ID" \
  --composition-dir "$COMP_REL"

# 3. Edit ONLY $COMP/index.html — change `data-duration` on the root
#    if you need a non-default length, swap the placeholder palette
#    in <style>, add 1–3 clip <div>s for text/imagery, and append the
#    matching GSAP tweens inside the existing
#    `window.__timelines["main"] = gsap.timeline({paused:true})` block.
#    Keep edits minimal; the scaffold is already valid HF.

# 4. Dispatch render through the OD daemon. Do NOT run HyperFrames
#    `render` from this shell — the daemon runs it for you in an
#    unsandboxed process. (Many agent CLIs, Claude Code in particular,
#    wrap Bash in macOS sandbox-exec under which puppeteer's Chrome
#    subprocess hangs partway through frame capture. The daemon process
#    is unsandboxed, so renders complete reliably.)
#
#    The dispatcher returns within ~1s with a {taskId}; drive the
#    render to completion by looping `"$OD_NODE_BIN" "$OD_BIN" media wait <taskId>` calls.
#    Each call long-polls up to 25s (well under your shell tool's
#    default 30s cap) and exits 0/2/5 to signal done/running/failed.
out=$("$OD_NODE_BIN" "$OD_BIN" media generate \
  --project "$OD_PROJECT_ID" \
  --surface video \
  --model hyperframes-html \
  --output "<descriptive-name>.mp4" \
  --composition-dir "$COMP_REL")
ec=$?
task_id=$(printf '%s\n' "$out" | tail -1 | jq -r '.taskId // empty')
since=$(printf '%s\n' "$out" | tail -1 | jq -r '.nextSince // 0')
while [ "$ec" -eq 2 ] && [ -n "$task_id" ]; do
  out=$("$OD_NODE_BIN" "$OD_BIN" media wait "$task_id" --since "$since")
  ec=$?
  since=$(printf '%s\n' "$out" | tail -1 | jq -r '.nextSince // '"$since")
done
[ "$ec" -ne 0 ] && { echo "$out" >&2; exit "$ec"; }

Each generate and each wait call lasts at most ~25s, so the agent shell tool's default ~30s cap never fires. Progress lines from HF (Capturing frame N/M) stream to stderr live throughout the loop. When the render finishes, the last stdout line is {"file": { "name": "<output>", "size": …, "kind": "video", … }} — quote file.name in your reply so the user knows what was produced.

Skip the Visual Identity Gate inside OD. The HARD-GATE section below (under "Approach") tells you to read DESIGN.md / visual-style.md or stop and ask 3 mood questions before writing any composition. That gate is for standalone HF projects. OD projects already have their own design-system layer — the user picked their visual direction at project creation time. For an OD test render, default to: dark canvas (#0b0b0f), one warm accent (#ffb76b), one cool accent (#7da4ff), restrained motion. Only ask for stylistic input if the user's prompt is too vague to even pick a subject (very rare).

When to skip the scaffold and write from scratch: only when the user explicitly asks for something the blank template clearly can't host (e.g. multi-composition timelines, audio-reactive overlays, captions synced to a TTS track they've already generated). For everything else, init + edit is the default path.

The lighter HF subcommands you CAN still run from your own shell (they don't need to spawn Chrome):

  • "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" lint "$COMP" — validate composition before dispatch
  • "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" transcribe <audio> — generate captions
  • "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" tts <text> — generate narration

Reserve the daemon dispatch for render/inspect/preview (anything Chrome-bound). After authoring the composition under .hyperframes-cache/, render it by calling "$OD_NODE_BIN" "$OD_BIN" media generate --surface video --model hyperframes-html --composition-dir <rel>. The daemon runs the Chrome-bound HyperFrames render outside your shell sandbox and streams progress back to you. Do not run HyperFrames render yourself.

Do NOT drop hyperframes.json / meta.json / index.html in the project root; OD's file listing scans recursively and the user would see three unrelated files appear in the chat.

For CLI options beyond render (lint, preview, transcribe, tts, inspect, benchmark) call them directly from your shell tool when the task warrants it (e.g., generate TTS audio into the cache before referencing it from the composition).

Approach

Before writing HTML, think at a high level:

  1. What — what should the viewer experience? Identify the narrative arc, key moments, and emotional beats.
  2. Structure — how many compositions, which are sub-compositions vs inline, what tracks carry what (video, audio, overlays, captions).
  3. Timing — which clips drive the duration, where do transitions land, what's the pacing.
  4. Layout — build the end-state first. See "Layout Before Animation" below.
  5. Animate — then add motion using the rules below.

For small edits (fix a color, adjust timing, add one element), skip straight to the rules.

Visual Identity Gate

<HARD-GATE> Before writing ANY composition HTML, you MUST have a visual identity defined. Do NOT write compositions with default or generic colors.

Check in this order:

  1. DESIGN.md exists in the project? → Read it. Use its exact colors, fonts, motion rules, and "What NOT to Do" constraints.
  2. visual-style.md exists? → Read it. Apply its style_prompt_full and structured fields. (Note: visual-style.md is a project-specific file. visual-styles.md is the style library with 8 named presets — different files.)
  3. User named a style (e.g., "Swiss Pulse", "dark and techy", "luxury brand")? → Read visual-styles.md for the 8 named presets. Generate a minimal DESIGN.md with: ## Style Prompt (one paragraph), ## Colors (3-5 hex values with roles), ## Typography (1-2 font families), ## What NOT to Do (3-5 anti-patterns).
  4. None of the above? → Ask 3 questions before writing any HTML:
    • What's the mood? (explosive / cinematic / fluid / technical / chaotic / warm)
    • Light or dark canvas?
    • Any specific brand colors, fonts, or visual references? Then generate a minimal DESIGN.md from the answers.

Every composition must trace its palette and typography back to a DESIGN.md, visual-style.md, or explicit user direction. If you're reaching for #333, #3b82f6, or Roboto — you skipped this step. </HARD-GATE>

For motion defaults, sizing, entrance patterns, and easing — follow house-style.md. The house style handles HOW things move. The DESIGN.md handles WHAT things look like.

Layout Before Animation

Position every element where it should be at its most visible moment — the frame where it's fully entered, correctly placed, and not yet exiting. Write this as static HTML+CSS first. No GSAP yet.

Why this matters: If you position elements at their animated start state (offscreen, scaled to 0, opacity 0) and tween them to where you think they should land, you're guessing the final layout. Overlaps are invisible until the video renders. By building the end state first, you can see and fix layout problems before adding any motion.

The process

  1. Identify the hero frame for each scene — the moment when the most elements are simultaneously visible. This is the layout you build.
  2. Write static CSS for that frame. The .scene-content container MUST fill the full scene using width: 100%; height: 100%; padding: Npx; with display: flex; flex-direction: column; gap: Npx; box-sizing: border-box. Use padding to push content inward — NEVER position: absolute; top: Npx on a content container. Absolute-positioned content containers overflow when content is taller than the remaining space. Reserve position: absolute for decoratives only.
  3. Add entrances with gsap.from() — animate FROM offscreen/invisible TO the CSS position. The CSS position is the ground truth; the tween describes the journey to get there.
  4. Add exits with gsap.to() — animate TO offscreen/invisible FROM the CSS position.

Example

/* scene-content fills the scene, padding positions content */
.scene-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 120px 160px;
  gap: 24px;
  box-sizing: border-box;
}
.title {
  font-size: 120px;
}
.subtitle {
  font-size: 42px;
}
/* Container fills any scene size (1920x1080, 1080x1920, etc).
   Padding positions content. Flex + gap handles spacing. */

WRONG — hardcoded dimensions and absolute positioning:

.scene-content {
  position: absolute;
  top: 200px;
  left: 160px;
  width: 1920px;
  height: 1080px;
  display: flex; /* ... */
}
// Step 3: Animate INTO those positions
tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
tl.from(".logo", { scale: 0.8, opacity: 0, duration: 0.4, ease: "power2.out" }, 0.3);

// Step 4: Animate OUT from those positions
tl.to(".title", { y: -40, opacity: 0, duration: 0.4, ease: "power2.in" }, 3);
tl.to(".subtitle", { y: -30, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.1);
tl.to(".logo", { scale: 0.9, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.2);

When elements share space across time

If element A exits before element B enters in the same area, both should have correct CSS positions for their respective hero frames. The timeline ordering guarantees they never visually coexist — but if you skip the layout step, you won't catch the case where they accidentally overlap due to a timing error.

What counts as intentional overlap

Layered effects (glow behind text, shadow elements, background patterns) and z-stacked designs (card stacks, depth layers) are intentional. The layout step is about catching unintentional overlap — two headlines landing on top of each other, a stat covering a label, content bleeding off-frame.

Data Attributes

All Clips

AttributeRequiredValues
idYesUnique identifier
data-startYesSeconds or clip ID reference ("el-1", "intro + 2")
data-durationRequired for img/div/compositionsSeconds. Video/audio defaults to media duration.
data-track-indexYesInteger. Same-track clips cannot overlap.
data-media-startNoTrim offset into source (seconds)
data-volumeNo0-1 (default 1)

data-track-index does not affect visual layering — use CSS z-index.

Composition Clips

AttributeRequiredValues
data-composition-idYesUnique composition ID
data-startYesStart time (root composition: use "0")
data-durationYesTakes precedence over GSAP timeline duration
data-width / data-heightYesPixel dimensions (1920x1080 or 1080x1920)
data-composition-srcNoPath to external HTML file

Composition Structure

Sub-compositions loaded via data-composition-src use a <template> wrapper. Standalone compositions (the main index.html) do NOT use <template> — they put the data-composition-id div directly in <body>. Using <template> on a standalone file hides all content from the browser and breaks rendering.

Sub-composition structure:

<template id="my-comp-template">
  <div data-composition-id="my-comp" data-width="1920" data-height="1080">
    <!-- content -->
    <style>
      [data-composition-id="my-comp"] {
        /* scoped styles */
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <script>
      window.__timelines = window.__timelines || {};
      const tl = gsap.timeline({ paused: true });
      // tweens...
      window.__timelines["my-comp"] = tl;
    </script>
  </div>
</template>

Load in root: <div id="el-1" data-composition-id="my-comp" data-composition-src="compositions/my-comp.html" data-start="0" data-duration="10" data-track-index="1"></div>

Video and Audio

Video must be muted playsinline. Audio is always a separate <audio> element:

<video
  id="el-v"
  data-start="0"
  data-duration="30"
  data-track-index="0"
  src="video.mp4"
  muted
  playsinline
></video>
<audio
  id="el-a"
  data-start="0"
  data-duration="30"
  data-track-index="2"
  src="video.mp4"
  data-volume="1"
></audio>

Timeline Contract

  • All timelines start { paused: true } — the player controls playback
  • Register every timeline: window.__timelines["<composition-id>"] = tl
  • Framework auto-nests sub-timelines — do NOT manually add them
  • Duration comes from data-duration, not from GSAP timeline length
  • Never create empty tweens to set duration

Rules (Non-Negotiable)

Deterministic: No Math.random(), Date.now(), or time-based logic. Use a seeded PRNG if you need pseudo-random values (e.g. mulberry32).

GSAP: Only animate visual properties (opacity, x, y, scale, rotation, color, backgroundColor, borderRadius, transforms). Do NOT animate visibility, display, or call video.play()/audio.play().

Animation conflicts: Never animate the same property on the same element from multiple timelines simultaneously.

No repeat: -1: Infinite-repeat timelines break the capture engine. Calculate the exact repeat count from composition duration: repeat: Math.ceil(duration / cycleDuration) - 1.

Synchronous timeline construction: Never build timelines inside async/await, setTimeout, or Promises. The capture engine reads window.__timelines synchronously after page load. Fonts are embedded by the compiler, so they're available immediately — no need to wait for font loading.

Never do:

  1. Forget window.__timelines registration
  2. Use video for audio — always muted video + separate <audio>
  3. Nest video inside a timed div — use a non-timed wrapper
  4. Use data-layer (use data-track-index) or data-end (use data-duration)
  5. Animate video element dimensions — animate a wrapper div
  6. Call play/pause/seek on media — framework owns playback
  7. Create a top-level container without data-composition-id
  8. Use repeat: -1 on any timeline or tween — always finite repeats
  9. Build timelines asynchronously (inside async, setTimeout, Promise)
  10. Use gsap.set() on clip elements from later scenes — they don't exist in the DOM at page load. Use tl.set(selector, vars, timePosition) inside the timeline at or after the clip's data-start time instead.
  11. Use <br> in content text — forced line breaks don't account for actual rendered font width. Text that wraps naturally + a <br> produces an extra unwanted break, causing overlap. Let text wrap via max-width instead. Exception: short display titles where each word is deliberately on its own line (e.g., "THE\nIMMORTAL\nGAME" at 130px).

Scene Transitions (Non-Negotiable)

Every multi-scene composition MUST follow ALL of these rules. Violating any one of them is a broken composition.

  1. ALWAYS use transitions between scenes. No jump cuts. No exceptions.
  2. ALWAYS use entrance animations on every scene. Every element animates IN via gsap.from(). No element may appear fully-formed. If a scene has 5 elements, it needs 5 entrance tweens.
  3. NEVER use exit animations except on the final scene. This means: NO gsap.to() that animates opacity to 0, y offscreen, scale to 0, or any other "out" animation before a transition fires. The transition IS the exit. The outgoing scene's content MUST be fully visible at the moment the transition starts.
  4. Final scene only: The last scene may fade elements out (e.g., fade to black). This is the ONLY scene where gsap.to(..., { opacity: 0 }) is allowed.

WRONG — exit animation before transition:

// BANNED — this empties the scene before the transition can use it
tl.to("#s1-title", { opacity: 0, y: -40, duration: 0.4 }, 6.5);
tl.to("#s1-subtitle", { opacity: 0, duration: 0.3 }, 6.7);
// transition fires on empty frame

RIGHT — entrance only, transition handles exit:

// Scene 1 entrance animations
tl.from("#s1-title", { y: 50, opacity: 0, duration: 0.7, ease: "power3.out" }, 0.3);
tl.from("#s1-subtitle", { y: 30, opacity: 0, duration: 0.5, ease: "power2.out" }, 0.6);
// NO exit tweens — transition at 7.2s handles the scene change
// Scene 2 entrance animations
tl.from("#s2-heading", { x: -40, opacity: 0, duration: 0.6, ease: "expo.out" }, 8.0);

Animation Guardrails

  • Offset first animation 0.1-0.3s (not t=0)
  • Vary eases across entrance tweens — use at least 3 different eases per scene
  • Don't repeat an entrance pattern within a scene
  • Avoid full-screen linear gradients on dark backgrounds (H.264 banding — use radial or solid + localized glow)
  • 60px+ headlines, 20px+ body, 16px+ data labels for rendered video
  • font-variant-numeric: tabular-nums on number columns

When no visual-style.md or animation direction is provided, follow house-style.md for aesthetic defaults.

Typography and Assets

  • Fonts: Just write the font-family you want in CSS — the compiler embeds supported fonts automatically. If a font isn't supported, the compiler warns.
  • Add crossorigin="anonymous" to external media
  • For dynamic text overflow, use window.__hyperframes.fitTextFontSize(text, { maxWidth, fontFamily, fontWeight })
  • All files live at the project root alongside index.html; sub-compositions use ../

Editing Existing Compositions

  • Read the full composition first — match existing fonts, colors, animation patterns
  • Only change what was requested
  • Preserve timing of unrelated clips

Output Checklist

  • "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" lint and "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" validate both pass
  • "$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" inspect passes, or every reported overflow is intentionally marked
  • Contrast warnings addressed (see Quality Checks below)
  • Layout issues addressed (see Quality Checks below)
  • Animation choreography verified (see Quality Checks below)

Quality Checks

Visual Inspect

hyperframes inspect runs the composition in headless Chrome, seeks through the timeline, and maps visual layout issues with timestamps, selectors, bounding boxes, and fix hints. Run it after lint and validate:

"$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" inspect
"$OD_NODE_BIN" "$OD_HYPERFRAMES_BIN" inspect --json

Failures usually mean text is spilling out of a bubble/card, a fixed-size label is clipping dynamic copy, or text has moved off the canvas. Fix by increasing container size or padding, reducing font size or letter spacing, adding a real max-width so text wraps inside the container, or using window.__hyperframes.fitTextFontSize(...) for dynamic copy.

Use --samples 15 for dense videos and --at 1.5,4,7.25 for specific hero frames. Repeated static issues are collapsed by default to avoid flooding agent context. If overflow is intentional for an entrance/exit animation, mark the element or ancestor with data-layout-allow-overflow. If a decorative element should never be audited, mark it with data-layout-ignore.

hyperframes layout is the compatibility alias for the same check.

Contrast

hyperframes validate runs a WCAG contrast audit by default. It seeks to 5 timestamps, screenshots the page, samples background pixels behind every text element, and computes contrast ratios. Failures appear as warnings:

⚠ WCAG AA contrast warnings (3):
  · .subtitle "secondary text" — 2.67:1 (need 4.5:1, t=5.3s)

If warnings appear:

  • On dark backgrounds: brighten the failing color until it clears 4.5:1 (normal text) or 3:1 (large text, 24px+ or 19px+ bold)
  • On light backgrounds: darken it
  • Stay within the palette family — don't invent a new color, adjust the existing one
  • Re-run hyperframes validate until clean

Use --no-contrast to skip if iterating rapidly and you'll check later.

Animation Map

After authoring animations, run the animation map to verify choreography:

node design-templates/hyperframes/scripts/animation-map.mjs <composition-dir> \
  --out <composition-dir>/.hyperframes/anim-map

Outputs a single animation-map.json with:

  • Per-tween summaries: `"#card1 animates opacity+y over 0.50s. moves 23px


web-prototype


name: web-prototype description: | General-purpose desktop web prototype. Single self-contained HTML file built by copying the seed assets/template.html and pasting section layouts from references/layouts.md. Default for any landing / marketing / docs / SaaS page when no more specific skill matches. triggers:

  • "prototype"
  • "mockup"
  • "landing"
  • "single page"
  • "marketing page"
  • "homepage" od: mode: prototype platform: desktop scenario: design preview: type: html entry: index.html design_system: requires: true sections: [color, typography, layout, components]

Web Prototype Skill

Produce a single, self-contained HTML prototype using the bundled seed and layout library — not by writing CSS from scratch. The seed already encodes good defaults (typography, spacing, accent budget). Your job is to compose it.

Resource map

web-prototype/
├── SKILL.md                ← you're reading this
├── assets/
│   └── template.html       ← seed: tokens + class system + chrome (READ FIRST)
└── references/
    ├── layouts.md          ← 8 paste-ready section skeletons
    └── checklist.md        ← P0/P1/P2 self-review

Workflow

Step 0 — Pre-flight (do this once before writing anything)

  1. Read assets/template.html end-to-end — at minimum through the <style> block. The class inventory at the top of references/layouts.md lists every class that must be defined there; if one is missing, add it to <style> rather than re-defining it inline on every section.
  2. Read references/layouts.md so you know which section skeletons exist. Don't write a section type that isn't covered — pick the closest layout and adapt.
  3. Read the active DESIGN.md (already injected into your system prompt). Map its colors to the six :root variables in the seed; don't introduce new tokens.

Step 1 — Prepare index.html from the seed

Use assets/template.html as the seed for the canonical project file, normally index.html.

Replace the six :root variables with the active design system's tokens. Replace the page <title> and the topnav brand.

Step 2 — Plan the section list

Pick layouts before writing copy. Default rhythms (from layouts.md):

Page kindDefault rhythm
Landing1 hero → 3 features → 4 stats or 5 quote → custom split → 6 cta
Marketing / editorial1 hero-center → 7 log list → 6 cta
Pricing1 hero-center → 8 comparison table → 6 cta
Docs index1 hero-center → 7 log list (sections of docs) → 6 cta

State the chosen list in one sentence to the user before writing — they can redirect cheaply now and not after 200 lines of HTML.

Step 3 — Paste and fill

For each chosen layout, copy the <section> block from layouts.md into <main id="content"> of the project HTML. Replace bracketed [REPLACE] strings with real, specific copy from the user's brief. No filler — if a slot is empty, the section is the wrong choice; pick a different layout. Treat every .ph-img block as layout scaffolding and replace it when the section requires imagery, following the real-first rule below before self-checking.

Step 4 — Self-check

Run through references/checklist.md top to bottom. Every P0 item must pass before you move on. P1 items should pass; P2 are bonus.

Step 5 — Write the project file

Write the completed HTML to the canonical project file, normally index.html. Then send one short ordinary assistant summary naming the file and describing what's there. Do not output the full HTML source in chat.

Hard rules (the seed protects most of these — don't fight it)

  • Single accent, used at most twice per screen. Eyebrow + primary CTA is the default budget.
  • Display font is serif (Iowan Old Style / Charter / Georgia in the seed). Sans for body. Mono for numerics, captions, eyebrows.
  • Real imagery, never remote hotlinks. .ph-img is temporary layout scaffolding, not the default final treatment. For a named real-world referent, search/fetch the correct real image, copy it into the project, and reference it relatively; never generate, draw, or invent a substitute. For illustrative or atmospheric subjects, prefer suitable fetched real photography and use image generation only as a fallback. If no compliant asset can be acquired, keep an intentional labeled .ph-img and disclose the limitation in the delivery summary.
  • Preserve real-image geometry. Inspect each acquired image's intrinsic width and height, replace the entire .ph-img scaffold with an <img class="content-img">, and set matching width and height attributes. Never copy .ph-img, .wide, .portrait, or .square onto a real image. Content images must show the full frame; object-fit: cover is only for intentionally croppable decorative fills. The seed's .content-img rule bounds unusually tall or wide images to the viewport while keeping the other axis automatic.
  • Mobile reflow already works via the seed's media query at 920px. Don't break it by adding fixed widths.
  • data-od-id on every <section> so comment mode can target it.

Output contract

Filesystem runs use project files as the source of truth:

index.html

OpenDesign derives the preview from the written project file. Do not also emit a source-code <artifact> block for the same generation turn.

One short summary after writing the file. Nothing after.


saas-landing


name: saas-landing description: | Single-page SaaS landing with hero, features, social proof, pricing, and CTA. Respects the active DESIGN.md color/typography/layout tokens. Trigger keywords: "saas landing", "marketing page", "product landing". triggers:

  • "saas landing"
  • "marketing page"
  • "product landing" od: mode: prototype platform: desktop scenario: marketing preview: type: html entry: index.html reload: debounce-100 design_system: requires: true sections: [color, typography, layout, components] craft: requires: [typography, color, anti-ai-slop, laws-of-ux] inputs:
    • name: product_name type: string required: true
    • name: tagline type: string required: true
    • name: has_pricing type: boolean default: true
    • name: proof_count type: integer default: 3 min: 0 max: 6 parameters:
    • name: hero_density type: spacing default: 96 range: [48, 200]
    • name: accent_strength type: opacity default: 1.0 range: [0.5, 1.0] outputs: primary: index.html capabilities_required:
    • file_write

SaaS Landing Skill

Produce a single-page SaaS landing. Agent, follow this workflow exactly.

1. Read context

Before writing anything:

  • Read DESIGN.md in the current working directory. If missing, stop and ask for one.
  • Identify the color palette, typography tokens, and layout principles.
  • Note the "Agent Prompt Guide" section — it overrides any instruction here if they conflict.

2. Plan sections

Required sections, in order:

  1. Hero — logo-or-wordmark, headline (tagline input), subhead (1–2 sentences), primary CTA, secondary CTA. Use the hero_density parameter as vertical padding in px.
  2. Features — 3–6 feature tiles. Each: icon, short title, 1–2 sentence body.
  3. Social proofproof_count logos or testimonials. If 0, skip this section.
  4. Pricing — 2–3 tiers. Include only if has_pricing is true.
  5. Footer CTA — large accent-colored band with one-button call to action.
  6. Footer — minimal: links + copyright.

3. Apply design system

  • All colors must come from DESIGN.md tokens. Do not invent hex values.
  • Typography: use the declared display font for headlines, body font for everything else.
  • Layout: respect the grid, max-width, and section spacing rules.
  • Components: use declared button/card/input patterns. Do not add shadows if DESIGN.md's Depth & Elevation says minimal.
  • Accent: use the accent color only once in the hero, once in the footer CTA, and for all links. Do not flood the page.

4. Write the file

Output a single self-contained index.html with:

  • All CSS inlined in a <style> block in <head>.
  • System font fallbacks if DESIGN.md fonts aren't loadable from Google Fonts etc.
  • No external JS.
  • Semantic HTML (<header>, <main>, <section>, <footer>).
  • Each editable element tagged with data-od-id="<unique-slug>" so the host app's comment mode can target it.

5. Self-check

Before finishing, verify:

  • All text is content-meaningful, not lorem ipsum (use product_name and tagline inputs; generate plausible specific copy for the rest).
  • No broken color references (every CSS color value is in DESIGN.md's palette or a valid alpha/fallback variant).
  • Responsive breakpoints match DESIGN.md's Responsive Behavior section.
  • The page looks good at 1440w, 768w, and 375w (mentally simulate).
  • Accent used no more than twice total.

6. Done

Write only index.html. Do not generate a separate CSS file, JS file, or README.


For skill authors reading this as a reference

This is a minimal but complete skill. Structure:

saas-landing-skill/
├── SKILL.md    ← you are here
└── assets/
    └── base.html    (optional starter template; this skill doesn't use one)

Things to notice:

  • The od: front-matter block is optional for Claude-Code-only compatibility, but adding it lights up OD's typed inputs, sliders, preview metadata, and capability gating.
  • The workflow below the front-matter is plain Markdown that the agent reads as its system prompt.
  • DESIGN.md is treated as a collaborator, not an override. The skill gives the agent authority to override when the brief conflicts, but never to invent new tokens.
  • data-od-id tagging is how we wire elements to comment mode. Skills that want comment-mode compatibility must annotate their output.

See ../../docs/skills-protocol.md for the full protocol.