From cem
Writes demo HTML partials for custom elements that work with cem serve. Use when users request demos or mention cem serve demos.
npx claudepluginhub bennypowers/cem --plugin cemThis skill uses the workspace's default tool permissions.
Never include `<!DOCTYPE>`, `<html>`, `<head>`, or `<body>`.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Automates semantic versioning and release workflow for Claude Code plugins: bumps versions in package.json, marketplace.json, plugin.json; verifies builds; creates git tags, GitHub releases, changelogs.
Never include <!DOCTYPE>, <html>, <head>, or <body>.
The dev server wraps partials with its own document shell, import maps,
and live reload. Adding document structure breaks rendering.
Read the element's manifest data (cem://element/{tagName} and sub-resources)
and check .config/cem.yaml for:
generate.demoDiscovery — fileGlob determines where demos live;
urlPattern captures path segments with :param; urlTemplate builds
served URLs from those params (supports alias, slug, lower, upper
template functions). Example: elements/rh-card/demo/sizes.html with
urlTemplate: /elements/{{.tag | alias}}/demo/{{.demo}}/ serves at
/elements/card/demo/sizes/. Index demos become the directory root.serve.urlRewrites (if present) — maps served URLs back to filesystem
paths when they differ (e.g., /elements/card/... to /elements/rh-card/...).
Most projects don't need this. Check if configured, and set up if asked.serve.importMap — bare specifiers need to be in dependencies or the
import map configPlace files where fileGlob expects them (typically elements/my-el/demo/).
Index demo — simplest possible usage, no metadata needed:
<script type="module">
import '../my-button.js';
</script>
<my-button>Click Me</my-button>
Feature demos — one feature per file, with metadata:
<meta itemprop="name"
content="With Icon">
<meta itemprop="description"
content="Button with a leading icon in the icon slot">
<script type="module">
import '../my-button.js';
import '../../my-icon/my-icon.js';
</script>
<my-button variant="primary">
<my-icon slot="icon"
name="check"></my-icon>
Save Changes
</my-button>
Multi-element demos — use demo-for to associate with specific elements:
<meta itemprop="demo-for"
content="my-button my-icon">
Call validate_html on the demo content, then verify:
<meta> tags use itemprop, not name or property| Mistake | Fix |
|---|---|
Adding <!DOCTYPE> / <html> | Demos are partials |
<meta name="description"> | <meta itemprop="description"> |
| Absolute import paths | Relative from demo file to source |
Importing from devDependencies | Move to dependencies |
| External CSS/JS links | Inline styles and scripts |
| Everything in one file | One feature per demo |
Missing type="module" | Always <script type="module"> |
generate_html: produce valid element markup via the MCP tool