diff --git a/CHANGELOG.md b/CHANGELOG.md index d71468ee2a..a87aa53a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **Site to Figma Components Skill** — Rebuilds a live site's components, patterns and templates in Figma after the reviewer approves an inventory. ([#3992](https://github.com/lightspeedwp/.github/issues/3992)) - **Site to Design Tokens Skill** — For rebuilds: proposes design tokens from a live site, then creates the Figma variables and a theme.json export once approved. ([#3990](https://github.com/lightspeedwp/.github/issues/3990)) - **Figma to Block Theme Skill** — One skill turns Figma variables into theme.json presets, Figma frames into block patterns, and fills theme.json gaps. ([#3989](https://github.com/lightspeedwp/.github/issues/3989)) diff --git a/agents/ai-readiness-agent/skills/lightspeed-project-onboarding/references/routing-map.yaml b/agents/ai-readiness-agent/skills/lightspeed-project-onboarding/references/routing-map.yaml index 0084cc3425..d6e6104ff6 100644 --- a/agents/ai-readiness-agent/skills/lightspeed-project-onboarding/references/routing-map.yaml +++ b/agents/ai-readiness-agent/skills/lightspeed-project-onboarding/references/routing-map.yaml @@ -403,6 +403,22 @@ routes: use_when: Figma variables or codebase tokens need to become WordPress theme.json settings, presets, or style variations. prompt_starter: "Use figma-to-block-theme to extract Figma variables into theme.json palette, typography, spacing, radius, shadow presets and style variations." + - match: + intents: + - website_rebuild + - live_site_to_figma + - rebuild_components + - rebuild_templates + primary_skill: site-to-figma-components + related_skills: + - site-to-design-tokens + - figma-to-block-theme + - figma-generate-library + - figma-generate-design + - audit-design-system + use_when: a live website is being rebuilt and its components, patterns, template parts and templates need to exist in Figma, bound to the design tokens, before the theme is built. + prompt_starter: "Use site-to-figma-components after site-to-design-tokens: crawl the live site, approve the inventory and build scope, build the approved set in Figma, then hand the manifest to figma-to-block-theme Pattern mode." + - match: intents: - linear_triage diff --git a/package-lock.json b/package-lock.json index 99065f5cfd..098920c491 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "puppeteer": "^25.11.0", "semver": "^7.8.5", "smol-toml": "^1.8.0", + "tsx": "4.23.15", "typescript": "^5.0.0", "typescript-eslint": "8.70.0", "yaml": "2.9.1", @@ -6128,6 +6129,448 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", @@ -14132,6 +14575,48 @@ "tests/browser-compat" ] }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -22859,6 +23344,25 @@ "dev": true, "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.23.15", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz", + "integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", diff --git a/package.json b/package.json index c741268d57..0af58ce6b0 100644 --- a/package.json +++ b/package.json @@ -156,6 +156,7 @@ "test:js": "jest --config .jest.config.cjs --coverage --forceExit --detectOpenHandles", "test:figma-to-block-theme": "jest --config skills/figma-to-block-theme/scripts/jest.config.cjs", "test:site-to-design-tokens": "jest --config skills/site-to-design-tokens/scripts/jest.config.cjs", + "test:site-to-figma-components": "jest --config skills/site-to-figma-components/scripts/jest.config.cjs", "test:agent-spec-validation": "node .github/scripts/__tests__/validate-agent-specs.test.js", "test:index-generator": "node .github/scripts/__tests__/generate-agent-index.test.js", "test:create-agent-spec": "node .github/scripts/__tests__/create-agent-spec.test.js", @@ -225,6 +226,7 @@ "puppeteer": "^25.11.0", "semver": "^7.8.5", "smol-toml": "^1.8.0", + "tsx": "4.23.15", "typescript": "^5.0.0", "typescript-eslint": "8.70.0", "yaml": "2.9.1", diff --git a/skills/site-to-figma-components/SKILL.md b/skills/site-to-figma-components/SKILL.md new file mode 100644 index 0000000000..b21a327045 --- /dev/null +++ b/skills/site-to-figma-components/SKILL.md @@ -0,0 +1,98 @@ +--- +name: site-to-figma-components +description: Rebuild a live website's building blocks in Figma as a design system for a WordPress rebuild. Use after site-to-design-tokens has created the Figma variables, when a project needs the site's components (buttons, cards, form fields, navigation, accordions, sliders), patterns (heroes, card grids, call-to-action bands), template parts (header, footer, sidebar) and templates (one frame per page type) built in Figma from those variables. Crawls chosen pages at 390px and 1440px, writes an inventory report for approval, then builds component sets, parts, patterns and templates bound to semantic tokens, verifies them against the live pages, and writes a manifest that maps each Figma node to its WordPress target for figma-to-block-theme Pattern mode. +--- + +# Site to Figma Components + +## Overview + +The third step of a rebuild. Tokens come first, then this skill, then the theme. + +```text +site-to-design-tokens → crawl → inventory report → approval → Figma build → verify → manifest → figma-to-block-theme (Pattern mode) +``` + +It stops for approval between stages. Nothing is written to Figma before the reviewer approves the inventory. + +## Companion skills + +- `figma-use`: **required before every `use_figma` call**, read-only ones included. +- `figma-generate-library`: component sets, variant properties and variable bindings (stage 3). +- `figma-generate-design`: composing parts, patterns and templates from instances (stage 3). +- `audit-design-system` and `fix-design-system-finding`: the design system audit (stage 4). +- `site-to-design-tokens`: must have run first. Its variables export is this skill's `--tokens` input. +- `figma-to-block-theme`: reads the manifest in Pattern mode. `wp-block-themes` and `wp-patterns` cover the WordPress side. + +If a companion skill is missing, say so and stop rather than calling Figma tools directly. + +## Stage 1: Inventory + +1. **Agree the pages** with the reviewer: one or two public pages per template, from the site's sitemap. See [references/crawling.md](references/crawling.md). +2. **Crawl** (scratch folder outside the repository). Install the repository's dependencies first and set `SITE_TO_FIGMA_REPO_ROOT` to the absolute path of its checkout. The `--prefix` option selects its pinned `tsx` while keeping output in the scratch folder: + + ```bash + npx --prefix "$SITE_TO_FIGMA_REPO_ROOT" tsx ${CLAUDE_SKILL_DIR}/scripts/crawl-site-structure.ts --url https://www.example.com \ + --pages '/,/tours/example/,/blog/,/?s=safari' --out site-structure.json --shots shots + ``` + +3. **Get the tokens.** Use the `variables.json` from `site-to-design-tokens`, or export the variables from the project's Figma file with the script in `figma-to-block-theme`'s `references/figma-access.md`. +4. **Propose**, then take one example screenshot per item: + + ```bash + npx --prefix "$SITE_TO_FIGMA_REPO_ROOT" tsx ${CLAUDE_SKILL_DIR}/scripts/propose-inventory.ts site-structure.json --tokens variables.json \ + --theme --out inventory.json --report inventory.md --shots shots + npx --prefix "$SITE_TO_FIGMA_REPO_ROOT" tsx ${CLAUDE_SKILL_DIR}/scripts/crawl-site-structure.ts --url https://www.example.com \ + --shoot inventory.json --shots shots + ``` + +## Stage 2: Approval report + +Present `inventory.md`: the decisions list first (with a proposal for every value that has no token), then each table. [references/inventory-review.md](references/inventory-review.md) explains the sections. The reviewer approves, renames, merges or cuts items. Record the answers in `decisions.json`, including the **build scope** (`"build"`: the templates and items to import), re-run `propose-inventory.ts` with `--decisions decisions.json`, and repeat until the report says **approved** and lists the build scope. How items are found, named and mapped is in [references/classification.md](references/classification.md). + +## Stage 3: Figma build + +Confirm the target file and pages, add the variables the reviewer approved, then follow [references/figma-build.md](references/figma-build.md). Build only the approved scope, in this order: + +1. **Components**: component sets with variant properties, Auto Layout, text styles and a variable on every fill, stroke, gap, padding, radius, font and effect. Each description names its WordPress block. +2. **Template parts and patterns**: composed from component instances. +3. **Templates**: composed from parts and patterns, at 1440px, and at 390px where the report says the layout changes. + +Record each built node ID in `figma-nodes.json` as you go. + +## Stage 4: Verify + +Compare each frame with the live page at both widths, list the differences, and run the design system audit until it is clean. See [references/verification.md](references/verification.md). + +## Stage 5: Hand-off + +```bash +npx --prefix "$SITE_TO_FIGMA_REPO_ROOT" tsx ${CLAUDE_SKILL_DIR}/scripts/write-manifest.ts inventory.json --nodes figma-nodes.json \ + --out manifest.json --markdown manifest.md +``` + +Add `--partial` while only some items are built. Hand `manifest.json` to `figma-to-block-theme` Pattern mode and post `manifest.md` on the project's Linear issue. See [references/manifest.md](references/manifest.md). + +## Rules + +- **Approval first.** No Figma writes before the inventory is approved, and confirm the target file and pages before the first write. +- **Tokens only.** Every colour, size, space, radius and shadow binds to a variable, semantic tokens before primitives. A value with no token gets a proposal for the reviewer: fonts match the live site (an `Alternate` family), colours fit the ramps, sizes get a new ramp step in order, and one-offs become semantically named `custom/*` variables. Nothing is added without approval. +- **Approved build scope.** The reviewer approves which templates to build before any import. +- **Public pages only**, one at a time at the default pace. Never log in, submit a form, click or type. Hovering and focusing to read states is allowed. +- **Archive, don't delete.** Move superseded Figma items to an archive page (`node.remove()` is blocked) and check prototype link destinations before moving anything. +- **No em dashes** in Figma copy or document text. +- **Real content.** Use the site's headings, labels and images, uploaded with the Figma image tools. + +## Scripts + +TypeScript run with `tsx` (`npx --prefix "$SITE_TO_FIGMA_REPO_ROOT" tsx