Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "contentstack-skills",
"source": "./",
"description": "Contentstack agent skills for CMS modeling, Delivery SDK, Live Preview, Studio, Brand Kit, Developer Hub apps, Launch, and migrations.",
"version": "0.3.0",
"version": "0.3.1",
"category": "development",
"tags": ["contentstack", "cms", "headless-cms", "studio"]
}
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "contentstack-skills",
"version": "0.3.0",
"version": "0.3.1",
"description": "Contentstack agent skills for CMS modeling, Delivery SDK, Live Preview, Studio, Brand Kit, Developer Hub apps, Launch, and migrations.",
"author": { "name": "Contentstack", "url": "https://www.contentstack.com" },
"homepage": "https://developers.contentstack.com",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "contentstack-skills",
"version": "0.3.0",
"version": "0.3.1",
"description": "Contentstack agent skills for CMS modeling, Delivery SDK, Live Preview, Studio, Brand Kit, Developer Hub apps, Launch, and migrations.",
"author": { "name": "Contentstack", "url": "https://www.contentstack.com" },
"skills": "./skills/"
Expand Down
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,70 @@

All notable changes to the Contentstack agent skills bundle. Versions match the `version` field in every plugin manifest that declares one.

## 0.3.1

### New studio guides

- **`csr-and-ssr-requirements`:** what a Studio page needs as CSR or SSR on the visitor site, the Live Preview pane, Visual Editor and the canvas.
- The five settings that must agree, plus preview mode vs builder mode.
- Where the Edit button shows, and which refetch to call on studio-react 2.0.1: `refetchData` ignores freeform compositions.
- Converting a page from one mode to the other.
- **`handle-404-pages`:** unknown URLs and bad slugs render the site's own 404 page on Next.js (App and Pages Router), Remix and React Router.
- SSR sends a real 404 through `resolveComposition`; CSR uses `noindex`.
- The 404 is decided by `isCompositionNotFound` only, so a bad token or an outage stays an error.

### Changed skills

- **`studio` matches Studio SDK 2.0.** Brought in the Studio team's latest guide fixes and checked them against the released SDK.
- Missing built-ins now surface as `COMPONENT_NOT_REGISTERED` ("Studio's own components are not registered"). The fix is to import `@contentstack/studio-react` above the fetch, not to upgrade. Updated in `troubleshoot-canvas`, `troubleshoot-ssr-rendering` and `byoc-end-to-end`.
- `upgrade-studio-sdk` has a 1.x → 2.0 section, checked by installing 1.9.0 and 2.0.1 side by side.
- It lists what 2.0 actually changed (`isCompositionNotFound`, deprecated `hasSpec`/`hasTemplate`, canvas tokens) separately from older rules that behave the same in both versions.
- It no longer points to `CHANGELOG.md` files, which the npm packages don't ship.
- `wire-studio-state` needs studio-react 1.8.0 or later, the first release that exports the state APIs.
- Key and token failures are named `STACK_NOT_FOUND_ON_HOST`. Entry lookups that miss are `URL_MATCHED_NO_ENTRY`. Log lines start with `[Contentstack Studio]`.
- `configure-csr-vs-ssr`: server styles come from `getSSRStyles`, computed on the server only. `isCompositionNotFound` is imported from `@contentstack/studio-react`. The Pages Router recipe reads `resolvedUrl`, not `req.url`. The RSC entry renders `<StudioServerComponent />`, and its components register through `@contentstack/studio-react/rsc` from a server module.
- The four-question framework is defined once, in `design-component-library`. Other guides link to it.
- Router triggers added for pinned Site Settings entries, Repeater recipes by API and App Router SSR crashes. `troubleshoot` stops after its clarifying question. `provision-studio-stack` waits for an explicit go on plan-only requests. `gate-third-party-scripts` covers analytics loader tags.
- `use-compositions-api` says Studio API service and drops two endpoints the service doesn't have.
- **`studio` end-to-end audit fixes.** The skill was followed as a customer would on a Next.js 16 app with `@contentstack/studio-react` 2.0.1. Every changed snippet is typechecked against that release.
- **Builds that look done but are wrong:**
- Every plan now includes a primitive library step.
- One Section-per-region rule replaces the conflicting reuse advice.
- `resolveComposition` resets the preview hash, so drafts no longer leak to visitors.
- The skill documents that the live site fetches only bound fields, and image props bind `.url`.
- Section Slot nodes omit the slot key, which the API rejects with a 422.
- New guides cover restarting the dev server after a registration change and a Studio-only route that sets no SEO metadata and turns 404s into 500s.
- **SDK 2.0.1:**
- `registerLazyComponent` is used for lazy registrations.
- `object` and `array` props declare their required `properties` and `items`.
- `styles` is an object of style groups.
- `isStudioEditorMode` and `isCompositionNotFound` are imported from `@contentstack/studio-react`.
- Built-in components use their SDK type names (`header`, `text`, `rich-text`, `hstack`).
- The deprecated `extendQuery` is explained, and `StudioCanvas` needs no `dynamic()` wrapper or token style tag.
- **New paths:**
- An app that already has a catch-all route.
- Live Preview without the Delivery SDK.
- Next.js 16 `proxy.ts` and Turbopack.
- Tailwind v4 `@theme` tokens and design props written in source.
- Interactive embeds in rich text.
- Static generation and caching for Studio routes.
- The canvas route layout, without a route group, and its `frame-ancestors`-only headers.
- **Compositions and MCP:**
- One canonical list recipe (Repeater, item Box, Condition Block).
- One wire-shape table for the CMA and the Compositions API.
- The compositions content type ships as JSON.
- Expected validator warnings are listed.
- The MCP content-type snapshot and the HTTP fallback are explained, with `--scope` and the hosted connector.
- Covers how to export the `csdx` OAuth token for scripts.
- The delivery-token probe path is fixed.
- **Consistency:**
- The definition of done is ten checks everywhere.
- `analyze-project-fit` runs first in the ordering hints.
- Shell snippets work in zsh.
- `verify-setup` is project-agnostic.
- The Custom Preview URL is only required when preview is opened from an entry.
- Example nodes carry all seven keys.

