Produce a world-class single-page editorial landing site in the Atelier Zero visual language (Monocle / Apartamento / Études editorial collage) — the same aesthetic OpenDesign uses for its own marketing surface. The agent fills a typed `inputs.json` from a brand brief, optionally generates 16 collage assets via gpt-image-2, then runs a pure-function composer that emits a self-contained HTML file; a separate path can mirror the Astro marketing site in `apps/landing-page/`. Drop-in scroll-reveal motion and a Headroom-style sticky nav are wired automatically.
Build a single-page editorial landing site (or a slide deck — see the
sibling open-design-landing-deck skill)
in the Atelier Zero design system: warm-paper background, Inter
Tight + Playfair Display, italic serif emphasis spans, dotted hairline
rules, coral terminating dots, scroll-reveal motion, and 16 surreal
collage plates.
This is the canonical OpenDesign marketing-page recipe — the example output is the very page you see at open-design.
The skill is fully parameterized. The agent fills one typed
inputs.json from the user's brief; the composer turns that JSON +
the canonical styles.css into a deployable artifact.
inputs.json + styles.css 16 image slots
│ │
└──────────► scripts/compose.ts ◄────────────┘
│
▼
<out>/index.html (self-contained)
<out>/assets/ (PNG or SVG)
A single HTML file with all of:
prefers-reduced-motion).Run these four steps in order. The agent should complete each step before moving on, and prefer asking the user a focused question over inventing copy.
Use AskQuestion (or the equivalent in your UI) to collect the brand
brief in chunks; do not dump the entire schema.ts on the user.
Map their answers into inputs.json matching the typed shape.
The eight question groups, in order:
| Group | Schema fields | Min answers | Notes |
| :---- | :------------------------------------------------------ | :---------- | :--------------------------------------- |
| 1 | brand.{name,mark,tagline,description,location} | 5 | Mark = single glyph (Ø, ▲, ★…) |
| 2 | brand.{license,version,year,primary_url,contact_email}| 4 | URL is required; license defaults Apache-2.0 |
| 3 | nav[] (up to 5) | 3 | Optional count badges |
| 4 | hero.{label,headline,lead,primary,secondary,stats} | All | Headline as MixedText (sans+em+dot) |
| 5 | about + capabilities.cards[4] | All | 4 cards × {num,tag,title,body} |
| 6 | labs.cards[5] + method.steps[4] | All | Both grids fixed-arity |
| 7 | work.cards[2] + testimonial | All | 5 partner glyphs as inline SVG path data |
| 8 | cta + footer.{columns[4],mega} | All | Mega kicker is a MixedText like the headlines |
Open inputs.example.json for a complete
worked example (OpenDesign itself).
| Strategy | When to choose | Cost / latency |
| :---------------- | :------------------------------------------------------ | :-------------------- |
| placeholder | First pass. Demo. Slide internal. No image budget yet. | $0, <1s |
| generate | Final delivery. Brand wants original collages. | ~$0.40, ~6 min |
| bring-your-own | User has art direction PNGs. Drop them at assets_path.| $0, 0s |
Set inputs.imagery.strategy accordingly.
placeholder — frame modenpx tsx scripts/placeholder.ts <out>/assets/
Writes 16 .svg files (with .png aliases for compatibility) into
<out>/assets/. Each placeholder shows the slot id, ratio, pixel
dimensions, and the prompt hint from image-manifest.json. The
composer's <img src='./assets/hero.png'> etc. just work.
generate — gpt-image-2 modeFAL_KEY=... npx tsx scripts/imagegen.ts <inputs.json> --out=<out>/assets/
Calls fal.ai's openai/gpt-image-2 synchronous endpoint per slot.
Composes prompts as: style anchor (paper-collage editorial system)
inputs.json) + per-slot composition (e.g. cropped plaster
head + tree growing through arch). Skips slots whose target file
already exists; pass --force to re-render.Without FAL_KEY, the script prints the prompts so the operator can
route them through the /gpt-image-fal slash-command skill manually.
bring-your-ownDrop 16 PNGs matching assets/image-manifest.json filenames at
inputs.imagery.assets_path. Done.
npx tsx scripts/compose.ts <inputs.json> <out>/index.html
The composer reads inputs.json and ../styles.css, then writes one
self-contained HTML file. The page includes:
data-reveal attributes for staggered
scroll motion.apps/landing-page/app/_components/reveal-root.tsx).header.tsx).brand.primary_url).For deployable production output, fork the apps/landing-page/
package: copy it into your workspace, align app/page.tsx with content
from your inputs.json, and copy your <out>/assets/*.png into the
paths expected by app/image-assets.ts / R2 URLs. Build with
pnpm --filter @open-design/landing-page build for a static out/
export ready for any CDN.
A future iteration may bundle a composer that emits the full
apps/landing-page/tree frominputs.jsonin one command. Until then, fork-and-edit is the supported path.
Before marking done, the agent must verify:
<out>/index.html opens in a browser without console errors.display h1/h2 end.prefers-reduced-motion: reduce (DevTools → Rendering) disables
transitions cleanly.design-templates/open-design-landing/
├── SKILL.md # this contract
├── README.md # quick-start
├── schema.ts # typed inputs (single source of truth)
├── styles.css # Atelier Zero stylesheet (single source of truth)
├── inputs.example.json # OpenDesign as the worked example
├── example.html # canonical rendering (regenerated from inputs.example.json)
├── scripts/
│ ├── compose.ts # inputs.json + styles.css → index.html
│ ├── imagegen.ts # gpt-image-2 wrapper (fal.ai)
│ └── placeholder.ts # SVG paper-textured frames
└── assets/
├── *.png # 16 collage plates (OpenDesign instance)
├── image-manifest.json # slot → file/dimensions/prompt mapping
└── imagegen-prompts.md # human-readable prompt pack
design-systems/atelier-zero/DESIGN.md; extend the design system
before adding a new ramp here.data-reveal attributes from generated markup.
Without them the page goes static and feels dead.styles.css verbatim into app/globals.css so visual parity
stays one-to-one.design-systems/atelier-zero/DESIGN.md — token spec.apps/landing-page/ — deployable Astro static counterpart.design-templates/open-design-landing-deck/ — sibling slides skill that reuses this design system.Copy a source-pinned command for your client. You run it yourself.
Destination: .claude/skills/open-design-landing · pinned to the source commit
# Run from your project root
git clone https://github.com/nexu-io/open-design.git .skillboard-tmp
git -C .skillboard-tmp checkout 9881cff70e02be86c2a58130af512011ba23d4af
mkdir -p ".claude/skills"
cp -r ".skillboard-tmp/design-templates/open-design-landing" ".claude/skills/"
rm -rf .skillboard-tmpReview the source before running. This copies files into your project; it is not a one-click install and does not verify runtime safety.
sudo apt update && sudo apt install -y gitnpm install -g @anthropic-ai/claude-code# Run from your project root
git clone https://github.com/nexu-io/open-design.git .skillboard-tmp
git -C .skillboard-tmp checkout 9881cff70e02be86c2a58130af512011ba23d4af
mkdir -p ".claude/skills"
cp -r ".skillboard-tmp/design-templates/open-design-landing" ".claude/skills/"
rm -rf .skillboard-tmpDestination: .claude/skills/open-design-landing
Scanner static-checks@0.1.0 · commit 9881cff70e02. Static checks cannot prove runtime safety – review the source and the exact diff before installing. How checks work.
References parent-directory traversal, which can escape a target directory.
Evidence: ../· fingerprint fa08499e14d0113b