handover-developer

v2026.09.24

Generate comprehensive technical documentation for developers taking over an AEM Edge Delivery Services project. Use when onboarding developers, creating technical handover documentation, or documenting a project's architecture — analyzes codebase structure, custom implementations, design tokens, and produces a complete developer guide.

GitHub
Install command
npx skhub add adobe/handover-developer
Markdown
SKILL.md

Project Handover - Development

Generate a complete technical guide for developers. Analyzes the codebase and produces actionable documentation that enables developers to understand, maintain, and extend the project.


Step 0: Navigate to Project Root (CONDITIONAL)

Skip if allGuides is set in .claude-plugin/project-config.json (orchestrator already validated).

ALL_GUIDES=$(cat .claude-plugin/project-config.json 2>/dev/null | node -e "
  const d = require('fs').readFileSync(0,'utf8');
  try { console.log(JSON.parse(d).allGuides ? 'true' : ''); } catch(e) { console.log(''); }
")
if [ -z "$ALL_GUIDES" ]; then
  cd "$(git rev-parse --show-toplevel)"
  ls scripts/aem.js
fi

If scripts/aem.js does not exist, tell the user this skill requires an AEM Edge Delivery Services project and stop.

All subsequent steps operate from project root. Guides are created at project-guides/.


Execution Checklist

- [ ] Phase 0: Get org name and authenticate
- [ ] Phase 1: Gather project information
- [ ] Phase 2: Analyze project architecture
- [ ] Phase 3: Document design system
- [ ] Phase 4: Document blocks, models, and templates
- [ ] Phase 5: Generate PDF

Phase 0: Get Organization Name and Authenticate

0.1 Check for Saved Organization

cat .claude-plugin/project-config.json 2>/dev/null | node -e "
  const d = require('fs').readFileSync(0,'utf8');
  try { const o = JSON.parse(d).org; if(o) console.log('org: ' + o); } catch(e) {}
"

0.2 Prompt for Organization Name (If Not Saved)

If no org name is found, ask the user:

"What is your Config Service organization name? This is the {org} part of your Edge Delivery Services URLs (e.g., https://main--site--{org}.aem.page). The org name may differ from your GitHub organization."

Ask as a plain text question — not AskUserQuestion with options. Organization name is mandatory.

0.3 Save Organization Name

mkdir -p .claude-plugin
grep -qxF '.claude-plugin/' .gitignore 2>/dev/null || echo '.claude-plugin/' >> .gitignore

if [ -f .claude-plugin/project-config.json ]; then
  cat .claude-plugin/project-config.json | sed 's/"org"[[:space:]]*:[[:space:]]*"[^"]*"/"org": "{ORG_NAME}"/' > /tmp/project-config.json && mv /tmp/project-config.json .claude-plugin/project-config.json
else
  echo '{"org": "{ORG_NAME}"}' > .claude-plugin/project-config.json
fi

Replace {ORG_NAME} with the actual organization name.

0.4 Check Auth Token

AUTH_TOKEN=$(node -e "
  const fs = require('fs');
  try {
    const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));
    if (t.authToken && t.authTokenExpiry > Math.floor(Date.now()/1000) + 60) {
      process.stdout.write(t.authToken);
    }
  } catch (e) {}
")

if [ -z "$AUTH_TOKEN" ]; then
  echo "AUTH_REQUIRED"
fi

If AUTH_REQUIRED, invoke the auth skill:

Skill({ skill: "aem-project-management:auth" })

Phase 1: Gather Project Information

1.1 Get Project URLs and Repository

git remote -v | head -1
git branch -a | head -10

Extract: repository owner, repo name, main branch name.

1.2 Check Configuration Method

ls helix-config.yaml 2>/dev/null && echo "Uses legacy helix-config" || echo "Uses Config Service (modern)"

1.3 Fetch Sites via Config Service API

The Config Service API is the only reliable source for site information. Do not use fstab.yaml, README, or git remote URLs.

