.agents/skills/create-content-component/SKILL.md
Creates a new page builder content component for both Strapi and the Next.js frontend. Triggers: add/create page component, new page section, page builder component, add form component.
npx skillsauth add notum-cz/strapi-next-monorepo-starter create-content-componentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Add a new page builder (component) to both Strapi and the Next.js frontend.
Before proceeding, validate inputs:
pricing-table). Reject PascalCase/camelCase like MyComponent or pricingTable — ask user to correct.sections, forms). Reject invalid formats.If invalid format provided, ask user to correct before proceeding.
Ask the user for:
testimonials, pricing-table)sections, forms, utilities, seo-utilities, elements (default: sections), or any custom category.If category doesn't exist in apps/strapi/src/components/, create the folder first before creating the component schema.
Before proceeding, first check if the component or similar one already exists in Strapi or the Next.js frontend. If so, ask user if they want to proceed, or go with a different name.
Given category sections and name testimonials:
sections.testimonialsapps/strapi/src/components/sections/testimonials.jsoncollectionName: components_sections_testimonials (format: components_{category}_{name_underscored})StrapiTestimonials (prefix Strapi + PascalCase of name)apps/ui/src/components/page-builder/components/sections/StrapiTestimonials.tsxCreate apps/strapi/src/components/{category}/{name}.json:
{
"collectionName": "components_{category}_{name_with_underscores}",
"info": {
"displayName": "{PascalCaseName}",
"description": ""
},
"options": {},
"attributes": {
"title": {
"type": "string",
"required": true
}
}
}
Populate attributes based on user requirements. Common attribute patterns:
{ "type": "string" } or { "type": "text" } (multiline) or { "type": "richtext" }"required": true{ "type": "component", "repeatable": false, "component": "utilities.link" }{ "type": "component", "repeatable": true, "component": "utilities.basic-image" }utilities.image-with-link or utilities.basic-image{ "type": "enumeration", "enum": ["option1", "option2"] }{ "type": "boolean", "default": false }Additional attribute options (add as needed):
description: admin UI hint (e.g. "description": "Displayed below the section title")default: default value (e.g. "default": "Click here")minLength/maxLength: string length constraints (e.g. "minLength": 3, "maxLength": 100)min/max: number constraintsprivate: hide from API response (e.g. "private": true)Reference the strapi documentation for more information on component schemas: https://docs.strapi.io/cms/backend-customization/models#model-schema
Edit apps/strapi/src/api/page/content-types/page/schema.json.
Add the new UID to the attributes.content.components array:
"content": {
"type": "dynamiczone",
"components": [
...existing,
"{category}.{name}"
]
}
Add files to apps/strapi/src/populateDynamicZone folder.
import basicImagePopulate from "../utilities/basic-image"
import linkPopulate from "../utilities/link"
export default {
populate: {
links: linkPopulate,
image: basicImagePopulate,
steps: true,
},
}
true if the component has no nested relations/components (like "utilities.ck-editor-content": true){ populate: { fieldName: true } } for simple nested components{ populate: { fieldName: { populate: { media: true } } } } for deeply nested mediaCreate apps/ui/src/components/page-builder/components/{category}/Strapi{PascalCaseName}.tsx:
import { Data } from "@repo/strapi-types"
import { removeThisWhenYouNeedMe } from "@/lib/general-helpers"
import { Container } from "@/components/elementary/Container"
export function Strapi{PascalCaseName}({
component,
}: {
readonly component: Data.Component<"{category}.{name}">
}) {
removeThisWhenYouNeedMe("Strapi{PascalCaseName}")
return (
<section>
<Container className="py-8">
<h2 className="mb-4 text-3xl font-bold">{component.title}</h2>
{/* TODO: Implement component UI */}
</Container>
</section>
)
}
Strapi{PascalCaseName}.displayName = "Strapi{PascalCaseName}"
export default Strapi{PascalCaseName}
Key patterns:
Data.Component<"{category}.{name}"> from @repo/strapi-typesremoveThisWhenYouNeedMe call — starter template placeholder, keep it for new componentsdisplayName set explicitly<Container> from @/components/elementary/Container, if it's not a root level component, or not explicit "container" component wrapping other components.Edit apps/ui/src/components/page-builder/index.tsx:
import Strapi{PascalCaseName} from "@/components/page-builder/components/{category}/Strapi{PascalCaseName}"
PageContentComponents under the matching category comment:"{category}.{name}": Strapi{PascalCaseName},
Run:
cd apps/strapi && pnpm generate:types
This updates @repo/strapi-types so the React component gets proper typing for Data.Component<"{category}.{name}">.
If expected paths are not found, search for existing similar files before reporting an error.
Example: glob for **/page-builder/**/Strapi*.tsx to find component location.
docs/page-builder.md — architecture overview, naming conventions, component propsdevelopment
Adds a new language/locale to the application. Involves Strapi admin config, Next.js i18n routing, and translation files. Triggers: add language, add locale, new language, new translation, internationalization.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.