## 0.3.0

### New skills
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Use `--list` to see every skill, or leave out `--skill` to install them all. The
| `launch-sync-environment-variables-from-env-example` | Sync Launch environment variables from .env.example | Launch | Comparing a local `.env.example` with Launch environment variables and patching missing keys without printing secrets. |
| `launch-trigger-and-monitor-launch-deployments` | Trigger and Monitor Launch Deployments | Launch | Triggering Launch deployments, polling deployment status, retrieving failure logs, and summarizing likely causes and next steps. |
| `migration-companion` | Contentstack Migration Companion | Developer Experience | Guided Contentful-to-Contentstack migration workflow covering prerequisites, content migration, code migration, bundled validation scripts, and completion reporting. |
| `studio` | Studio (preview) | Studio | Contentstack Studio end to end: SDK install, project provisioning, component registration, sections and templates, data binding, canvas and preview routes, verification, and troubleshooting. A router skill that loads one of 109 bundled specialist files per task. |
| `studio` | Studio (preview) | Studio | Contentstack Studio end to end: SDK install, project provisioning, component registration, sections and templates, data binding, canvas and preview routes, verification, and troubleshooting. A router skill that loads one of 111 bundled specialist files per task. |

## How it works

Expand Down
2 changes: 1 addition & 1 deletion docs/skills/studio.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Contentstack Studio (preview)
description: Build with Contentstack Studio end to end, routed to one of 109 bundled specialist guides per task.
description: Build with Contentstack Studio end to end, routed to one of 111 bundled specialist guides per task.
---

# Contentstack Studio (preview)
Expand Down
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "contentstack-skills",
"version": "0.3.0",
"version": "0.3.1",
"description": "Contentstack agent skills for CMS modeling, Delivery SDK, Live Preview, Studio, Brand Kit, Developer Hub apps, Launch, and migrations."
}
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "contentstack-skills",
"version": "0.3.0",
"version": "0.3.1",
"description": "Contentstack agent skills for CMS modeling, Delivery SDK, Live Preview, Studio, Brand Kit, Developer Hub apps, Launch, and migrations.",
"author": { "name": "Contentstack", "url": "https://www.contentstack.com" },
"homepage": "https://developers.contentstack.com",
Expand Down
30 changes: 14 additions & 16 deletions skills/studio/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,26 @@ Fallback: if `<name>.md` isn't there, try `../<name>/SKILL.md` (a host that inst

