Skills for building AEM Edge Delivery Services sites — block development, content modeling, code review, testing, and page import.
82
76%
Does it follow best practices?
Impact
88%
1.04xAverage score across 6 eval scenarios
Advisory
Suggest reviewing before use
{
"context": "Tests whether the agent follows AEM EDS block file structure conventions and performance optimization patterns. Covers correct directory/file naming with kebab-case, lazy loading with IntersectionObserver, deferred heavy operations, dynamic imports for conditional modules, and proper use of aem.js utilities.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Correct directory path",
"description": "The block JavaScript file is created at `blocks/{block-name}/{block-name}.js` (e.g., `blocks/video-embed/video-embed.js`), matching the block name exactly in kebab-case",
"max_score": 8
},
{
"name": "Correct CSS file path",
"description": "The block CSS file is created at `blocks/{block-name}/{block-name}.css` (e.g., `blocks/video-embed/video-embed.css`), matching the block name in kebab-case",
"max_score": 7
},
{
"name": "IntersectionObserver for lazy load",
"description": "Uses `IntersectionObserver` to defer loading the heavy embed content until the block enters the viewport (not loading immediately in the decorate function body)",
"max_score": 15
},
{
"name": "Observer disconnect after trigger",
"description": "After the intersection is detected and loading triggered, the observer is disconnected (`observer.disconnect()`) to avoid firing repeatedly",
"max_score": 10
},
{
"name": "Minimal initial decoration",
"description": "The synchronous/immediate part of decorate() does minimal work (e.g., adds placeholder UI or initializes observer) rather than eagerly fetching data or building complex DOM",
"max_score": 10
},
{
"name": "Dynamic import for heavy module",
"description": "Any heavy or conditionally needed JavaScript module (e.g., a third-party player library or complex renderer) is loaded via dynamic `import()` inside the observer callback or conditional branch, NOT as a top-level static import",
"max_score": 12
},
{
"name": "aem.js imports with .js extension",
"description": "Any import from `scripts/aem.js` uses the full relative path with `.js` extension: `import { ... } from '../../scripts/aem.js'`",
"max_score": 8
},
{
"name": "aem.js not modified",
"description": "The solution does NOT modify or overwrite `scripts/aem.js`; it only imports from it",
"max_score": 8
},
{
"name": "async decorate function",
"description": "The decorate function is declared with the `async` keyword (since it awaits operations or performs async logic)",
"max_score": 7
},
{
"name": "Default export decorate",
"description": "The block JS uses `export default` for the decorate function",
"max_score": 7
},
{
"name": "Error handling on fetch",
"description": "Any network requests (fetch) inside the block include a try/catch or .catch() error handler",
"max_score": 8
}
]
}evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
skills
analyze-and-plan
block-collection-and-party
block-inventory
building-blocks
code-review
content-driven-development
content-modeling
docs-search
find-test-content
generate-import-html
identify-page-structure
page-decomposition
page-import
preview-import
scrape-webpage
testing-blocks