ORG=$(cat .claude-plugin/project-config.json | node -e "
  const d = require('fs').readFileSync(0,'utf8');
  console.log(JSON.parse(d).org || '');
")
AUTH_TOKEN=$(node -e "
  const fs = require('fs');
  try {
    const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));
    process.stdout.write(t.authToken || '');
  } catch (e) {}
")

curl -s -H "x-auth-token: ${AUTH_TOKEN}" -H "Accept: application/json" \
  "https://admin.hlx.page/config/${ORG}/sites.json" > .claude-plugin/sites-config.json

node -e "
  const d = require('fs').readFileSync('.claude-plugin/sites-config.json', 'utf8');
  const j = JSON.parse(d);
  if (!j.sites || !j.sites.length) {
    console.error('No sites returned — verify org name and re-authenticate if needed');
    process.exit(1);
  }
  console.log('Found ' + j.sites.length + ' site(s): ' + j.sites.map(s => s.name).join(', '));
"

If validation fails, verify the org name is correct, re-authenticate, and retry.

Fetch per-site config:

curl -s -H "x-auth-token: ${AUTH_TOKEN}" \
  "https://admin.hlx.page/config/${ORG}/sites/{site-name}.json"

Extract: code.owner, code.repo, content.source.url, content.source.type.

Multiple sites = repoless setup. Single site = standard setup. Record this — it affects the aem up local dev instructions.

1.4 Check Node.js Requirements

cat .nvmrc 2>/dev/null || cat package.json | grep -A2 '"engines"'

Phase 2: Analyze Project Architecture

Read site config:

cat .claude-plugin/sites-config.json

2.1 Map Project Structure

ls -la && ls -la blocks/ && ls -la scripts/ && ls -la styles/
ls -la templates/ 2>/dev/null || echo "No templates folder"

2.2 Identify Boilerplate vs Custom Files

Only document files that were actually customized.

git log --oneline --follow {file_path} | head -5
git log --format="%an - %s" --follow {file_path} | head -5
Git HistoryAction
Only "Initial commit"Skip — boilerplate default, never worked on
Only aem-aemy[bot] commitsSkip — auto-generated
Multiple commits by teamDocument — customized

2.3 Analyze scripts/aem.js (Core Library)

grep -E "^export" scripts/aem.js

Document which functions the project imports from aem.js (e.g., sampleRUM, loadHeader, loadFooter, decorateBlock, loadBlock, loadCSS).

2.4 Analyze scripts/scripts.js

grep -E "^import|^export|^function|^async function|buildAutoBlocks|loadTemplate|getLanguage|getSiteRoot|decorateMain|loadEager|loadLazy|loadDelayed" scripts/scripts.js

Document:

PatternWhat to Document
import statementsWhat it imports from aem.js and utils.js
loadEager / loadLazyAny custom logic added to E-L-D phases
buildAutoBlocksAuto-blocking logic
loadTemplate / template handlingTemplate system
getLanguage / language detectionMulti-language setup
getSiteRoot / site detectionMulti-site configuration
External script loadingWhich phase — flag if in eager (performance risk)

2.5 Analyze scripts/delayed.js

grep -E "^import|function|google|analytics|gtag|alloy|martech|OneTrust|launch|chatbot|widget" scripts/delayed.js

Document analytics integrations, marketing tools, performance monitoring. Confirm no render-critical code is in this file.

2.6 Check for Utility Functions

