From dx-aem
Verify a component on AEM after deployment — walk dialog fields, create a test page with the component configured, and save verification docs. Compares against baseline if /aem-snapshot was run. Use after deploying changes.
npx claudepluginhub easingthemes/dx-aem-flow --plugin dx-aemThis skill is limited to using the following tools:
**Platform note:** This skill uses `context: fork` + `agent: aem-inspector` for isolated execution. If subagent dispatch is unavailable (e.g., VS Code Chat), you may run inline but AEM MCP tools (`AEM/*`, `chrome-devtools-mcp/*`) must be available. If they are not, inform the user: "AEM verification requires AEM and Chrome DevTools MCP servers. Please use Claude Code or Copilot CLI."
Orchestrates content-first development workflow for AEM Edge Delivery Services. Ensures test content exists before implementing JS/CSS/block changes, bug fixes, or core functionality.
Verifies frontend changes against spec acceptance criteria using Playwright MCP for browser automation. Automates spec intake, dev server/auth checks, and test runs.
Verifies UI component rendering via Storybook snapshots and Playwright browser automation including screenshots and accessibility trees. Use for visual checks.
Share bugs, ideas, or general feedback.
Platform note: This skill uses context: fork + agent: aem-inspector for isolated execution. If subagent dispatch is unavailable (e.g., VS Code Chat), you may run inline but AEM MCP tools (AEM/*, chrome-devtools-mcp/*) must be available. If they are not, inform the user: "AEM verification requires AEM and Chrome DevTools MCP servers. Please use Claude Code or Copilot CLI."
Before running, determine if AEM verification is meaningful from the current repo alone.
Read .ai/config.yaml for repos section. If the project uses multiple repos (e.g., separate BE and FE):
Backend-only repos:
Frontend-only repos:
How to determine: Check .ai/specs/*-*/explain.md or .ai/specs/*-*/research.md for "Repos Required" or "Cross-Repo Scope". If the other repo's changes are a prerequisite, skip.
digraph aem_verify {
"Cross-repo applicability check" [shape=box];
"Applicable from this repo?" [shape=diamond];
"STOP: cross-repo dependency" [shape=doublecircle];
"Existing verification check" [shape=box];
"Previous aem-after.md exists?" [shape=diamond];
"Ask user: overwrite or compare?" [shape=box];
"Load baseline and plan" [shape=box];
"Parallel discovery (dialog + pages)" [shape=box];
"Get current dialog fields" [shape=box];
"Baseline exists?" [shape=diamond];
"Compare with baseline" [shape=box];
"Read site config for scoping" [shape=box];
"Find existing pages" [shape=box];
"Get authored config from page" [shape=box];
"Discover proper test page placement" [shape=box];
"Create or reuse demo page" [shape=box];
"Configure demo data" [shape=box];
"Write verification docs" [shape=box];
"Return summary" [shape=doublecircle];
"Cross-repo applicability check" -> "Applicable from this repo?";
"Applicable from this repo?" -> "STOP: cross-repo dependency" [label="no"];
"Applicable from this repo?" -> "Existing verification check" [label="yes"];
"Existing verification check" -> "Previous aem-after.md exists?";
"Previous aem-after.md exists?" -> "Ask user: overwrite or compare?" [label="yes"];
"Previous aem-after.md exists?" -> "Load baseline and plan" [label="no"];
"Ask user: overwrite or compare?" -> "Load baseline and plan";
"Load baseline and plan" -> "Parallel discovery (dialog + pages)";
"Parallel discovery (dialog + pages)" -> "Get current dialog fields";
"Get current dialog fields" -> "Baseline exists?";
"Baseline exists?" -> "Compare with baseline" [label="yes"];
"Baseline exists?" -> "Read site config for scoping" [label="no"];
"Compare with baseline" -> "Read site config for scoping";
"Read site config for scoping" -> "Find existing pages";
"Find existing pages" -> "Get authored config from page";
"Get authored config from page" -> "Discover proper test page placement";
"Discover proper test page placement" -> "Create or reuse demo page";
"Create or reuse demo page" -> "Configure demo data";
"Configure demo data" -> "Write verification docs";
"Write verification docs" -> "Return summary";
}
Read .ai/config.yaml for repos section and check .ai/specs/*-*/explain.md or .ai/specs/*-*/research.md for "Repos Required" or "Cross-Repo Scope". Determine if AEM verification is meaningful from the current repo alone based on change type (BE-only, FE-only, full-stack).
If the other repo's changes are a prerequisite for verification, take the "no" path. Otherwise, take the "yes" path.
Print: "Cross-repo dependency — skipping. Deploy the other repo first, then re-run verification."
STOP.
Check for existing $SPEC_DIR/aem-after.md.
If aem-after.md exists in the spec directory, take the "yes" path. Otherwise, take the "no" path.
Ask user: "Previous verification found. Overwrite or compare with new results?"
Task: Verify the AEM component $ARGUMENTS after deployment, create a demo page, and save verification docs. Compare against baseline if available.
Environment flag: If --qa is present in arguments, use aem.author-url-qa for all doc links and Chrome DevTools URLs instead of aem.author-url. Without --qa, defaults to local (aem.author-url). Note: MCP calls always go to whichever AEM instance the MCP server is connected to — the --qa flag only affects documentation links and browser navigation URLs.
If no component name was provided, check .ai/specs/*-*/aem-before.md, .ai/specs/*-*/implement.md, or .ai/specs/*-*/aem-after.md to infer it. If unclear, state what you need and stop.
Check if <spec-dir>/aem-before.md exists.
Read <spec-dir>/implement.md to get new field names and expected test values.
These can run simultaneously (single message, multiple AEM MCP calls):
getComponents or getNodeContent)enhancedPageSearch or searchContent)Wait for both. Use dialog fields for comparison; use page list for demo page selection.
Walk the dialog tree to extract all fields.
If aem-before.md was found in "Load baseline and plan", take the "yes" path. Otherwise, take the "no" path (skip comparison, list all current fields as the definitive field inventory).
For each field, categorize as: ADDED, REMOVED, UNCHANGED, MODIFIED.
Mark the "Changes from Baseline" section accordingly.
If no baseline: mark the section as "No baseline available — showing current state".
Read .ai/config.yaml aem.content-paths (or discover via mcp__plugin_dx-aem_AEM__fetchSites). Use these to:
.ai/config.yaml aem.resource-type-patternSearch configured content paths first (faster, more targeted).
JCR query for sling:resourceType = '<resource-type-pattern>/$ARGUMENTS', limit 10.
Count total. Extract top 3 page paths.
For the first page found, read the component node (depth 4) to capture authored values.
Also examine the container chain — what's between jcr:content/root and the component.
Read shared/demo-page-setup.md for the Page Selection Rule — it applies to this skill.
Key rule: New pages are ONLY for new components. For updates to existing components (enhancements, a11y fixes, bug fixes), find the best representative existing page with the component and reuse it for screenshots and QA URLs. Do NOT modify production pages — just use them as-is. Only fall back to creating a new page if no existing page has the component.
Discover component placement:
If pages were found (existing component):
jcr:content/cq:template)Language root detection: Some sites have duplicated country/lang segments (e.g., /content/brand/ca/en/ca/en/...). The language root is the FULL path before the content pages start — use mcp__plugin_dx-aem_AEM__fetchLanguageMasters or walk up the page tree checking jcr:content/jcr:language to find the actual root. Do NOT assume a fixed depth — always verify.
Create the test page on the SAME site as the production pages.
If no pages found (new component):
<spec-dir>/explain.md or <spec-dir>/raw-story.md for target project/brandcomponentGroup using mcp__plugin_dx-aem_AEM__getComponentsmcp__plugin_dx-aem_AEM__fetchSites then first site then find language rootFollow the demo page workflow from shared/demo-page-setup.md:
a. Read aem.demo-parent-path from .ai/config.yaml (e.g., /content/brand-a/ca/en/ca/en/demo). If not set, fall back to <language-root>/demo.
b. Ensure the parent path exists (create folder page if missing, using same template as sibling pages)
c. Check if <demo-parent-path>/<spec-slug> already exists — use mcp__plugin_dx-aem_AEM__getPageProperties or mcp__plugin_dx-aem_AEM__getNodeContent to check
mcp__plugin_dx-aem_AEM__getNodeContent on the container to look for a child with sling:resourceType matching the componentFirst check if the component already has data configured — use mcp__plugin_dx-aem_AEM__getNodeContent on the component node (depth 3) to inspect existing properties.
data/ child node with authored properties): log "Demo data already configured, skipping." and move on.Get real data from an existing component instance:
mcp__plugin_dx-aem_AEM__getNodeContent (depth 5) on that component instance to extract all its propertiesmcp__plugin_dx-aem_AEM__updateComponentjcr:*, sling:*, cq:*) — only copy authored data propertiesMap dialog fields to properties:
name="./data/heading" maps to property data/headingFallback (only for fields with no real data found):
Determine author URL: If --qa flag was passed, read aem.author-url-qa from .ai/config.yaml. Otherwise read aem.author-url (defaults to http://localhost:4502). Use this URL for all doc links in the output. (MCP calls use JCR paths — the MCP server handles which AEM instance to connect to.)
Read the exporter selector from .ai/config.yaml aem.selector (if configured).
Read shared/provenance-schema.md. Write <spec-dir>/aem-after.md with provenance frontmatter (use agent: aem-verify, confidence high):
---
provenance:
agent: aem-verify
model: <your-model-tier>
created: <ISO-8601 timestamp>
confidence: high
verified: false
---
# AEM Verification: <title> (`<name>`)
**Verified:** <date>
**Component:** `<component-path>/<name>`
**Pages using component:** <N>
**Test page:** <author-url>/editor.html<test-page-path>.html
**Test JSON:** <author-url><component-node-path>.<selector>.json
## Changes from Baseline
_If baseline exists:_
| Change | Field | Type | Label | JCR Property |
|--------|-------|------|-------|-------------|
| ADDED | ... | ... | ... | ... |
| REMOVED | ... | ... | ... | ... |
| UNCHANGED | ... | ... | ... | ... |
**Summary:** <N> added, <N> removed, <N> unchanged
_If no baseline:_ "No baseline available — showing current field inventory"
## Current Dialog Fields (<N> total)
### Tab: <tab-title>
| Field | Type | Label | JCR Property |
|-------|------|-------|-------------|
| ... | ... | ... | ... |
## Current Authored Config
_From: <existing-page-path>_
| Property | Value |
|----------|-------|
| ... | ... |
## Test Page
- **Path:** `<test-page-path>`
- **Author:** <author-url>/editor.html<test-page-path>.html
- **JSON:** <author-url><component-node-path>.<selector>.json
- **Language root:** `<language-root>`
- **Template:** `<template-path>`
- **Container chain:** responsivegrid > <section if needed> > <component>
- **Demo data:** configured/partial/needs manual authoring
- **Notes:** <any manual steps needed>
## Pages Using This Component (<N> total, top 3)
| # | Page Path | Author Link |
|---|-----------|-------------|
| 1 | ... | <author-url>/editor.html/....html |
## Verification Checklist
- [ ] Component dialog opens without errors
- [ ] New fields visible and functional
- [ ] Show/hide logic works (if applicable)
- [ ] JSON output includes new fields
- [ ] Existing fields unchanged
- [ ] Demo data renders correctly
Return ONLY:
aem-after.md exists in spec directory/aem-verify hero
If /aem-snapshot hero was run before development, compares current dialog fields against baseline. Shows ADDED, REMOVED, UNCHANGED fields. Creates demo page under <demo-parent-path>/<slug>/, configures demo data, writes aem-after.md.
/aem-verify my-new-component
No baseline exists — shows current field inventory instead of diff. Finds a similar component to determine placement (template, container chain), creates test page, configures demo data.
/aem-verify hero
If test page already exists, reuses it. If demo data is already configured, skips reconfiguration. Only regenerates aem-after.md.
Cause: No argument provided and no spec files to infer from.
Fix: Pass the component name explicitly: /aem-verify hero.
Cause: Language root detection failed (some sites have duplicated country/lang segments), or the template is restricted.
Fix: Check the language root path in the error. The skill walks up the page tree to find it — if the site structure is unusual, specify the target path in explain.md.
Cause: The component needs both BE and FE changes, but the other repo's code isn't deployed yet. Fix: Deploy the other repo first, then re-run verification. Or verify only the aspects available in the current repo (dialog changes for BE-only, styling for FE-only).
Before: Dialog had 5 fields (title, subtitle, image, link, linkText) After: Dialog has 4 fields — linkText missing Decision: REGRESSION — field removed. Flag and compare against spec.
Before: Dialog had 5 fields After: Dialog has 6 fields (new: backgroundColor) Spec says: "Add background color field to hero dialog" Decision: NOT regression — intentional addition per spec. Verify field works correctly.