---
name: platformdtc-theme
description: Build, edit, check, preview and publish PlatformDTC storefront themes (Builder2 template JSON, header/footer groups, custom React sections in theme/custom). Use whenever the user works on a PlatformDTC store's theme, storefront pages, sections, blocks or template JSON — through the PlatformDTC MCP server or the `dtc theme` CLI.
---

# PlatformDTC theme development

A PlatformDTC storefront theme is **Builder2**: pages are JSON data rendered by React sections.
You change a real store's theme workspace — the same files the dashboard editor opens and the
publish pipeline deploys. Work as if a customer will see every change, because after a publish
they will.

Tools you may have:

- **Remote MCP** (OAuth): `https://api.platformdtc.com/mcp/theme` has only the theme tools;
  `https://api.platformdtc.com/mcp` has the same theme tools plus the rest of the store. Theme tools:
  `list_themes`, `create_dev_theme`, `get_theme`, `delete_theme`, `get_theme_manifest`,
  `read_theme_files`, `write_theme_files`, `delete_theme_files`, `check_theme`, `preview_theme`,
  `publish_theme`, `get_publish_status`, `list_theme_versions`, `rollback_theme`,
  `get_section_schemas`.
- **CLI `dtc`** (install: `curl -fsSL https://platformdtc.com/cli/install.sh | sh`, or on Windows
  `irm https://platformdtc.com/cli/install.ps1 | iex`):
  `dtc theme init|pull|push|dev|check|share|publish|versions|rollback`.

## The loop — follow it in order

1. **Pick the theme, never the live one by default.** `list_themes`. Work on a `development` theme:
   reuse one or `create_dev_theme` (without `from_theme_id` it copies the live theme). Only touch the
   `main` (live) theme if the user explicitly asks for it in this conversation.
   - **Check `builder_version`.** Agents can edit only `builder_version: 2` themes. If the live theme
     is `1` (the classic page builder), do not copy it: `BUILDER1_NOT_SUPPORTED` lists the store's
     Builder2 themes. Show the user those options and ask which one to build on, telling them it is a
     different design and publishing it replaces the whole storefront. Then `create_dev_theme` with
     `from_theme_id`. If the store has no Builder2 theme, the user creates one in the dashboard
     (Themes → New theme) first.
2. **Read the manifest first.** `get_theme_manifest` before any read or write. It lists the editable
   files with their `checksum`, the `platform_paths` you must never write, the limits, and the
   available `section_types` / `block_types` (type, name, presets). Do not guess paths or types.
3. **Learn before writing anything unfamiliar.** The theme docs are at
   https://docs.platformdtc.com/themes/overview (template JSON, settings types, custom sections,
   limits, publish). Before writing template JSON, call `get_section_schemas` with
   the exact types you will use (up to 10 per call) and use only setting ids and option values it
   returns. A section lists its blocks; fetch a block it defines inline (`local: true`) as
   `"<section>:<block>"`. Prefer an existing section type over a new custom section when one fits.
4. **Read, then write only editable paths.**
   - Template data: `templates/*.json`, `sections/*-group.json`, `config/settings_data.json`.
   - Merchant code: `theme/custom/**`, `app/page.tsx`, `app/layout.tsx`, `app/not-found.tsx`,
     `components/store-layout.tsx`, `components/store-providers.tsx`, `styles/merchant.css`,
     `public/**`.
   - Never write a `platform` path (`PLATFORM_OWNED`) or an ignored path (`node_modules/`, `.next/`,
     `out/`, `.git/`, `data/`). Never write `theme/custom/index.ts` — it is generated.
   - Send `checksum_before` (from the manifest or your last read) on every write. On `CONFLICT`,
     re-read the file, merge, and write again — never overwrite blindly.
   - At most 50 files and 2 MiB per file per write.
5. **Custom sections are React in `theme/custom`.** A new section is
   `theme/custom/sections/<type>.tsx` (blocks: `theme/custom/blocks/<type>.tsx`), `<type>` matching
   `[a-z0-9-]{1,48}`, registered as `custom-<type>`. The file exports a **static**
   `export const schema = { type: "custom-<type>", name, settings: [...], presets: [...] }` and a
   default React component taking `{ id, settings, blocks, sq }`. Runtime imports only from `react`, `@/theme`, `@/lib/*` and files under
   `theme/custom/`; `import type` from `@/theme/builder2/types`. No new npm packages.
6. **Validate → fix → retry, at most 3 rounds.** Run `check_theme` (remote) or `dtc theme check`
   (local). Fix every error, then check again. After 3 failed rounds, **stop** and report the
   remaining errors verbatim with file and line. Never say the work is done while check reports an
   error. Treat warnings as work to do unless the user decides otherwise.
7. **Preview.** `preview_theme` (or `dtc theme dev`) and give the user the URL to look at.
8. **Publish only when all of these are true:** check passes with zero errors in `publish` mode,
   the user explicitly asked to publish this theme, and you have told them what will change. The
   store may require approval: a `pending_approval` result means the merchant approves it in the
   dashboard — say so; do not retry. Follow `get_publish_status` to the end and report the outcome.

## No placeholders — ever

What you write goes live. When real content is missing, render **nothing**, and ask the user for
the real content if it matters.

- No lorem ipsum, "Your Store", "Coming soon", "Product name" or any sample copy — in components,
  in schema defaults and presets, and in template JSON. That includes copy written to the merchant,
  such as "Say what you sell, in one line" or "Describe your returns window here", which some
  starting themes ship with: when you find it on a page you are editing, ask the user for the real
  text, or remove the setting's value so nothing renders. Check blocks publish while it remains.
- No link without a destination: no `href="#"`, no `href=""`, no `/` standing in for an unknown page.
  Unknown destination → no link.
- No image without a real `src`: no empty box, grey square or "No image" label. No image → no
  element.
- No invented numbers: no hard-coded star ratings, review counts, "10,000+ customers", stock levels
  or badges. Absent data → the element is absent.
- Claims (ingredients, results, shipping, guarantees) must come from the user or the store's real
  data, never from you.

## Reporting

End with: the theme (name, id, role), the files changed, the final check result (errors/warnings),
the preview URL, and — if published — the publish status. If anything was left unfixed, list it
first.
