Skip to content
AI & Agents
Skill

/create-custom-component

Create a custom form component for an AEM Forms Edge Delivery Services (Form block) project — scaffold blocks/form/components/<name>, extend an OOTB field type (text-input, drop-down, panel, etc.), define authoring properties in _<name>.json, wire the decorate function to the

From plugin
skills
328179 skills5 MCP

Claude Code

$ npx -y skills add adobe/skills --skill create-custom-component --agent claude-code

SKILL.md

create-custom-component.SKILL.md
name: create-custom-component
description: "Create a custom form component for an AEM Forms Edge Delivery Services (Form block) project — scaffold blocks/form/components/<name>, extend an OOTB field type (text-input, drop-down, panel, etc.), define authoring properties in _<name>.json, wire the decorate function to the form model with subscribe(), register it in mappings.js, build, and validate the output. Use when a user asks to create, scaffold, build, or fix a custom form component, form field widget, or viewType in an aem-boilerplate-forms project."
license: Apache-2.0
metadata:
  version: "1.0.0"

Create Custom Form Component

Build a custom component for the AEM Forms **Form block** on Edge Delivery Services end to end — scaffold, authoring schema, `decorate` logic, model subscriptions, registration, documentation — and **prove** it works before reporting done.

When to use

  • The project is a forms project derived from `aem-boilerplate-forms` (it has `blocks/form/`, `blocks/form/mappings.js`, `blocks/form/rules/index.js`).
  • The user wants a new field widget/variant (slider, rating, OTP input, searchable dropdown, card choice, consent panel…) or wants to fix one under `blocks/form/components/`.

Not for: generic Edge Delivery Services blocks (use the `building-blocks` skill of the `aem-edge-delivery-services` plugin), AEM Sites HTL components (`create-component` in `aem-cloud-service`), or rule-editor logic.

References (read as needed)

| File | Read when | |------|-----------| | `references/custom-form-components.md` | Always — architecture, folder layout, JSON schema, registration | | `references/form-field-types.md` | Step 4 — the base HTML the `element` parameter already contains | | `references/authoring-field-types.md` | Step 3 — widgets for the properties dialog (`text`, `select`, `container`, …) | | `references/subscribe-api.md` | Step 4 — `subscribe()` patterns: own value, child fields, custom events | | `scripts/validate-component.mjs` | Step 7 — static validator (Node 18+, no dependencies) | | `scripts/create-e2e-test.mjs` | Step 7 — generates the component's Playwright e2e test + form JSON | | `scripts/run-e2e-test.mjs` | Step 7 — runs those tests with the project's own Playwright setup (Chromium, no retries) | | `assets/e2e/form-harness.js` | Test harness copied into the project's e2e test folder by `create-e2e-test.mjs` | | `scripts/preview-component.mjs` | Step 8: opens the component in a browser, with a live model inspector, for user feedback | | `scripts/validate-registration.js` | Optional — in-page check on an already deployed form |

Paths under `scripts/`, `assets/` and `references/` are relative to this skill's directory; resolve them to absolute paths before running commands from the repository root.

---

Workflow

Step 1: Gather requirements

Run every command in this skill from the **repository root** — the directory containing `package.json` and `blocks/form/`. Do not `cd` into a subfolder (such as `code/`) first. Then confirm — ask only for what the request does not already answer:

| Question | Why | |----------|-----| | Component name | Folder, file names, and `fd:viewType` (lowercase kebab-case, e.g. `star-rating`) | | Which OOTB field type does it extend? | Base HTML and AEM resource type | | Which authorable properties does it need? | Fields in `_<name>.json` | | What model state does it read/write, and when should `model.value` be committed? | Drives `subscribe` wiring and the README contract | | Is it a panel that watches child fields, or does it react to custom events? | Selects the subscribe pattern | | Expected behaviour to prove (what the user does, what the model should hold, how often rules fire) | Assertions of the e2e test in Step 7 |

Supported base types: `text-input`, `number-input`, `drop-down`, `button`, `checkbox`, `radio-group`, `checkbox-group`, `panel`, `date-input`, `multiline-input`, `file-input`, `email`, `telephone-input`.

Check the name is not already used: `blocks/form/components/<name>/` must not exist and `<name>` must not be in `mappings.js`.

Step 2: Scaffold

Create `blocks/form/components/<name>/{<name>.js,<name>.css,_<name>.json}` by hand: copy the base type's `blocks/form/models/form-components/_<base>.json`, set `definitions[0].id` and `models[0].id` to `<name>`, set `template["fd:viewType"]` to `<name>`, and fix `"..."` include paths so they resolve from the component folder (`../../models/form-common/...`).

Don't run the repo's `create:custom-component` script (`node tools/forms-scaffolder.js`) yourself: it takes no flags and asks its three questions at an interactive prompt, which an agent's shell can't answer. If the user prefers it, they run `npm run create:custom-component` in their own terminal. It creates the same three files and usually also registers the component (mappings, `_form.json` filter, `models/_component-definition.json`). **Do not assume it did — Step 7 verifies.**

Step 3: Define authoring properties (`_<name>.json`)

Read `references/authoring-field-types.md` to choose the widget for each property. Add custom fields to `models[0].fields`; reuse shared field groups instead of redefining them:

{ "...": "../../models/form-common/_basic-validation-fields.json#/fields" }

Rules: every field has `component` and a unique `name`; `select`/`multiselect`/`radio-group`/`checkbox-group` have `options`; keep `fieldType`, `resourceType`, and `fd:viewType` from the scaffold.

Step 4: Implement `decorate`

Read `references/form-field-types.md` (base HTML) and `references/subscribe-api.md`, then pick the pattern:

| The component… | Use | |----------------|-----| | Reacts to its own value / enum / visible changes | `subscribe(fieldDiv, formId, cb, { listenChanges: true })` — handle `'register'` and `'change'` | | Watches child fields (panel) | Same on the parent; inside `'register'`, `subscribe()` each child wrapper found with `[data-id="${child.id}"]` | | Re

Read more
@adobe
Ships withskills

Skills that teach AI coding agents to work with Adobe products. A skill is a folder with a SKILL.md that an agent loads when a task calls for it (agentskills.io).

328179 skills5 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
328
Star history of adobe/skills on GitHub, a chart by star-history.com

Other skills on skills.

aa-conversion-funnel-analysis

aa-conversion-funnel-a…

Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have the worst leakage. Use this skill…

@adobe@adobeInstall Skill
aa-executive-briefing

aa-executive-briefing

Generates a concise, executive-ready performance summary covering key metrics, trends, and what's driving movement. Use this…

@adobe@adobeInstall Skill
aa-kpi-pulse

aa-kpi-pulse

Produces a compact KPI digest showing how key metrics changed over a period and what's driving the movement. Use this skill when…

@adobe@adobeInstall Skill
aa-top-movers-watchlist

aa-top-movers-watchlis…

Identifies which items (pages, campaigns, products, channels, regions) had the biggest increases or decreases for a key metric…

@adobe@adobeInstall Skill
cja-dimension-analysis

cja-dimension-analysis

Comprehensive dimension analysis and reporting for CJA. Use this skill whenever the user wants to analyze one or more dimensions…

@adobe@adobeInstall Skill

More skills from other plugins.

1password

1password

Set up and use 1Password CLI for sign-in, desktop integration, and reading or injecting secrets.

openclaw2w393k
@openclaw@openclawInstall Skill

Questions about create-custom-component.

Which coding agents can use create-custom-component?
create-custom-component installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.