plugins/aem/edge-delivery-services/skills/building-blocks/SKILL.md
Use this when implementing code changes in AEM Edge Delivery Services (EDS, Franklin, Helix), whether new or modified blocks, core functionality (scripts.js, styles, delayed.js, etc.), or both. Creates and modifies block folders and decorate functions, updates core scripts, scopes CSS, and wires up delayed loading. For the overall development process use content-driven-development.
npx skillsauth add adobe/skills building-blocksInstall 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.
This skill guides you through implementing AEM Edge Delivery blocks following established patterns and best practices. Blocks transform authored content into rich, interactive experiences through JavaScript decoration and CSS styling.
IMPORTANT: This skill should ONLY be invoked from the content-driven-development skill during Step 5 (Implementation).
If you are not already following the CDD process, STOP and invoke the content-driven-development skill first.
This skill is invoked automatically by content-driven-development during Step 5 (Implementation). It handles:
Block Development:
Core Functionality:
Combined:
Prerequisites (verified by CDD):
Track your progress:
Note: If your changes require core modifications (utilities in scripts.js, global styles, etc.), make those changes first, test them, then return to this workflow. See "When Modifying Core Files" below.
When to use: Creating new blocks or making major structural modifications
Skip this step when: Making minor modifications to existing blocks (CSS tweaks, small decoration changes)
Quick start:
Search the codebase for similar blocks:
ls blocks/
Use the block-collection-and-party skill to find reference implementations
Review patterns from similar blocks:
Create the block directory and files:
mkdir -p blocks/{block-name}
touch blocks/{block-name}/{block-name}.js
touch blocks/{block-name}/{block-name}.css
Basic JavaScript structure:
/**
* decorate the block
* @param {Element} block the block
*/
export default async function decorate(block) {
// Your decoration logic here
}
Basic CSS structure:
/* All selectors scoped to block */
main .{block-name} {
/* block styles */
}
blocks/{block-name}/# View the initial HTML structure from the server
curl http://localhost:3000/{test-content-path}
Essential pattern - re-use existing DOM elements:
export default async function decorate(block) {
// Platform delivers images as <picture> elements with <source> tags
const picture = block.querySelector('picture');
const heading = block.querySelector('h2');
// Create new structure, re-using existing elements
const figure = document.createElement('figure');
figure.append(picture); // Re-uses picture element
const wrapper = document.createElement('div');
wrapper.className = 'content-wrapper';
wrapper.append(heading, figure);
block.replaceChildren(wrapper);
// Only check variants when they affect decoration logic
// CSS-only variants like 'dark', 'wide' don't need JS
if (block.classList.contains('carousel')) {
// Carousel variant needs different DOM structure/behavior
setupCarousel(block);
}
}
For complete JavaScript guidelines including:
Read references/js-guidelines.md
Essential patterns - scoped, responsive, using custom properties:
/* All selectors MUST be scoped to block */
main .my-block {
/* Use CSS custom properties for consistency */
background-color: var(--background-color);
color: var(--text-color);
font-family: var(--body-font-family);
max-width: var(--max-content-width);
/* Mobile-first styles (default) */
padding: 1rem;
flex-direction: column;
}
main .my-block h2 {
font-family: var(--heading-font-family);
font-size: var(--heading-font-size-m);
}
main .my-block .item {
display: flex;
gap: 1rem;
}
/* Tablet and up */
@media (width >= 600px) {
main .my-block {
padding: 2rem;
}
}
/* Desktop and up */
@media (width >= 900px) {
main .my-block {
flex-direction: row;
padding: 4rem;
}
}
/* Variants - most are CSS-only */
main .my-block.dark {
background-color: var(--dark-color);
color: var(--clr-white);
}
For complete CSS guidelines including:
Read references/css-guidelines.md
Note on iterative validation: While building, you can test changes in your browser as you go (load test content URL, check console, verify layout and functionality). For comprehensive testing guidance including browser testing techniques, responsive testing, and validation approaches, see the testing-blocks skill invoked in Step 5.
After implementation is complete, invoke the testing-blocks skill.
The testing-blocks skill will guide you through:
Provide the testing-blocks skill with:
After testing is complete, return to CDD workflow.
If your changes require modifying core files (scripts.js, styles.css, delayed.js), follow these principles:
Common core files:
Key principles:
Testing core changes:
For detailed patterns:
tools
Use the run-workflow MCP to discover, compose, execute, publish, and save Adobe Firefly workflows. TRIGGER when: user asks what actions are available, what the MCP can do, how to process images/video/3D via workflow, wants to build/run/save/publish a workflow, OR pastes any workflow/batch/execution ID. BARE ID (UUID/workflowId/batchId) = INSPECT ONLY — call inspect_run, NEVER run_workflow_submit. ALWAYS call list_actions first for capability/discovery questions. DO NOT TRIGGER for direct Firefly API calls without MCP (use firefly-api-specs).
tools
Run predefined featured workflows via run-workflow MCP. TRIGGER when user names a featured workflow (retargeting, banners at scale, localization, packaging, banner advertising, etc.) or asks to run a known marketing/production workflow. Requires run-workflow MCP. ALWAYS call get_featured_workflow before compose_workflow. DO NOT TRIGGER for custom one-off workflows with no named template — use run-workflow skill.
tools
Migrate an Adobe Commerce App Builder project from the Integration Starter Kit or Checkout Starter Kit to the new App Management approach. Run from the root of the App Builder project to be migrated. Pass --auto to skip confirmation prompts (suitable for CI or batch use) — auto mode prints a summary of all Q&A questions answered with their defaults. Pass --doc-scan-only to scan README.md and env.dist for outdated content without modifying any files. Use when the user wants to migrate an App Builder project from the Integration Starter Kit or Checkout Starter Kit to the App Management approach, or mentions upgrading their Adobe Commerce extension architecture.
development
Add or modify webhook interceptors in an Adobe Commerce app. Use when the user wants to intercept Commerce operations to validate input, append data, or modify behavior — before or after execution. Requires a base app initialized with commerce-app-init.