| name | template-author |
| description | Add or edit ready-to-edit start-screen templates in `ComposerTemplateLibrary` (`CW-71` / `CW-77`). Use whenever the user asks to create, generate, design, or edit a template; recreate App Store marketing screenshots as a template (provide an `apps.apple.com` URL or numeric track id and this skill will inspect every Apple platform the app ships on); generate a background image for a template (landscapes, minimalist arches, mesh gradients, geometric, grain, or any other plate-fill imagery); add a new entry to the start-screen chooser; or update an existing builder, scene, palette, or copy. Pairs with the `screenshot-format` skill for the `.screenshot` JSON schema, and respects the workspace `screen-specs` and `test-driven-design` rules. |
Template author
ScreenShotComposer's start-screen templates ship in two backing forms that merge into one chooser catalog:
- Bundled file-based templates — preferred for all new work. Each template is a
.screenshot-shaped directory under ScreenShotComposer/Templates/<template-id>/ (auto-bundled into Resources/Templates/<id>/ by a Copy bundled Templates build phase) plus a template.json sidecar that holds chooser metadata. BundledTemplateStore discovers them at first access; the catalog merge in ComposerTemplateLibrary.templates makes them appear alongside legacy code-based templates with no extra wiring.
- Code-backed templates — historical surface in
ComposerTemplateLibrary.swift under codeBackedTemplates + enum Builders. Still supported for the original 11 templates but do not add new ones here. A bundled file with the same id shadows a code-backed entry, so the migration path is "bake → drop the Swift code".
Three scenes ship per template by default: .home, .feature, .socialProof (the App Store standard 3-pager — CW-77).
Empty bezels auto-fill with a device wallpaper
A bezeled image layer that has no embedded raster is not an empty placeholder anymore. The renderer (ImageLayerChromeView.bezeledLayer) detects the bezel id and paints a generic iPhone / iPad / Mac mesh-gradient wallpaper inside the inner rect, both in the canvas preview and in any PNG that flows through CompositionExporter (chooser thumbnails, user PNG exports, etc). Mapping logic lives in DeviceWallpaper.swift (iphone → pink/purple/blue, ipad → coral/orange/purple, mac → cobalt/navy). Custom or unrecognized bezels fall through to the legacy "drop an image here" placeholder so the user still gets the affordance.
Implication for new templates: don't bake a placeholder screenshot into the bezel when authoring — leave the layer's image empty and the wallpaper will fill it. Templates only need to embed an image inside the bezel when the design specifically calls for in-app UI (e.g. a Shortcuts mockup) rather than a generic device wallpaper. If you want the empty bezel to feel like a real device in the chooser preview, you don't have to do anything; just save with the bezel image unset.
Read the screenshot-format skill (.cursor/skills/screenshot-format/SKILL.md) before authoring or editing a template; it documents the JSON your bundled directory ultimately stores.
When to use this skill
- "Create a template" / "add a template" / "design a template that looks like X".
- "Recreate this App Store listing as a template" (with or without an
apps.apple.com URL).
- "Edit the Hero Spotlight template" / "change the social-proof page on every template" / "swap the bezel".
- "Generate a background image for this template" — landscapes, minimalist arches, mesh gradients, geometric grids, grainy textures, paper-cut shapes, or any other plate-fill imagery that a flat color or gradient can't capture.
- Adding a new template category, scene type, or palette helper.
If the user only wants to draft a one-off .screenshot document (not a reusable template), use the screenshot-format skill directly instead.
Workflow
Pick the matching path. Both paths converge on the same registration + verification steps.
Path A — Recreate an existing App Store listing
User shares an apps.apple.com URL (or any numeric track id / bundle id).
-
Inspect the listing across every Apple platform. Run:
.cursor/skills/template-author/scripts/fetch-app-store-listing.sh <url-or-id>
The script emits a single JSON object on stdout with the iPhone, iPad, and Mac search results merged (whichever the app ships on). It pulls from https://itunes.apple.com/lookup once per entity (software, iPadSoftware, macSoftware) and notes which platforms returned no result.
-
Download reference screenshots into a scratch directory you can ignore in git:
.cursor/skills/template-author/scripts/download-app-store-screenshots.sh \
<url-or-id> tmp/<template-id>-refs
Files land as tmp/<template-id>-refs/<platform>/<NN>-<resolution>.png. Use the 0x0w URL substitution the script applies to grab full-resolution captures, not the 643px thumbnails.
-
Read the listing to derive template intent: headline copy style, dominant background colors, background style (flat? gradient? landscape photo? minimalist arches? mesh gradient? geometric pattern?), device pose (centered? tilted pair? multi-device?), whether the listing leans editorial (left-aligned text) or hero (oversized headline). Look at the actual PNGs you just downloaded — the iTunes metadata only gives you titles and URLs.
-
If the source background isn't a flat color or simple gradient, plan to generate a matching background image. See references/background-image-generation.md for the visual-language catalog (landscapes, arches, mesh, geometric, grain, paper-cut), prompt templates, plate sizing, and builder wiring. You'll execute the actual generation in Common steps below.
-
Continue at Common steps below (starts at step 3 — pick a template id).
Path B — From scratch (no App Store URL)
-
Get a clear design intent from the user: category (.devices, .hero, .minimal, .multiDevice, .editorial), mood (palette, gradient direction), device pose for the home + feature scenes, and any custom copy they want over the boilerplate in Builders.copy(for:scene:).
-
Continue at Common steps below.
Common steps
New templates ship as bundled .screenshot directories under ScreenShotComposer/Templates/<template-id>/. The recommended authoring loop is:
-
Pick a template id — short, lowercase, hyphenated, unique against ComposerTemplateLibrary.templates. Examples: pastel-arches, hero-spotlight. The id is used as the directory name, in the chooser, in Recents storage, and in preview filenames.
-
Update the spec first (per screen-specs skill). Add a planned row in docs/product-specs/screens/composer-workspace.md under the existing CW-71 / CW-77 block, calling out the new template id, category, and what it brings to the catalog. Note any embedded background art so reviewers know to look at the new Templates/<id>/assets/ PNGs.
-
Compose the template visually inside the running app.
bin/launch-mac
Use File → New to start from the closest existing template (or a blank document), then iterate on plate background, layers, copy, and bezels until each platform's three scenes look right. Save the document somewhere you can find — every embedded asset (background images, screenshots inside bezels, decorative artwork) ends up in the .screenshot package's assets/ directory, so the saved document is already most of the bundled template.
-
Promote the saved .screenshot document into a bundled template. A .screenshot package and a bundled template directory share the same on-disk shape — info.json + mac.json / iphone.json / ipad.json + assets/ + optional QuickLook/. Copy the saved package into the templates directory and rename it (drop the .screenshot extension) so it becomes ScreenShotComposer/Templates/<template-id>/. Then add a template.json sidecar:
{
"id": "<template-id>",
"label": "Display Label",
"summary": "One-line caption shown in the chooser row.",
"category": "editorial"
}
Valid category values mirror ComposerTemplateCategory: devices, hero, minimal, multiDevice, editorial. (Unknown values fall back to editorial at load time.)
-
(Migrating a code-backed template?) Use the bake helper instead of hand-copying. Add the template id to ScreenShotComposerTests/BundledTemplateBaker.swift's queue, then run:
bin/bake-bundled-templates
The helper runs the legacy Swift Builders.* for every (platform, scene), serializes the result through ScreenshotPackageSerialization, and copies the resulting directory into ScreenShotComposer/Templates/<id>/. After the directory is committed, delete the matching Builders.* function, the catalog row in codeBackedTemplates, the builderFor(templateID:) switch case, and the homeWireframe / featureWireframe / copy(for:scene:) entries for that id — the bundled file shadows the code path and the dead code becomes pure clutter.
-
Add a unit test (per test-driven-design skill). Add coverage to ScreenShotComposerTests/BundledTemplateStoreTests.swift (or model on it) — verify the new template is discovered by BundledTemplateStore.shared, lands in ComposerTemplateLibrary.templates, ships compositions for every supported platform, and (if it embeds background image bytes) carries .imageFill on the pinned background layer with non-empty imageData.
-
Re-render the chooser previews:
bin/refresh-template-previews
This writes <template-id>-<platform>-<scene>.png (3 scenes × 3 platforms = 9 PNGs per template) into ScreenShotComposer/TemplatePreviews/. Commit those PNGs alongside the new Templates/<id>/ directory.
-
Run tests + a launch smoke check:
bin/test-mac
bin/launch-mac
-
Finalize the spec: flip the planned row to complete and link the new test in the Tests column. Refresh docs/product-specs/screens/README.md if the overall status moved.
Editing an existing template
For bundled templates (the only kind you should add new work to):
- Open
ScreenShotComposer/Templates/<id>/ as a .screenshot package in the running app (rename the directory to add a temporary .screenshot extension if needed, then rename back after saving).
- Edit visually, save, and copy the saved package back over the bundled directory. The
template.json sidecar persists across saves; copy it back if you overwrote it.
- For mass tweaks (palette swap across every scene, copy edit), edit the JSON directly — the schema is documented in the screenshot-format skill.
For code-backed templates (legacy), see workflows/edit-template.md for the focused checklist (find the right builder, decide whether the change is per-scene or shared, when to retitle vs replace, when to bump preview PNGs).
Anatomy & helpers (references)
- references/template-anatomy.md —
ComposerTemplate metadata, Builders.* dispatch (legacy code path), TemplateBuildContext helpers (frame, centeredFrame, primaryBezelID, primaryAspect).
- references/palette-and-typography.md — Shared color tokens (
Builders.inkText, lightText, mutedDarkText, mutedLightText, goldStar), font scale conventions, socialProofScene palette.
- references/background-image-generation.md — When to generate a plate background image, visual-language catalog (landscapes, arches, mesh, geometric, grain, paper-cut, photography), prompt patterns, plate sizing, file naming. For bundled templates the generated PNG lives in the saved
.screenshot package's assets/ dir, not under TemplateBackgrounds/.
- references/previews-and-registration.md — How
bin/refresh-template-previews works, where chooser sidebar buckets are defined, Recents storage.
Workflows
Helper scripts
scripts/fetch-app-store-listing.sh <url-or-id> — Lookup the app on iTunes Search across all three Apple software entities; print merged JSON (one block per platform) with screenshot URLs and basic metadata.
scripts/download-app-store-screenshots.sh <url-or-id> <output-dir> — Download every screenshot at full resolution into <output-dir>/<platform>/.
Both scripts depend only on curl and jq (standard on macOS).