---
name: studio
description: Conversational, CMS-free authoring. Turn a brief ("new release for my song at <link>, suspenseful synthwave") into a published page — resolve platform links, fetch art, draft schema-valid content in voice, validate, build, review, and (only on explicit approval) deploy. Use when the user wants to create and ship a release/blog/review/profile page by talking.
---

# /studio — brief → published page

You orchestrate the whole arc as a conversation. Lean on the same contract as /new-post,
plus link resolution, art backfill, a checklist, and a human-gated deploy.

## 1. Brief → classify
Read the user's brief. Infer the content type (release/editorial/review/profile). Extract
everything provided: title, links, facts, art links, the desired vibe/tone.

## 2. Resolve links (real metadata, not fabrication)
For each platform URL in the brief, call `resolveOEmbed(url)` from `templates/oembed.js`
(Spotify/SoundCloud/YouTube) to get real title, artist (`author`), and a cover `thumbnail`.
Register every platform URL as a media **source** (the build/`media.js` turn these into the
player switcher). If `fetch` is unavailable, ask the user to paste title/artist instead.

## 3. Backfill art (cover resolution order)
1. An explicit local file the user dropped in `assets/img/` → use it.
2. A Dropbox/Google Drive/any share link → `fetchAsset(url, "img/<slug>.<ext>")`
   from `tools/fetch-asset.js` (public links; http/https only).
   fetchAsset only downloads from known art hosts (Dropbox/Drive/Spotify/SoundCloud/YouTube).
   For any other host, ask the human to confirm, then pass it as an explicit `allowHosts`
   option for that one fetch — or have them paste/drop the file into `assets/img/` instead.
   Do NOT edit the `DEFAULT_ALLOW` list in `tools/fetch-asset.js` on the fly.
3. The oEmbed `thumbnail` from step 2 → fetch it as the cover.
4. None → leave it out; the build's **missing-assets** report will flag it (or generate a
   placeholder SVG into `assets/img/`).

## 4. Checklist (the todo)
Maintain a checklist and write it to `drafts/<slug>.todo.md` (create the `drafts/` directory if
needed; it's working scratch). Mark each item: ✅ have · 🤖 fetched · ⬜ need from you · ✍️ I'll
write. Human-only
facts (ISRC/BPM/key/credits/exact dates) stay ⬜ and `null` until supplied — never invented.

## 5. Draft → validate → build
Write `content/<folder>/<slug>.json` in the producer's voice (`voice/voice-guide.md`; obey the
banlist; enums only). Run `npm run build` — it validates (Ajv gate) and reports facts-to-confirm
+ missing-assets. Fix and rebuild until clean; do not hand back broken JSON. For a **review**, follow
`docs/reviews.md` (verdict-first, honest pros/cons in the fields, a screenshot-stub figure, no fabricated price/specs).

## 5b. Layout & vibe (the appearance wizard)
Choose the page's `appearance` WITH the human, in plain language — see `docs/layouts.md` for the full
menu, recipes, and the wizard questions. Ask 1–2 simple questions (or infer from their brief's vibe
words), then set `appearance: { layout, background, bgImage?, surface, fx[] }`. Default to nothing
(clean) if unsure; everything is opt-in and degrades gracefully — never force a vibe they didn't ask
for. Images for `background:"image"` go in `assets/img/bg/`.

## 6. Review gate
Present: the preview path `dist/<segment>/<slug>/index.html`, the **facts-to-confirm** list,
**missing-assets**, and the resolved metadata for confirm/override. Get the human's OK.
Note: URL **segment** differs from source **folder** for editorial — source folder `posts/` → URL `/blog/<slug>/`
(segments: release→releases, editorial→**blog**, review→reviews, profile→profile). Previews live at
`dist/<segment>/<slug>/`, not `dist/<folder>/`.

## 7. Deploy — ONLY on explicit approval
NEVER deploy automatically. After the human says "ship it", hand off to the **`/deploy`** skill — it owns
preflight, `wrangler login`, project create, the publish, and the custom domain. Inline shortcut if you're
already set up: `npx wrangler pages deploy` (reads `wrangler.toml`). Approval is per-publish, not standing.
If Bash/wrangler is unavailable, stop at the built `dist/` and hand off.

## Guardrails
- Facts vs. prose: write prose; never fabricate identifiers. oEmbed metadata is real, fine to use.
- Agent-agnostic: degrade gracefully (no fetch → ask; no wrangler → build-only).
- Security: asset fetch is http/https only and writes only into `assets/`.