grep -E "^export|^function" scripts/utils.js 2>/dev/null || echo "No utils.js"
ls scripts/*.js
grep -rl "utils.js" blocks/ scripts/ 2>/dev/null

Document shared utility functions and which blocks/scripts import them.

2.7 Check for External Dependencies

grep -A 20 '"dependencies"' package.json 2>/dev/null | head -25
grep -r "cdn\|unpkg\|jsdelivr" scripts/ blocks/ --include="*.js" 2>/dev/null

Phase 3: Document Design System

3.1 Extract CSS Custom Properties

grep -E "^\s*--" styles/styles.css

Organize into categories: Typography, Colors, Spacing, Layout.

3.2 Document Font Setup

grep -E "@font-face|font-family|font-weight|src:" styles/fonts.css 2>/dev/null
ls fonts/ 2>/dev/null

Document: font files and formats, family names, weights, fallback fonts.

3.3 Document Breakpoints

grep -E "@media.*min-width|@media.*max-width" styles/styles.css | sort -u

Standard breakpoints: Mobile < 600px, Tablet 600-899px, Desktop 900px+, Large 1200px+. Document any deviations.

3.4 Document Section Styles

grep -A 5 "\.section\." styles/styles.css
grep -A 5 "\.section\[" styles/styles.css

Phase 4: Document Blocks, Models, and Templates

Boilerplate Filtering

Run silently — do not show output to user.

  • Include: Items with 2+ commits and at least one after "Initial commit"
  • Exclude: Items with only "Initial commit" or only aem-aemy[bot] commits

4.1 Identify and Analyze Customized Blocks

head -30 blocks/{blockname}/{blockname}.js
grep -E "^\." blocks/{blockname}/{blockname}.css | head -30
grep -E "classList\.contains|classList\.add" blocks/{blockname}/{blockname}.js

Document for each customized block:

FieldWhat to Record
NameBlock folder name
PurposeWhat it does
DOM InputExpected HTML structure from CMS
DOM OutputTransformed structure after decoration
VariantsCSS classes that modify behavior
DependenciesExternal libraries, other blocks, utils

4.2 Document Universal Editor Models (If Customized)

Apply boilerplate filtering to models/*.json. Exclude standard boilerplate models (_page.json, _section.json, _button.json, _image.json, _text.json, _title.json) if unchanged. Skip section if all models are boilerplate.

4.3 Document Customized Templates

Apply boilerplate filtering to templates/*/. For each customized template, document purpose, how it's applied (template: name in metadata), and what it changes.


Phase 5: Generate Developer Guide

5.1 Output File

Save to project-guides/DEVELOPER-GUIDE.md (run mkdir -p project-guides first).

Read resources/developer-guide-template.md for the full document structure. Fill in all sections using data gathered in Phases 1–4 — replace every [placeholder] with actual project values.

5.2 Convert to Professional PDF

Save the completed markdown to project-guides/DEVELOPER-GUIDE.md with YAML frontmatter (title, date using full date format e.g., "February 17, 2026"). Then immediately invoke PDF conversion:

Skill({ skill: "aem-project-management:whitepaper", args: "project-guides/DEVELOPER-GUIDE.md project-guides/DEVELOPER-GUIDE.pdf" })

The whitepaper skill auto-cleans source files. Final output: project-guides/DEVELOPER-GUIDE.pdf.

Inform the user: "Developer guide complete: project-guides/DEVELOPER-GUIDE.pdf"


Success Criteria

CategoryCheck
Data SourceConfig Service API called (https://admin.hlx.page/config/{ORG}/sites.json)
Data SourceSite list from API response, not fstab.yaml or codebase analysis
Data SourceRepoless/standard determination from Config Service, not inferred from code
ContentQuick Reference with all project URLs
ContentArchitecture overview accurate to project
ContentDesign system fully documented (tokens, fonts, breakpoints)
ContentProject-specific blocks documented
ContentCustom scripts.js functions documented
Contentdelayed.js integrations documented
ContentTemplates documented (if applicable)
ContentLocal development setup verified
ContentCommon tasks have clear instructions
ContentTroubleshooting section covers common issues
OutputPDF generated at project-guides/DEVELOPER-GUIDE.pdf
OutputAll source files cleaned up (only PDF remains)

Communication: Never use "EDS" as an acronym — always write "Edge Delivery Services" or "AEM Edge Delivery Services" in all output and documentation.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Apache-2.0

Source path

plugins/aem/project-management/skills/handover-developer

Default branch

main

Latest commit

e26e61d

Tree SHA

b0267ec