Before creating, registering, or authoring anything:

1. **Decompose first.** Never register or build a component that renders more than one piece of content. The test: does it render more than one heading / image / body / list? If yes, run [`decompose-jsx-to-atomics`](decompose-jsx-to-atomics.md) before anything else. One Section per page, or one component swallowing a whole page, is a defect, not a shortcut.
2. **Compose from atoms by default: do NOT reach for a pre-composed composite.** A palette usually contains both **atoms + layout primitives** (`*-atom-heading`, `*-stack`, `*-row`, `*-grid`, `*-section-shell`) and **composites** that already bundle a whole shape (`*-feature-card`, `*-hero`, `*-card-grid`). Dropping one composite is faster and looks identical on the canvas, and it is the wrong default: its internals are fixed in code, so the author cannot restructure it, the spacing inside it cannot be matched to a comp, and the design is no longer expressed as a composition. **Build the shape out of atoms unless the user explicitly asks to reuse an existing component.** If a composite would clearly save real work, say so and let them choose. Do not decide it silently.
3. **Reuse atoms, not shapes.** Reuse means the same `*-atom-heading` everywhere, not a ready-made card. Two things differing only in spacing are one Section plus an exposed prop, never two.
4. **Shared shells are Sections.** Header, footer, nav, menus, breadcrumbs render on every page and are the highest-value reusable pieces in any project. They are never "atomic, no binding". Their menus are **Repeaters over a field**, never hardcoded lists. Otherwise an author cannot add a menu item without a developer.
5. **One atomic prop maps to one CT field.** A single prop taking a whole object is how binding breaks: the binder recursively unwraps single-key objects for every type except `object`/`array`, so a coarse prop renders blank with no error.
<a id="section-rule"></a>

1. **The Section rule (defined here only; every other skill links to it): one Section per page region, always. Inside a Section, reuse a production component whole only when it is interactive or computes its values.**
- **Region**: a part of the page a person can point at and name (header, hero, form band, feature grid, card list, footer). A Template is a stack of these Sections, whether it is a new build or a migration, and whatever the reuse count. One Section for a whole page, or one component bound to the whole page body, is a defect.
- **Interactive**: local state, event handlers, forms, carousels, modals. Built-ins and atoms cannot express behavior, so the app's component stays whole inside its Section.
- **Computes its values**: it derives what it renders instead of printing fields (formatting, totals, sorting or filtering, a layout that depends on item count or position). Keep it whole too, or the logic has nowhere to live.
- **Everything else** (presentational markup that prints fields) is decomposed into the primitive library's atoms and layout primitives, one prop per CT field: run [`decompose-jsx-to-atomics`](decompose-jsx-to-atomics.md). The test for "everything else": does it render more than one heading / image / body / list and do nothing else? Then it is not registered whole.
2. **Plan the primitive library before any Section.** Every build has a library of atoms and layout primitives with menu-style design props and defaults ([`design-component-library`](design-component-library.md)), and Sections are composed from it. Sections built from generic boxes plus hard-coded CSS classes render, and an author cannot compose anything with them. [`plan-studio-architecture`](plan-studio-architecture.md) makes this a required step.
3. **Compose from atoms by default: do NOT reach for a pre-composed composite.** A palette usually contains both **atoms + layout primitives** (`*-atom-heading`, `*-stack`, `*-row`, `*-grid`, `*-section-shell`) and **composites** that already bundle a whole shape (`*-feature-card`, `*-hero`, `*-card-grid`). Dropping one composite is faster and looks identical on the canvas, and it is the wrong default: its internals are fixed in code, so the author cannot restructure it, the spacing inside it cannot be matched to a comp, and the design is no longer expressed as a composition. **Build the shape out of atoms unless the user explicitly asks to reuse an existing component.** If a composite would clearly save real work, say so and let them choose. Do not decide it silently.
4. **Reuse atoms, not shapes.** Reuse means the same `*-atom-heading` everywhere, not a ready-made card. Two things differing only in spacing are one Section plus an exposed prop, never two.
5. **Shared shells are Sections.** Header, footer, nav, menus, breadcrumbs render on every page and are the highest-value reusable pieces in any project. They are never "atomic, no binding". Their menus are **Repeaters over a field**, never hardcoded lists. Otherwise an author cannot add a menu item without a developer.
6. **One atomic prop maps to one CT field.** A single prop taking a whole object is how binding breaks: the binder recursively unwraps single-key objects for every type except `object`/`array`, so a coarse prop renders blank with no error.

