Skip to content
Closed
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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contentstack Skills

A bundle of 21 ready-to-use [Contentstack](https://www.contentstack.com) agent skills for AI coding tools, covering CMS implementation, Brand Kit guidance, delivery SDK development, migration workflows, Developer Hub app architecture, and Launch automation.
A bundle of 22 ready-to-use [Contentstack](https://www.contentstack.com) agent skills for AI coding tools, covering CMS implementation, Brand Kit guidance, delivery SDK development, migration workflows, Developer Hub app architecture, Launch automation, and Contentstack Studio.

## What's in here?

Expand Down Expand Up @@ -29,11 +29,11 @@ After install, the router at `skills/CLAUDE.md` is loaded into context and Claud

### Cursor

Install via Cursor's plugin marketplace, **or** copy `cursor/rules/*.mdc` into your project's `.cursor/rules/` directory. The `00-router.mdc` rule is marked `alwaysApply: true`, so Cursor always knows which skill to reach for.
Install via Cursor's plugin marketplace, **or** copy `cursor/rules/*.mdc` into your project's `.cursor/rules/` directory. The `00-router.mdc` rule is marked `alwaysApply: true`, so Cursor always knows which skill to reach for. The Studio rule reads its specialist files from `skills/studio/`, so copy that folder to your project's `skills/studio/` as well.

### Codex / OpenAI agents

Point your agent at this repo or copy the `codex/` directory into your project. The entry point is [`codex/AGENTS.md`](codex/AGENTS.md).
Point your agent at this repo or copy the `codex/` directory into your project. The entry point is [`codex/AGENTS.md`](codex/AGENTS.md). `codex/studio/` holds only the Studio router; it reads its specialist files from `skills/studio/`, so copy that folder too.

### Gemini CLI

Expand Down Expand Up @@ -72,6 +72,7 @@ npx skills add <this-repo>@<skill-slug>
| `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 | 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. |

## How it works

Expand Down
1 change: 1 addition & 0 deletions codex/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ Use the table below to route a user request to the right skill. Each row maps a
| Use when you need to automate Launch deployments for a known project and environment, monitor progress, and surface failure diagnostics. This is appropriate for CI/CD or operator workflows that need a deterministic deploy status check and log-based troubleshooting. | [Trigger and Monitor Launch Deployments](./launch-trigger-and-monitor-launch-deployments/SKILL.md) |
| Use when developers ask about content personalization, A/B testing, audience segmentation, variant creation, or integrating Personalize with the CMS. | [Variants & Personalization](./cms-variants-personalization/SKILL.md) |
| Use when a user needs help designing or building a Contentstack Developer Hub or Marketplace app. | [Developer Hub App Architect](./developer-hub-app-architect/SKILL.md) |
| Use when the user is working with Contentstack Studio: installing the Studio SDK, provisioning a Studio project, registering components, building sections and templates, binding data, wiring the canvas and preview routes, verifying a build, or troubleshooting the canvas, compositions, data binding or SSR. Start at the Studio router, which picks the matching specialist from its own index. | [Studio](./studio/SKILL.md) |
95 changes: 95 additions & 0 deletions codex/studio/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# studio

> This skill's files, including `skills-index.md` and every `<name>.md` it routes to, are in `../../skills/studio/` relative to this file. Resolve every relative path and skill name below against that folder, not against this file. If that folder is missing, the pack is installed without its files: say so and stop.


# Studio router

You are working on Contentstack Studio. The pack has one specialist skill per task, covering install, provisioning, component registration, section/template authoring, data binding, preview wiring, verification, troubleshooting, and migration.

Loading every skill's frontmatter into every turn was the previous design and it burned ~8K always-on tokens. The current design keeps only this skill hot and routes everything else through a lookup file.

## Resolving a skill file: three layouts, try each

**The pack ships in one shape and installs in another, and the shape differs per host. A Read against the wrong one returns "File does not exist", and the failure is silent**: routing stops and the answer gets improvised from memory, which is the exact thing this router exists to prevent.

For a skill named `<name>`, resolve in this order and use the first that exists:

| # | Path | Where this is the layout |
|---|---|---|
| 1 | `../<name>/SKILL.md` | **Nested**: Claude Code gives every skill its own directory (`~/.claude/skills/<name>/SKILL.md`). |
| 2 | `./<name>.md` | **Flat**: the repo (`skills/src/`, `docs/prompts/`), and Windsurf / Cline / Continue installs. |
| 3 | `./<name>.mdc` | **Flat, Cursor**: `.cursor/rules/` loads only `.mdc`, so the installer changes the extension. Contents are identical. |

Same rule for `skills-index.md`: try `./skills-index.md`, then `../studio/skills-index.md`, then `./skills-index.mdc`.

**If both fail, say so out loud**: "the skill pack looks mis-installed, `<name>` resolved to neither path", and do NOT quietly fall back to general knowledge. A silent fallback looks identical to the pack working, so the user never learns their install is broken. Every cross-reference in this file and in `skills-index.md` is written as `<name>.md` for readability. Apply this resolution rule to all of them.

## What to do

**Setup intent takes precedence over keyword matching.** “Enable Studio”, “make this project Studio ready”, “Studio setup”, and equivalent whole-app requests run `convert-project-to-studio` through verification. `install-studio` alone is for an explicit SDK-only request. Preserve the active setup objective across replies such as “yes”, “start”, and “OAuth done”; resume the pending step rather than routing that reply as a new task. Use the orchestrator's scoped completion checklist; authoring requirements below apply only when components or compositions are authored.

**Discover MCP execution before resolving raw HTTP credentials.** Follow `install-contentstack-mcp` to inspect callable tools in the current host and verify the target with a read call. A stored OAuth session is not evidence of a connected MCP server. Prefer available MCP operations; use OAuth HTTP for missing operations or an explicitly recorded connection limitation. Never infer tool availability solely from a conversation flag.

1. Read `skills-index.md` (resolution above). It has two parts.

2. **Trigger table.** Scan the user's most recent message against the phrases in the left column. If one row matches, Read that skill's file and follow it. If several match, run them in the order the table implies (installs before authoring, `analyze-project-fit` before anything state-changing).

3. **Topic map.** Use this when no trigger phrase fires but the topic is Studio-shaped. The user is exploring or asking a conceptual question. Pick the closest skill by name + one-liner and Read it.

4. If nothing matches after both passes, answer from general Studio knowledge, but say so, and check whether a skill is missing that should exist.

## Standing rule: atomic and reusable, every time

**This applies on every Studio turn, whatever the user asked for. It is not optional and it is not only a planning concern.**

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`](../../skills/studio/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.

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:

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`](../../skills/studio/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`](../../skills/studio/complete-the-build.md) for the how and the verification block. The runnable node count is in [`build-connected-template`](../../skills/studio/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.

## Standing rule: auth preflight

**Settle the credential before the first API call of the turn, not when one fails.** Every specialist repeats this. It lives here because it must hold even before a specialist is pulled.

1. Resolve OAuth-first per [`authenticate-cma`](../../skills/studio/authenticate-cma.md): `CS_OAUTH_ACCESS_TOKEN`, else the Contentstack MCP's stored session (`~/Library/Application Support/ContentstackMCP/oauth-config.json` and its platform equivalents).
2. **Never ask the user for a session `authtoken`.** It is a full user-session credential and is the last rung, requested only after a freshly refreshed OAuth token has been observed to fail.
3. Access tokens last **59 minutes** and refresh tokens **rotate**. Tooling that refreshes must persist the new pair. A bare `curl` loop does neither, so long work belongs in a script.
4. If nothing resolves, or a refresh returns `400 invalid_refresh_token`, hand the user `! CONTENTSTACK_REGION=<code> npx @contentstack/mcp --auth` and wait. It needs a TTY and a browser, you cannot run it for them. The region must be **in** the command. `DEFAULT_REGION` is `NA`, so omitting it silently authenticates against NA prod.
5. `403 error_code 316` is **not** an auth failure. It is a valid credential aimed at a stack outside its org. Re-authenticating fixes nothing. Check with `GET /v3/stacks` + `organization_uid`.

## Rules

- Always re-Read the skill file. Never answer from a remembered summary. The source of truth is the file on disk.
- **A failed Read is a hard stop, not a shrug.** If a skill file won't resolve under either layout above, report it. Improvising over a broken install is worse than erroring: the user believes the pack ran when it didn't.
- Never skip step 1. The lookup is cheap. Missing a skill is expensive.
- If the user's request implies multiple skills (e.g. "install and set up preview routes"), pull each in the order they must run: skills-index.md's Trigger table encodes that ordering.
- Prerequisite skills: many authoring skills assume `install-studio` + `configure-studio` are done. If the user's project state is unclear, run `analyze-project-fit` first.

## Why this exists

The old design put a rich `description` + `when-to-use` in every skill's frontmatter so Claude Code's classifier could auto-fire the right one. That worked but cost every downstream customer ~8K tokens per turn, every skill description loaded on every single message, whether the turn was about Studio or not.

The new design collapses those descriptions into `skills-index.md`, keeps only this file hot, and shifts routing into an explicit two-step read. Per-turn always-on cost drops by ~7.4K tokens. On non-Studio turns, this skill doesn't fire and the whole pack sits cold.

Nothing was deleted. Every trigger phrase from the old per-skill `when-to-use` fields lives in skills-index.md's Trigger table, verbatim.
1 change: 1 addition & 0 deletions cursor/rules/00-router.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Use the table below to route a user request to the right skill. Each row maps a
| Use when you need to automate Launch deployments for a known project and environment, monitor progress, and surface failure diagnostics. This is appropriate for CI/CD or operator workflows that need a deterministic deploy status check and log-based troubleshooting. | [Trigger and Monitor Launch Deployments](../../skills/launch-trigger-and-monitor-launch-deployments/SKILL.md) |
| Use when developers ask about content personalization, A/B testing, audience segmentation, variant creation, or integrating Personalize with the CMS. | [Variants & Personalization](../../skills/cms-variants-personalization/SKILL.md) |
| Use when a user needs help designing or building a Contentstack Developer Hub or Marketplace app. | [Developer Hub App Architect](../../skills/developer-hub-app-architect/SKILL.md) |
| Use when the user is working with Contentstack Studio: installing the Studio SDK, provisioning a Studio project, registering components, building sections and templates, binding data, wiring the canvas and preview routes, verifying a build, or troubleshooting the canvas, compositions, data binding or SSR. Start at the Studio router, which picks the matching specialist from its own index. | [Studio](../../skills/studio/SKILL.md) |
Loading
Loading