If the user's request would skip this ("just register the page component", "make the whole page one section"), say what it costs (nothing reusable, authors can't reorder, bindings break) and propose the decomposed shape instead. Do it their way only if they confirm after hearing that.

## Standing rule: definition of done

**Also every Studio turn.** Eight deliverables decide whether what you built is usable by a marketer rather than only by a developer. Every one fails silently. The page still renders, nothing errors, and the gap surfaces only when a non-developer opens Studio:
**Also every Studio turn.** Ten deliverables decide whether what you built is usable by a marketer rather than only by a developer. They are listed once, with owners and checks, in [`complete-the-build`](complete-the-build.md). Every one fails silently: the page still renders, nothing errors, and the gap surfaces only when a non-developer opens Studio.

1. `cslp: { appendTags: true }` in the SDK init, once per project.
2. `studioAttributes` on the root + `wrap: false` in the register entry + `$prop` twins, **every** registered component.
3. `thumbnailUrl`, **every** `registerComponent` call.
4. `ui_preview`, **every** Section composition. The editor writes this for itself by screenshotting the canvas on save. **A CMA-authored Section has it empty forever** unless you supply an asset uid explicitly. So "at write time" means have the asset ready and include it, not "the create call handles it". See [`author-composition-via-api`](author-composition-via-api.md) § Section thumbnails for the three ways to do it. Scripted authoring is exactly where this gets skipped, and the only signal is a blank tile in the palette.
5. Live Preview enabled on the stack + preview token, once per project.
6. The `/canvas` route mounted, once per project.
7. **Published** to the environment the project targets, every Section and Template, and again after every tree edit. Delivery otherwise serves the old version while the CMA and canvas both look correct.
8. **Composed of Sections**: every Template. Read the saved composition back and count `section-composition` nodes. Zero means the page is one component bound to the whole body. The standing rule above already forbids that shape, and a build still reached it, because a monolith renders correctly and fails no other check here. Counting is the only thing that catches it.

Read [`complete-the-build`](complete-the-build.md) for the how and the verification block. The runnable node count is in [`build-connected-template`](build-connected-template.md) § Post-build structural check. Never report a build done with any of these outstanding. Say "created, thumbnail pending" and then finish it. State them in the plan up front too, so what the user approves is what they get.
Read that list before you plan, and again before you report done. State the ten in the plan up front, so what the user approves is what they get. Never report a build done with any of them outstanding: say "created, thumbnail pending" and then finish it.

## Standing rule: auth preflight

Expand Down
2 changes: 1 addition & 1 deletion skills/studio/adapt-collection-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Use when the production wrapper's leaf takes an object shape that can't easily b

Studio has two ways to render a CMS collection through a production wrapper. Pick before writing any adapter:

**Path A: native array prop** (`build-repeating-section` § array-prop alternative). Register the production wrapper with a `type: "array"` prop, bind that prop to a Reference field on the section's linked schema, populate `data_sources.resolvedReferences`. The SDK's data-binder reads the bound array and delivers full resolved entries. The component does its own `.map()`. No Repeater, no Condition Block. Simpler and native.
**Path A: native array prop** (`build-repeating-section` § array-prop alternative). Register the production wrapper with a `type: "array"` prop, bind that prop to a Reference field on the section's linked schema, populate `data_sources.resolvedReferences`. The SDK's data-binder reads the bound array and delivers the resolved entries, but on the live site only with the fields your bindings name (see [`register-component-prop-contracts`](register-component-prop-contracts.md) § Studio fetches only the fields your bindings name). The component does its own `.map()`. No Repeater, no Condition Block. Simpler and native.

Use Path A when: the production wrapper already accepts an `array` prop of full entry-like objects. The list iterates a **single Reference field** (one CT, no per-item polymorphism). Template authors don't need to swap the child Section per template instance. You don't need Studio Preview Mode to show N rendered children on the canvas.

Expand Down
Loading
Loading