codymaster 4.1.4 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (662) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/README.md +56 -86
  3. package/dist/index.js +130 -16
  4. package/dist/ui/box.js +2 -2
  5. package/dist/ui/onboarding.js +11 -5
  6. package/install.sh +317 -35
  7. package/package.json +8 -8
  8. package/public/dashboard/app.js +1270 -0
  9. package/public/dashboard/index.html +218 -0
  10. package/public/dashboard/style.css +440 -0
  11. package/skills/AGENTS.md +61 -0
  12. package/skills/CLAUDE.md +158 -0
  13. package/skills/boxme-git-config/SKILL.md +56 -0
  14. package/skills/boxme-local-dev/SKILL.md +66 -0
  15. package/skills/build.sh +30 -0
  16. package/skills/cf +314 -0
  17. package/skills/cf 2 +313 -0
  18. package/skills/cm-ads-tracker/SKILL.md +364 -69
  19. package/skills/cm-auto-publisher/SKILL.md +81 -0
  20. package/skills/cm-booking-calendar/SKILL.md +521 -0
  21. package/skills/cm-booking-calendar/references/industry-patterns.md +527 -0
  22. package/skills/cm-booking-calendar/templates/booking-form.css +626 -0
  23. package/skills/cm-booking-calendar/templates/booking-form.html +477 -0
  24. package/skills/cm-booking-calendar/templates/calendar-engine.js +419 -0
  25. package/skills/cm-booking-calendar/templates/calendar-export.js +395 -0
  26. package/skills/cm-booking-calendar/templates/reminder-config.js +629 -0
  27. package/skills/cm-brainstorm-idea/SKILL.md +15 -24
  28. package/skills/cm-clean-code/SKILL.md +300 -0
  29. package/skills/cm-code-review/SKILL.md +0 -27
  30. package/skills/cm-codeintell/SKILL.md +598 -0
  31. package/skills/cm-content-factory/.content-factory-state.json +132 -0
  32. package/skills/cm-content-factory/.git 2/logs/refs/heads/main +1 -0
  33. package/skills/cm-content-factory/.git 2/logs/refs/remotes/origin/main +1 -0
  34. package/skills/cm-content-factory/.git 2/objects/02/fb0956734b5f8ba3f918b7defd04a89cfe0076 +0 -0
  35. package/skills/cm-content-factory/.git 2/objects/08/1e129d75dc6feac6c02037272e6bd1a04e3324 +0 -0
  36. package/skills/cm-content-factory/.git 2/objects/0c/5393416f3c5e01c9a655a802bff0dd52f76f0a +0 -0
  37. package/skills/cm-content-factory/.git 2/objects/10/0b9be46978a946a77188f68be725098a122001 +0 -0
  38. package/skills/cm-content-factory/.git 2/objects/10/cf041167fc9843610eb3d90259ef3396315fdc +0 -0
  39. package/skills/cm-content-factory/.git 2/objects/12/5e19538dd6e1338ffe74f6c4c165b00435bf48 +0 -0
  40. package/skills/cm-content-factory/.git 2/objects/16/a9b9d0088d5c1347628b45a2620b479d8ad57c +0 -0
  41. package/skills/cm-content-factory/.git 2/objects/17/8c2a9ef93c33ae4eec9d58e82321f9229843a1 +0 -0
  42. package/skills/cm-content-factory/.git 2/objects/25/397ae41d09104d763bdcac2695209d85cdea89 +0 -0
  43. package/skills/cm-content-factory/.git 2/objects/2f/a836b7947f2d458e1f639788bf4bb0983a3305 +0 -0
  44. package/skills/cm-content-factory/.git 2/objects/3a/baaaf0a1c0909c0828335791557125fba911e0 +0 -0
  45. package/skills/cm-content-factory/.git 2/objects/42/2924221b81f5ce3c4e4daac9a64a24f9b01f9a +0 -0
  46. package/skills/cm-content-factory/.git 2/objects/42/ec0ce707447dc11446a34c9995fb8533801731 +0 -0
  47. package/skills/cm-content-factory/.git 2/objects/46/e43ce92866d56ce74b1d750db307cfe6154a15 +0 -0
  48. package/skills/cm-content-factory/.git 2/objects/48/5e41b633c63f55b8277bcc59f44f67681f671a +0 -0
  49. package/skills/cm-content-factory/.git 2/objects/49/49c596a3a89fa240642acd95dd3258e261eb09 +0 -0
  50. package/skills/cm-content-factory/.git 2/objects/50/9d42d8412ef8eaf7f7e138476bac2e4d10ce60 +0 -0
  51. package/skills/cm-content-factory/.git 2/objects/55/0c8c389d981b463ef849aeb792d8be3ccb6ec8 +0 -0
  52. package/skills/cm-content-factory/.git 2/objects/5d/82d3b18410cdda3ace3677436f0cb599dbe2d2 +0 -0
  53. package/skills/cm-content-factory/.git 2/objects/60/0617c58e871a38b33bf29e282d132bb3c381ad +0 -0
  54. package/skills/cm-content-factory/.git 2/objects/6a/8369a99c687b7245c92ffaf0e0f0dab9014504 +0 -0
  55. package/skills/cm-content-factory/.git 2/objects/79/bea435d40ab531c1aaf6be0432c6a5b7aaed21 +0 -0
  56. package/skills/cm-content-factory/.git 2/objects/7e/5ebd79251c2f14e4aceb86c74b6b6daae6b500 +0 -0
  57. package/skills/cm-content-factory/.git 2/objects/81/98a822a60178d6d5023ddb3e222cddf048742e +0 -0
  58. package/skills/cm-content-factory/.git 2/objects/86/0a0e1943dfe53411d2e499a1f16f46a96ef758 +0 -0
  59. package/skills/cm-content-factory/.git 2/objects/86/971fb55fdc081fdbae52376f0f13e57a4e9b04 +0 -0
  60. package/skills/cm-content-factory/.git 2/objects/88/b89dd609a0a03f8d4fe8bfde20d5b8fc1d326d +0 -0
  61. package/skills/cm-content-factory/.git 2/objects/90/8737edb6b7809e32cc01590b4e08ba42a9d40d +0 -0
  62. package/skills/cm-content-factory/.git 2/objects/93/d5a8a9a7d4fb7f11491cb596a6880528725118 +0 -0
  63. package/skills/cm-content-factory/.git 2/objects/98/46a2ab81d0c3b3eb00ef88fc56989aa7e9f316 +0 -0
  64. package/skills/cm-content-factory/.git 2/objects/9b/d8dd1e49cf274eaf9c555f3ab39dce7af5715e +0 -0
  65. package/skills/cm-content-factory/.git 2/objects/a1/13329fb0cec96ae78b222d33a24c3b5bc7fa1f +0 -0
  66. package/skills/cm-content-factory/.git 2/objects/a9/e6effe626e8a3aea3a8fc3364b492191c6e7d0 +0 -0
  67. package/skills/cm-content-factory/.git 2/objects/ad/6de7e48d9782cca9353d1ff0aa1aab7fe1df85 +0 -0
  68. package/skills/cm-content-factory/.git 2/objects/af/54ae316f771ff692e299ffcd8bf2f06b413b59 +0 -0
  69. package/skills/cm-content-factory/.git 2/objects/b0/4cb8b0b00dad633e731c1472161419e738d674 +0 -0
  70. package/skills/cm-content-factory/.git 2/objects/b3/094abb0b9ed46419b269e4a4e36a459690e3b0 +0 -0
  71. package/skills/cm-content-factory/.git 2/objects/b9/435c5d4baac2cfc5c83009ddd27b46b60db5f1 +0 -0
  72. package/skills/cm-content-factory/.git 2/objects/ba/5da17dbaec5ec2dcfdfd126aead518d1171d5c +0 -0
  73. package/skills/cm-content-factory/.git 2/objects/c0/bf58703aa258ba5dd63083bebaec8f223d844c +0 -0
  74. package/skills/cm-content-factory/.git 2/objects/c4/701a34edf1fc1bad58ccc57bd03f9426acb59a +0 -0
  75. package/skills/cm-content-factory/.git 2/objects/c7/5ccce9a4e5cc74d9b3174550cf6d993ca43638 +0 -0
  76. package/skills/cm-content-factory/.git 2/objects/c7/710d59b5a35b0f1f0a0399386643a0bd94c929 +0 -0
  77. package/skills/cm-content-factory/.git 2/objects/d1/fe58237112e953e5fec52da22cf38e08be3df9 +5 -0
  78. package/skills/cm-content-factory/.git 2/objects/d2/2bbe9fd2f74c95bc5583e803f5e435f1e2cd86 +0 -0
  79. package/skills/cm-content-factory/.git 2/objects/d7/e72852ea2bff74581dbf247d400120086229f4 +0 -0
  80. package/skills/cm-content-factory/.git 2/objects/d8/d4c3b5553e4fd72807e1d4b49ef07d9ef3ac35 +0 -0
  81. package/skills/cm-content-factory/.git 2/objects/dc/75050c2876f6a02ae2a53a3c886f395b622977 +0 -0
  82. package/skills/cm-content-factory/.git 2/objects/ee/e8546f95acec500187c08a28a8b9ee02db0dec +0 -0
  83. package/skills/cm-content-factory/.git 2/objects/ef/263c059208b416c2146434f10cb2b9fabcba16 +0 -0
  84. package/skills/cm-content-factory/.git 2/objects/f3/ae597e84d9a59b88acd21c99bde2eaf686d785 +0 -0
  85. package/skills/cm-content-factory/.git 2/objects/f3/f6f5673c821d3d8e76fa267a9e882e7a5387ea +0 -0
  86. package/skills/cm-content-factory/.git 2/objects/f9/6e6d0ad02624dd11d5848594d056caef7a5e8b +0 -0
  87. package/skills/cm-content-factory/.git 2/objects/ff/278988fc1edf0db3abcf18de795f4cc0b4f3e1 +0 -0
  88. package/skills/cm-content-factory/.git 2/refs/heads/main +1 -0
  89. package/skills/cm-content-factory/.git 2/refs/remotes/origin/main +1 -0
  90. package/skills/cm-content-factory/.pytest_cache 2/v/cache/nodeids +76 -0
  91. package/skills/cm-content-factory/.pytest_cache 2/v/cache/stepwise +1 -0
  92. package/skills/cm-content-factory/AGENTS.md +61 -0
  93. package/skills/cm-content-factory/CLAUDE.md +63 -0
  94. package/skills/cm-content-factory/CURSOR.md +43 -0
  95. package/skills/cm-content-factory/Content Factory.zip +0 -0
  96. package/skills/cm-content-factory/cf +313 -0
  97. package/skills/cm-content-factory/config.schema.json +397 -0
  98. package/skills/cm-content-factory/dashboard/app.js +556 -0
  99. package/skills/cm-content-factory/dashboard/index.html +397 -0
  100. package/skills/cm-content-factory/dashboard/style.css +1211 -0
  101. package/skills/cm-content-factory/examples/01-real-estate.config.json +146 -0
  102. package/skills/cm-content-factory/examples/02-personal-finance.config.json +146 -0
  103. package/skills/cm-content-factory/examples/03-health-wellness.config.json +147 -0
  104. package/skills/cm-content-factory/examples/04-saas-software.config.json +147 -0
  105. package/skills/cm-content-factory/examples/05-legal-services.config.json +147 -0
  106. package/skills/cm-content-factory/examples/06-insurance.config.json +146 -0
  107. package/skills/cm-content-factory/examples/07-ecommerce-dropship.config.json +146 -0
  108. package/skills/cm-content-factory/examples/08-online-education.config.json +147 -0
  109. package/skills/cm-content-factory/examples/09-crypto-defi.config.json +147 -0
  110. package/skills/cm-content-factory/examples/10-beauty-skincare.config.json +147 -0
  111. package/skills/cm-content-factory/examples/11-home-services.config.json +146 -0
  112. package/skills/cm-content-factory/examples/12-dental-clinic.config.json +147 -0
  113. package/skills/cm-content-factory/examples/13-pet-care.config.json +147 -0
  114. package/skills/cm-content-factory/examples/14-travel-hospitality.config.json +147 -0
  115. package/skills/cm-content-factory/examples/15-ai-automation.config.json +147 -0
  116. package/skills/cm-content-factory/examples/16-wedding-events.config.json +147 -0
  117. package/skills/cm-content-factory/examples/17-fitness-coaching.config.json +148 -0
  118. package/skills/cm-content-factory/examples/18-cybersecurity.config.json +147 -0
  119. package/skills/cm-content-factory/examples/19-food-restaurant.config.json +148 -0
  120. package/skills/cm-content-factory/examples/20-solar-energy.config.json +147 -0
  121. package/skills/cm-content-factory/examples/fitness-blog.config.json +116 -0
  122. package/skills/cm-content-factory/examples/tech-blog.config.json +107 -0
  123. package/skills/cm-content-factory/extensions/EXTENSION_GUIDE.md +72 -0
  124. package/skills/cm-content-factory/extensions/hooks.py +126 -0
  125. package/skills/cm-content-factory/extensions/openclaw_adapter.py +132 -0
  126. package/skills/cm-content-factory/landing/index.html +680 -0
  127. package/skills/cm-content-factory/landing/script.js +101 -0
  128. package/skills/cm-content-factory/landing/style.css +1216 -0
  129. package/skills/cm-content-factory/landing/translations.js +508 -0
  130. package/skills/cm-content-factory/logs/events.jsonl +11 -0
  131. package/skills/cm-content-factory/profiles/_template.profile.json +231 -0
  132. package/skills/cm-content-factory/profiles/finance.profile.json +278 -0
  133. package/skills/cm-content-factory/profiles/legal.profile.json +263 -0
  134. package/skills/cm-content-factory/profiles/medical-research.profile.json +321 -0
  135. package/skills/cm-content-factory/profiles/technology.profile.json +275 -0
  136. package/skills/cm-content-factory/scripts/agent_dispatcher.py +266 -0
  137. package/skills/cm-content-factory/scripts/audit.py +106 -0
  138. package/skills/cm-content-factory/scripts/dashboard_server.py +225 -0
  139. package/skills/cm-content-factory/scripts/deploy.py +146 -0
  140. package/skills/cm-content-factory/scripts/extract.py +132 -0
  141. package/skills/cm-content-factory/scripts/landing_generator.py +459 -0
  142. package/skills/cm-content-factory/scripts/memory.py +521 -0
  143. package/skills/cm-content-factory/scripts/monetize.py +239 -0
  144. package/skills/cm-content-factory/scripts/pipeline.py +357 -0
  145. package/skills/cm-content-factory/scripts/plan.py +163 -0
  146. package/skills/cm-content-factory/scripts/publish.py +145 -0
  147. package/skills/cm-content-factory/scripts/research.py +337 -0
  148. package/skills/cm-content-factory/scripts/scaffold.py +464 -0
  149. package/skills/cm-content-factory/scripts/scoreboard.py +336 -0
  150. package/skills/cm-content-factory/scripts/seo.py +90 -0
  151. package/skills/cm-content-factory/scripts/state_manager.py +320 -0
  152. package/skills/cm-content-factory/scripts/token_manager.py +268 -0
  153. package/skills/cm-content-factory/scripts/validate.py +221 -0
  154. package/skills/cm-content-factory/scripts/wizard.py +329 -0
  155. package/skills/cm-content-factory/scripts/write.py +93 -0
  156. package/skills/cm-content-factory/sites/docs-site/src/assets/houston.webp +0 -0
  157. package/skills/cm-content-factory/sites/docs-site/src/content/docs/architecture.md +90 -0
  158. package/skills/cm-content-factory/sites/docs-site/src/content/docs/data-flow.md +54 -0
  159. package/skills/cm-content-factory/sites/docs-site/src/content/docs/deployment.md +38 -0
  160. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/index.md +65 -0
  161. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/lc-content-lifecycle.md +48 -0
  162. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/seq-write-mode.md +39 -0
  163. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/uj-first-batch.md +42 -0
  164. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-content-pipeline.md +51 -0
  165. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-learning-cycle.md +52 -0
  166. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/configuration.md +86 -0
  167. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/installation.md +80 -0
  168. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/intro.md +58 -0
  169. package/skills/cm-content-factory/sites/docs-site/src/content/docs/index.md +102 -0
  170. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/index.md +45 -0
  171. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/optimize-seo.md +29 -0
  172. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/scale-content-production.md +55 -0
  173. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/standardize-quality.md +29 -0
  174. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-cmo-huong.md +41 -0
  175. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-content-lead-khoa.md +40 -0
  176. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/index.md +56 -0
  177. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-content-manager-lan.md +46 -0
  178. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-seo-minh.md +45 -0
  179. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-writer-tu.md +45 -0
  180. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/content-pipeline.md +108 -0
  181. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/index.md +22 -0
  182. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/memory-system.md +52 -0
  183. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/seo-optimization.md +58 -0
  184. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/troubleshooting-guide.md +92 -0
  185. package/skills/cm-content-factory/sites/docs-site/src/styles/custom.css +575 -0
  186. package/skills/cm-content-factory/tests/conftest.py +66 -0
  187. package/skills/cm-content-factory/tests/test_agent_dispatcher.py +125 -0
  188. package/skills/cm-content-factory/tests/test_memory.py +128 -0
  189. package/skills/cm-content-factory/tests/test_pipeline.py +107 -0
  190. package/skills/cm-content-factory/tests/test_research.py +56 -0
  191. package/skills/cm-content-factory/tests/test_state_manager.py +131 -0
  192. package/skills/cm-content-factory/tests/test_token_manager.py +110 -0
  193. package/skills/cm-content-factory/tests/test_wizard.py +121 -0
  194. package/skills/cm-continuity/SKILL.md +7 -0
  195. package/skills/cm-cro-methodology/SKILL.md +290 -0
  196. package/skills/cm-dashboard/SKILL.md +7 -525
  197. package/skills/cm-debugging/SKILL.md +7 -116
  198. package/skills/cm-deep-search/SKILL.md +5 -1
  199. package/skills/cm-dockit/README.md +6 -15
  200. package/skills/cm-dockit/SKILL.md +20 -37
  201. package/skills/cm-execution/SKILL.md +6 -1
  202. package/skills/cm-frappe-agent/SKILL.md +134 -0
  203. package/skills/cm-frappe-agent/agents/doctype-architect.md +596 -0
  204. package/skills/cm-frappe-agent/agents/erpnext-customizer.md +643 -0
  205. package/skills/cm-frappe-agent/agents/frappe-backend.md +814 -0
  206. package/skills/cm-frappe-agent/agents/frappe-custom-frontend.md +557 -0
  207. package/skills/cm-frappe-agent/agents/frappe-debugger.md +625 -0
  208. package/skills/cm-frappe-agent/agents/frappe-fixer.md +275 -0
  209. package/skills/cm-frappe-agent/agents/frappe-frontend.md +660 -0
  210. package/skills/cm-frappe-agent/agents/frappe-installer.md +158 -0
  211. package/skills/cm-frappe-agent/agents/frappe-performance.md +307 -0
  212. package/skills/cm-frappe-agent/agents/frappe-planner.md +419 -0
  213. package/skills/cm-frappe-agent/agents/frappe-remote-ops.md +153 -0
  214. package/skills/cm-frappe-agent/agents/github-workflow.md +286 -0
  215. package/skills/cm-frappe-agent/commands/frappe-app.md +351 -0
  216. package/skills/cm-frappe-agent/commands/frappe-backend.md +162 -0
  217. package/skills/cm-frappe-agent/commands/frappe-bench.md +254 -0
  218. package/skills/cm-frappe-agent/commands/frappe-debug.md +263 -0
  219. package/skills/cm-frappe-agent/commands/frappe-doctype-create.md +272 -0
  220. package/skills/cm-frappe-agent/commands/frappe-doctype-field.md +310 -0
  221. package/skills/cm-frappe-agent/commands/frappe-erpnext.md +210 -0
  222. package/skills/cm-frappe-agent/commands/frappe-fix.md +59 -0
  223. package/skills/cm-frappe-agent/commands/frappe-frontend.md +210 -0
  224. package/skills/cm-frappe-agent/commands/frappe-fullstack.md +243 -0
  225. package/skills/cm-frappe-agent/commands/frappe-github.md +57 -0
  226. package/skills/cm-frappe-agent/commands/frappe-install.md +52 -0
  227. package/skills/cm-frappe-agent/commands/frappe-plan.md +442 -0
  228. package/skills/cm-frappe-agent/commands/frappe-remote.md +58 -0
  229. package/skills/cm-frappe-agent/commands/frappe-test.md +356 -0
  230. package/skills/cm-frappe-agent/docs/README.md +51 -0
  231. package/skills/cm-frappe-agent/docs/agents-catalog.md +113 -0
  232. package/skills/cm-frappe-agent/docs/architecture.md +149 -0
  233. package/skills/cm-frappe-agent/docs/commands-catalog.md +82 -0
  234. package/skills/cm-frappe-agent/docs/resources-catalog.md +66 -0
  235. package/skills/cm-frappe-agent/docs/sitemap-urls.txt +52 -0
  236. package/skills/cm-frappe-agent/docs/sitemap.md +81 -0
  237. package/skills/cm-frappe-agent/docs/sop/user-guide.md +178 -0
  238. package/skills/cm-frappe-agent/docs/sop/vibe-coding-guide.md +122 -0
  239. package/skills/cm-frappe-agent/resources/7-layer-architecture.md +985 -0
  240. package/skills/cm-frappe-agent/resources/bench_commands.md +73 -0
  241. package/skills/cm-frappe-agent/resources/code-patterns-guide.md +948 -0
  242. package/skills/cm-frappe-agent/resources/common_pitfalls.md +266 -0
  243. package/skills/cm-frappe-agent/resources/doctype-registry.md +158 -0
  244. package/skills/cm-frappe-agent/resources/installation-guide.md +289 -0
  245. package/skills/cm-frappe-agent/resources/rest-api-patterns.md +182 -0
  246. package/skills/cm-frappe-agent/resources/scaffold_checklist.md +82 -0
  247. package/skills/cm-frappe-agent/resources/upgrade_patterns.md +113 -0
  248. package/skills/cm-frappe-agent/resources/web-form-patterns.md +252 -0
  249. package/skills/cm-frappe-agent/skills/bench-commands/SKILL.md +621 -0
  250. package/skills/cm-frappe-agent/skills/client-scripts/SKILL.md +642 -0
  251. package/skills/cm-frappe-agent/skills/doctype-patterns/SKILL.md +576 -0
  252. package/skills/cm-frappe-agent/skills/frappe-api/SKILL.md +740 -0
  253. package/skills/cm-frappe-agent/skills/remote-operations/SKILL.md +47 -0
  254. package/skills/cm-frappe-agent/skills/server-scripts/SKILL.md +608 -0
  255. package/skills/cm-frappe-agent/skills/web-forms/SKILL.md +46 -0
  256. package/skills/cm-git-worktrees/SKILL.md +0 -7
  257. package/skills/cm-google-form/SKILL.md +266 -0
  258. package/skills/cm-google-form/templates/apps-script.js +55 -0
  259. package/skills/cm-google-form/templates/form-markup.html +110 -0
  260. package/skills/cm-google-form/templates/form-submit.js +201 -0
  261. package/skills/cm-google-form/templates/toast.css +152 -0
  262. package/skills/cm-growth-hacking/SKILL.md +293 -0
  263. package/skills/cm-growth-hacking/bottom-sheet-engine.md +261 -0
  264. package/skills/cm-growth-hacking/calendar-integration.md +264 -0
  265. package/skills/cm-growth-hacking/references/engagement-patterns.md +346 -0
  266. package/skills/cm-growth-hacking/templates/bottom-sheet.css +528 -0
  267. package/skills/cm-growth-hacking/templates/bottom-sheet.js +269 -0
  268. package/skills/cm-growth-hacking/templates/calendar-cta.js +213 -0
  269. package/skills/cm-growth-hacking/templates/tracking-events.js +211 -0
  270. package/skills/cm-growth-hacking/templates/trigger-manager.js +254 -0
  271. package/skills/cm-growth-hacking/tracking-events.md +246 -0
  272. package/skills/cm-growth-hacking/trigger-system.md +342 -0
  273. package/skills/cm-how-it-work/SKILL.md +20 -4
  274. package/skills/cm-identity-guard/SKILL.md +0 -11
  275. package/skills/cm-jtbd/SKILL.md +1 -1
  276. package/skills/cm-notebooklm/SKILL.md +172 -0
  277. package/skills/cm-notebooklm/references/command_reference.md +94 -0
  278. package/skills/cm-notebooklm/references/workflows.md +60 -0
  279. package/skills/cm-notebooklm/resources/knowledge_sources.md +106 -0
  280. package/skills/cm-notebooklm/scripts/brain-sync.sh +453 -0
  281. package/skills/cm-notebooklm/scripts/graduate_wisdom.py +101 -0
  282. package/skills/cm-planning/SKILL.md +39 -52
  283. package/skills/cm-project-bootstrap/SKILL.md +1308 -99
  284. package/skills/cm-quality-gate/SKILL.md +13 -106
  285. package/skills/cm-reactor/SKILL.md +274 -0
  286. package/skills/cm-safe-deploy/SKILL.md +415 -52
  287. package/skills/cm-safe-i18n/SKILL.md +1 -22
  288. package/skills/cm-secret-shield/SKILL.md +2 -2
  289. package/skills/cm-security-gate/SKILL.md +114 -0
  290. package/skills/cm-skill-chain/SKILL.md +2 -2
  291. package/skills/cm-skill-index/SKILL.md +9 -6
  292. package/skills/cm-skill-mastery/SKILL.md +2 -15
  293. package/skills/cm-start/SKILL.md +9 -0
  294. package/skills/cm-tdd/SKILL.md +16 -49
  295. package/skills/cm-ui-preview/SKILL.md +35 -173
  296. package/skills/cm-ux-master/FEATURES-v4.md +305 -0
  297. package/skills/cm-ux-master/README-ru.md +135 -0
  298. package/skills/cm-ux-master/README-vi.md +135 -0
  299. package/skills/cm-ux-master/README-zh.md +135 -0
  300. package/skills/cm-ux-master/README.md +489 -0
  301. package/skills/cm-ux-master/SKILL.md +773 -62
  302. package/skills/cm-ux-master/cli/README.md +180 -0
  303. package/skills/cm-ux-master/cli/pyproject.toml +106 -0
  304. package/skills/cm-ux-master/cli/requirements.txt +21 -0
  305. package/skills/cm-ux-master/cli/templates/base/skill-core.md +262 -0
  306. package/skills/cm-ux-master/cli/templates/platforms/claude.yaml +21 -0
  307. package/skills/cm-ux-master/cli/templates/platforms/cursor.yaml +21 -0
  308. package/skills/cm-ux-master/cli/templates/platforms/figma.yaml +24 -0
  309. package/skills/cm-ux-master/cli/templates/platforms/vscode-mcp.yaml +28 -0
  310. package/skills/cm-ux-master/cli/templates/platforms/windsurf.yaml +21 -0
  311. package/skills/cm-ux-master/cli/uxmaster/__init__.py +10 -0
  312. package/skills/cm-ux-master/cli/uxmaster/__main__.py +19 -0
  313. package/skills/cm-ux-master/cli/uxmaster/cli.py +349 -0
  314. package/skills/cm-ux-master/cli/uxmaster/commands/__init__.py +8 -0
  315. package/skills/cm-ux-master/cli/uxmaster/commands/extract.py +18 -0
  316. package/skills/cm-ux-master/cli/uxmaster/commands/init.py +58 -0
  317. package/skills/cm-ux-master/cli/uxmaster/commands/mcp.py +194 -0
  318. package/skills/cm-ux-master/cli/uxmaster/commands/search.py +23 -0
  319. package/skills/cm-ux-master/cli/uxmaster/commands/validate.py +270 -0
  320. package/skills/cm-ux-master/cli/uxmaster/search_engine.py +532 -0
  321. package/skills/cm-ux-master/cli/uxmaster/template_engine.py +458 -0
  322. package/skills/cm-ux-master/cli/uxmaster/utils/__init__.py +9 -0
  323. package/skills/cm-ux-master/cli/uxmaster/utils/console.py +42 -0
  324. package/skills/cm-ux-master/cli/uxmaster/utils/detect.py +83 -0
  325. package/skills/cm-ux-master/data/accessibility-advanced.csv +26 -0
  326. package/skills/cm-ux-master/data/animation.csv +31 -0
  327. package/skills/cm-ux-master/data/charts.csv +26 -0
  328. package/skills/cm-ux-master/data/colors.csv +97 -0
  329. package/skills/cm-ux-master/data/design-tests.csv +37 -0
  330. package/skills/cm-ux-master/data/devices.csv +21 -0
  331. package/skills/cm-ux-master/data/icons.csv +101 -0
  332. package/skills/cm-ux-master/data/landing.csv +31 -0
  333. package/skills/cm-ux-master/data/products.csv +97 -0
  334. package/skills/cm-ux-master/data/react-performance.csv +45 -0
  335. package/skills/cm-ux-master/data/responsive.csv +26 -0
  336. package/skills/cm-ux-master/data/semi-tokens.csv +52 -0
  337. package/skills/cm-ux-master/data/stacks/angular.csv +34 -0
  338. package/skills/cm-ux-master/data/stacks/astro.csv +54 -0
  339. package/skills/cm-ux-master/data/stacks/electron.csv +32 -0
  340. package/skills/cm-ux-master/data/stacks/flutter.csv +53 -0
  341. package/skills/cm-ux-master/data/stacks/html-tailwind.csv +56 -0
  342. package/skills/cm-ux-master/data/stacks/htmx.csv +28 -0
  343. package/skills/cm-ux-master/data/stacks/jetpack-compose.csv +53 -0
  344. package/skills/cm-ux-master/data/stacks/nextjs.csv +53 -0
  345. package/skills/cm-ux-master/data/stacks/nuxt-ui.csv +51 -0
  346. package/skills/cm-ux-master/data/stacks/nuxtjs.csv +59 -0
  347. package/skills/cm-ux-master/data/stacks/react-native.csv +52 -0
  348. package/skills/cm-ux-master/data/stacks/react.csv +54 -0
  349. package/skills/cm-ux-master/data/stacks/shadcn.csv +61 -0
  350. package/skills/cm-ux-master/data/stacks/svelte.csv +54 -0
  351. package/skills/cm-ux-master/data/stacks/swiftui.csv +51 -0
  352. package/skills/cm-ux-master/data/stacks/tauri.csv +29 -0
  353. package/skills/cm-ux-master/data/stacks/vue.csv +50 -0
  354. package/skills/cm-ux-master/data/styles.csv +68 -0
  355. package/skills/cm-ux-master/data/typography.csv +58 -0
  356. package/skills/cm-ux-master/data/ui-reasoning.csv +101 -0
  357. package/skills/cm-ux-master/data/ux-guidelines.csv +100 -0
  358. package/skills/cm-ux-master/data/ux-laws.csv +49 -0
  359. package/skills/cm-ux-master/data/web-interface.csv +31 -0
  360. package/skills/cm-ux-master/docs/LANDING-PAGE.html +377 -0
  361. package/skills/cm-ux-master/docs/README.md +108 -0
  362. package/skills/cm-ux-master/docs/css/styles.css +573 -0
  363. package/skills/cm-ux-master/docs/examples/demo-script.md +319 -0
  364. package/skills/cm-ux-master/docs/guides/for-designers.md +692 -0
  365. package/skills/cm-ux-master/docs/guides/for-developers.md +778 -0
  366. package/skills/cm-ux-master/docs/guides/for-product-managers.md +693 -0
  367. package/skills/cm-ux-master/docs/guides/react-guide-vi.md +50 -0
  368. package/skills/cm-ux-master/docs/index.html +1062 -0
  369. package/skills/cm-ux-master/docs/js/i18n.js +84 -0
  370. package/skills/cm-ux-master/docs/js/lang/de.js +145 -0
  371. package/skills/cm-ux-master/docs/js/lang/en.js +145 -0
  372. package/skills/cm-ux-master/docs/js/lang/fr.js +145 -0
  373. package/skills/cm-ux-master/docs/js/lang/hi.js +145 -0
  374. package/skills/cm-ux-master/docs/js/lang/id.js +145 -0
  375. package/skills/cm-ux-master/docs/js/lang/ja.js +145 -0
  376. package/skills/cm-ux-master/docs/js/lang/ko.js +145 -0
  377. package/skills/cm-ux-master/docs/js/lang/ru.js +145 -0
  378. package/skills/cm-ux-master/docs/js/lang/vi.js +145 -0
  379. package/skills/cm-ux-master/docs/js/lang/zh.js +145 -0
  380. package/skills/cm-ux-master/docs/js/main.js +117 -0
  381. package/skills/cm-ux-master/docs/plan/PHASE1-COMPLETION.md +217 -0
  382. package/skills/cm-ux-master/docs/plan/PHASE2-COMPLETION.md +199 -0
  383. package/skills/cm-ux-master/docs/plan/PHASE2-ENHANCED-COMPLETION.md +352 -0
  384. package/skills/cm-ux-master/docs/plan/PHASE3-VALIDATION-COMPLETION.md +499 -0
  385. package/skills/cm-ux-master/docs/plan/PHASE4-TESTING-POLISH-COMPLETION.md +483 -0
  386. package/skills/cm-ux-master/docs/plan/UXM-2.0-ROADMAP.md +681 -0
  387. package/skills/cm-ux-master/docs/plan/WOW-PITCH.md +410 -0
  388. package/skills/cm-ux-master/docs/technical/api-reference.md +824 -0
  389. package/skills/cm-ux-master/docs/technical/harvester-v4.md +328 -0
  390. package/skills/cm-ux-master/docs/technical/how-it-works.md +1128 -0
  391. package/skills/cm-ux-master/docs/tutorials/quickstart.md +339 -0
  392. package/skills/cm-ux-master/docs/tutorials/tutorials.md +939 -0
  393. package/skills/cm-ux-master/docs/tutorials/user-guide.md +716 -0
  394. package/skills/cm-ux-master/examples/README.md +63 -0
  395. package/skills/cm-ux-master/mcp/__init__.py +3 -0
  396. package/skills/cm-ux-master/mcp/integrations/__init__.py +11 -0
  397. package/skills/cm-ux-master/mcp/integrations/figma/__init__.py +6 -0
  398. package/skills/cm-ux-master/mcp/integrations/figma/client.py +293 -0
  399. package/skills/cm-ux-master/mcp/integrations/figma/plugin/code.js +561 -0
  400. package/skills/cm-ux-master/mcp/integrations/figma/plugin/ui.html +334 -0
  401. package/skills/cm-ux-master/mcp/integrations/stitch/__init__.py +5 -0
  402. package/skills/cm-ux-master/mcp/integrations/stitch/client.py +410 -0
  403. package/skills/cm-ux-master/mcp/integrations/vscode/package.json +167 -0
  404. package/skills/cm-ux-master/mcp/integrations/vscode/src/extension.ts +81 -0
  405. package/skills/cm-ux-master/mcp/mcp-config.json +274 -0
  406. package/skills/cm-ux-master/mcp/server.py +771 -0
  407. package/skills/cm-ux-master/mcp/tools/__init__.py +13 -0
  408. package/skills/cm-ux-master/mcp-server/server.py +595 -0
  409. package/skills/cm-ux-master/output/fila/FilaDashboard.tsx +47 -0
  410. package/skills/cm-ux-master/output/fila/components/badge/component.tsx +35 -0
  411. package/skills/cm-ux-master/output/fila/components/badge/index.ts +1 -0
  412. package/skills/cm-ux-master/output/fila/components/button/component.tsx +53 -0
  413. package/skills/cm-ux-master/output/fila/components/button/index.ts +1 -0
  414. package/skills/cm-ux-master/output/fila/components/card/component.tsx +35 -0
  415. package/skills/cm-ux-master/output/fila/components/card/index.ts +1 -0
  416. package/skills/cm-ux-master/output/fila/components/input/component.tsx +41 -0
  417. package/skills/cm-ux-master/output/fila/components/input/index.ts +1 -0
  418. package/skills/cm-ux-master/output/fila/design-system.css +151 -0
  419. package/skills/cm-ux-master/output/fila/design-system.html +1596 -0
  420. package/skills/cm-ux-master/output/fila/design-system.json +168 -0
  421. package/skills/cm-ux-master/output/fila/figma-tokens.json +523 -0
  422. package/skills/cm-ux-master/output/fila/harvest-v4-raw.json +406 -0
  423. package/skills/cm-ux-master/output/fila/semi-theme-override.css +95 -0
  424. package/skills/cm-ux-master/output/haravan/HaravanDashboard.tsx +103 -0
  425. package/skills/cm-ux-master/output/haravan/design-system-v3-live.html +2716 -0
  426. package/skills/cm-ux-master/output/haravan/design-system-v3.html +1770 -0
  427. package/skills/cm-ux-master/output/haravan/design-system.html +914 -0
  428. package/skills/cm-ux-master/output/haravan/figma-tokens.json +84 -0
  429. package/skills/cm-ux-master/output/haravan/haravan-harvest.json +33 -0
  430. package/skills/cm-ux-master/output/haravan/harvest-v3-raw.json +167 -0
  431. package/skills/cm-ux-master/output/haravan/semi-theme-override.css +39 -0
  432. package/skills/cm-ux-master/references/audit-template.md +257 -0
  433. package/skills/cm-ux-master/references/cultural-ux.md +346 -0
  434. package/skills/cm-ux-master/references/dark-patterns.md +362 -0
  435. package/skills/cm-ux-master/references/heuristic-conflicts.md +296 -0
  436. package/skills/cm-ux-master/references/krug-principles.md +289 -0
  437. package/skills/cm-ux-master/references/nielsen-heuristics.md +360 -0
  438. package/skills/cm-ux-master/references/wcag-checklist.md +306 -0
  439. package/skills/cm-ux-master/scripts/component_generator.py +631 -0
  440. package/skills/cm-ux-master/scripts/core.py +305 -0
  441. package/skills/cm-ux-master/scripts/demo_validation.py +452 -0
  442. package/skills/cm-ux-master/scripts/design_doc_generator.py +1325 -0
  443. package/skills/cm-ux-master/scripts/design_system.py +1141 -0
  444. package/skills/cm-ux-master/scripts/design_system_indexer.py +889 -0
  445. package/skills/cm-ux-master/scripts/extract_i18n.py +251 -0
  446. package/skills/cm-ux-master/scripts/extractor.py +1437 -0
  447. package/skills/cm-ux-master/scripts/figma_bridge.py +406 -0
  448. package/skills/cm-ux-master/scripts/generate.py +147 -0
  449. package/skills/cm-ux-master/scripts/harvest_session.py +207 -0
  450. package/skills/cm-ux-master/scripts/harvester.js +240 -0
  451. package/skills/cm-ux-master/scripts/harvester_browser.py +717 -0
  452. package/skills/cm-ux-master/scripts/harvester_cli.py +431 -0
  453. package/skills/cm-ux-master/scripts/harvester_v1.js +275 -0
  454. package/skills/cm-ux-master/scripts/harvester_v3.js +620 -0
  455. package/skills/cm-ux-master/scripts/harvester_v4.js +1003 -0
  456. package/skills/cm-ux-master/scripts/install.py +528 -0
  457. package/skills/cm-ux-master/scripts/license.py +81 -0
  458. package/skills/cm-ux-master/scripts/media/qrpayment.png +0 -0
  459. package/skills/cm-ux-master/scripts/pro_stubs.py +120 -0
  460. package/skills/cm-ux-master/scripts/project_registry.py +217 -0
  461. package/skills/cm-ux-master/scripts/search.py +114 -0
  462. package/skills/cm-ux-master/scripts/semi_mcp_bridge.py +425 -0
  463. package/skills/cm-ux-master/scripts/stitch_integration.py +583 -0
  464. package/skills/cm-ux-master/scripts/test_harvester_v4.py +335 -0
  465. package/skills/cm-ux-master/scripts/token_mapper.py +626 -0
  466. package/skills/cm-ux-master/scripts/validation_engine.py +1571 -0
  467. package/skills/cm-ux-master/scripts/wizard.py +653 -0
  468. package/skills/cm-ux-master/setup.py +93 -0
  469. package/skills/cm-ux-master/templates/base/flutter-widget.dart +69 -0
  470. package/skills/cm-ux-master/templates/base/html-page.html +152 -0
  471. package/skills/cm-ux-master/templates/base/react-component.tsx +47 -0
  472. package/skills/cm-ux-master/templates/base/swiftui-view.swift +62 -0
  473. package/skills/cm-ux-master/templates/quick-start.sh +176 -0
  474. package/skills/cm-ux-master/tests/automation/batch-validate.sh +250 -0
  475. package/skills/cm-ux-master/tests/automation/generate-test-projects.sh +561 -0
  476. package/skills/cm-ux-master/tests/automation/run-all-tests.sh +315 -0
  477. package/skills/cm-ux-master/tests/test_design_doc.py +145 -0
  478. package/skills/cm-ux-master/tests/test_devices.py +74 -0
  479. package/skills/cm-ux-master/tests/test_generator.py +116 -0
  480. package/skills/cm-ux-master/tests/test_harvest_session.py +131 -0
  481. package/skills/cm-ux-master/tests/test_harvester.py +127 -0
  482. package/skills/cm-ux-master/tests/test_harvester_v3.py +324 -0
  483. package/skills/cm-ux-master/tests/test_mcp_server.py +496 -0
  484. package/skills/cm-ux-master/tests/test_new_domains.py +108 -0
  485. package/skills/cm-ux-master/tests/test_new_stacks.py +103 -0
  486. package/skills/cm-ux-master/tests/test_project_registry.py +146 -0
  487. package/skills/cm-ux-master/tests/test_semi_mcp_bridge.py +207 -0
  488. package/skills/cm-ux-master/tests/test_token_mapper.py +247 -0
  489. package/skills/cm-ux-master/tests/test_validation_engine.py +617 -0
  490. package/skills/config.schema.json +397 -0
  491. package/skills/frappe-app-builder.zip +0 -0
  492. package/skills/jobs-to-be-done/SKILL.md +266 -0
  493. package/skills/jobs-to-be-done/references/case-studies.md +154 -0
  494. package/skills/jobs-to-be-done/references/competitive-strategy.md +280 -0
  495. package/skills/jobs-to-be-done/references/diagnostics.md +158 -0
  496. package/skills/jobs-to-be-done/references/innovation-process.md +392 -0
  497. package/skills/jobs-to-be-done/references/organizational-change.md +328 -0
  498. package/skills/marketplace-report-crawler/SKILL.md +176 -0
  499. package/skills/marketplace-report-crawler/config/accounts.json +41 -0
  500. package/skills/marketplace-report-crawler/config/report-types.json +422 -0
  501. package/skills/marketplace-report-crawler/config/sessions.json +3 -0
  502. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +102 -0
  503. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +114 -0
  504. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +94 -0
  505. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +272 -0
  506. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +281 -0
  507. package/skills/marketplace-report-crawler/scripts/session-check.sh +72 -0
  508. package/skills/marketplace-report-crawler/scripts/session-manager.sh +349 -0
  509. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +83 -0
  510. package/skills/medical-research/SKILL.md +194 -0
  511. package/skills/medical-research/scripts/evidence_checker.py +288 -0
  512. package/skills/mom-test/SKILL.md +267 -0
  513. package/skills/mom-test/references/avoiding-bad-data.md +221 -0
  514. package/skills/mom-test/references/case-studies.md +306 -0
  515. package/skills/mom-test/references/commitment-advancement.md +219 -0
  516. package/skills/mom-test/references/finding-conversations.md +251 -0
  517. package/skills/mom-test/references/processing-learning.md +256 -0
  518. package/skills/mom-test/references/question-patterns.md +198 -0
  519. package/skills/pandasai-analytics/SKILL.md +251 -0
  520. package/skills/release-it/SKILL.md +235 -0
  521. package/skills/release-it/references/anti-patterns.md +279 -0
  522. package/skills/release-it/references/capacity-planning.md +285 -0
  523. package/skills/release-it/references/chaos-engineering.md +325 -0
  524. package/skills/release-it/references/deployment-strategies.md +331 -0
  525. package/skills/release-it/references/observability.md +301 -0
  526. package/skills/release-it/references/stability-patterns.md +355 -0
  527. package/skills/scripts/sync-ide-skills.sh +61 -0
  528. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +37 -0
  529. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +34 -0
  530. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +51 -0
  531. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +39 -0
  532. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +52 -0
  533. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +25 -0
  534. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +31 -0
  535. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +25 -0
  536. package/skills/skill-creator-ultra/README.md +1242 -0
  537. package/skills/skill-creator-ultra/SKILL.md +388 -0
  538. package/skills/skill-creator-ultra/agents/analyzer.md +274 -0
  539. package/skills/skill-creator-ultra/agents/comparator.md +202 -0
  540. package/skills/skill-creator-ultra/agents/grader.md +223 -0
  541. package/skills/skill-creator-ultra/assets/eval_review.html +146 -0
  542. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +471 -0
  543. package/skills/skill-creator-ultra/eval-viewer/viewer.html +1325 -0
  544. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +109 -0
  545. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +116 -0
  546. package/skills/skill-creator-ultra/examples/example_api_docs.md +189 -0
  547. package/skills/skill-creator-ultra/examples/example_db_migration.md +253 -0
  548. package/skills/skill-creator-ultra/examples/example_git_commit.md +111 -0
  549. package/skills/skill-creator-ultra/install.ps1 +289 -0
  550. package/skills/skill-creator-ultra/install.sh +313 -0
  551. package/skills/skill-creator-ultra/phases/phase1_interview.md +202 -0
  552. package/skills/skill-creator-ultra/phases/phase2_extract.md +55 -0
  553. package/skills/skill-creator-ultra/phases/phase3_detect.md +57 -0
  554. package/skills/skill-creator-ultra/phases/phase4_generate.md +543 -0
  555. package/skills/skill-creator-ultra/phases/phase5_test.md +319 -0
  556. package/skills/skill-creator-ultra/phases/phase6_eval.md +301 -0
  557. package/skills/skill-creator-ultra/phases/phase7_iterate.md +103 -0
  558. package/skills/skill-creator-ultra/phases/phase8_optimize.md +113 -0
  559. package/skills/skill-creator-ultra/resources/advanced_patterns.md +499 -0
  560. package/skills/skill-creator-ultra/resources/anti_patterns.md +376 -0
  561. package/skills/skill-creator-ultra/resources/blueprints.md +498 -0
  562. package/skills/skill-creator-ultra/resources/checklist.md +243 -0
  563. package/skills/skill-creator-ultra/resources/composition_cookbook.md +291 -0
  564. package/skills/skill-creator-ultra/resources/description_optimization.md +90 -0
  565. package/skills/skill-creator-ultra/resources/eval_guide.md +133 -0
  566. package/skills/skill-creator-ultra/resources/industry_questions.md +189 -0
  567. package/skills/skill-creator-ultra/resources/interview_questions.md +200 -0
  568. package/skills/skill-creator-ultra/resources/pattern_detection.md +200 -0
  569. package/skills/skill-creator-ultra/resources/prompt_engineering.md +531 -0
  570. package/skills/skill-creator-ultra/resources/schemas.md +430 -0
  571. package/skills/skill-creator-ultra/resources/script_integration.md +593 -0
  572. package/skills/skill-creator-ultra/resources/scripts_guide.md +339 -0
  573. package/skills/skill-creator-ultra/resources/skill_template.md +124 -0
  574. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +634 -0
  575. package/skills/skill-creator-ultra/resources/versioning_guide.md +193 -0
  576. package/skills/skill-creator-ultra/scripts/ci_eval.py +200 -0
  577. package/skills/skill-creator-ultra/scripts/package_skill.py +165 -0
  578. package/skills/skill-creator-ultra/scripts/simulate_skill.py +398 -0
  579. package/skills/skill-creator-ultra/scripts/skill_audit.py +611 -0
  580. package/skills/skill-creator-ultra/scripts/skill_compare.py +265 -0
  581. package/skills/skill-creator-ultra/scripts/skill_export.py +334 -0
  582. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +403 -0
  583. package/skills/skill-creator-ultra/scripts/skill_stats.py +339 -0
  584. package/skills/skill-creator-ultra/scripts/validate_skill.py +411 -0
  585. package/skills/tailwind-mastery/SKILL.md +229 -0
  586. package/skills/vercel-react-best-practices/AGENTS.md +3373 -0
  587. package/skills/vercel-react-best-practices/README.md +123 -0
  588. package/skills/vercel-react-best-practices/SKILL.md +143 -0
  589. package/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  590. package/skills/vercel-react-best-practices/rules/_template.md +28 -0
  591. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  592. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  593. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  594. package/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  595. package/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  596. package/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  597. package/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  598. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  599. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  600. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  601. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  602. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  603. package/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  604. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  605. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  606. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  607. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  608. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  609. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  610. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  611. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  612. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  613. package/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  614. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  615. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  616. package/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  617. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  618. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  619. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  620. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  621. package/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  622. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  623. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  624. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  625. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  626. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  627. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  628. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  629. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  630. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  631. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  632. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  633. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  634. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  635. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  636. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  637. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  638. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  639. package/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  640. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  641. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  642. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  643. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  644. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  645. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  646. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  647. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  648. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  649. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  650. package/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  651. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  652. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +142 -0
  653. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  654. package/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  655. package/skills/web-design-guidelines/SKILL.md +39 -0
  656. package/skills/cro-methodology/SKILL.md +0 -98
  657. /package/skills/{cro-methodology → cm-cro-methodology}/references/COPYWRITING.md +0 -0
  658. /package/skills/{cro-methodology → cm-cro-methodology}/references/OBJECTIONS.md +0 -0
  659. /package/skills/{cro-methodology → cm-cro-methodology}/references/PERSUASION.md +0 -0
  660. /package/skills/{cro-methodology → cm-cro-methodology}/references/RESEARCH.md +0 -0
  661. /package/skills/{cro-methodology → cm-cro-methodology}/references/funnel-analysis.md +0 -0
  662. /package/skills/{cro-methodology → cm-cro-methodology}/references/testing-methodology.md +0 -0
@@ -0,0 +1,1437 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Design System Extractor — Extract design tokens from existing websites/apps.
5
+
6
+ This is the CORE NEW CAPABILITY that existing AI tools and libraries lack:
7
+ the ability to analyze an existing product's design system and generate
8
+ a compatible skill set that inherits the brand identity.
9
+
10
+ Usage:
11
+ # Extract from URL
12
+ python3 extractor.py --url "https://example.com" --output design-system/EXTRACTED.md
13
+
14
+ # Extract from screenshots directory
15
+ python3 extractor.py --screenshots ./screenshots/ --output design-system/EXTRACTED.md
16
+
17
+ # Extract and generate custom skill
18
+ python3 extractor.py --url "https://example.com" --generate-skill --project "MyBrand"
19
+
20
+ # Extract with specific pages for deeper analysis
21
+ python3 extractor.py --url "https://example.com" --pages "home,pricing,dashboard"
22
+
23
+ Workflow:
24
+ 1. ANALYZE — Crawl/parse existing product → extract visual tokens
25
+ 2. GENERATE — Create custom skill set matching brand identity
26
+ 3. EXTEND — Build new pages/features consistent with extracted system
27
+
28
+ Dependencies:
29
+ - Python 3.8+ (stdlib only for core; optional: requests for URL fetching)
30
+ - No external dependencies required for local/screenshot mode
31
+ """
32
+
33
+ import argparse
34
+ import json
35
+ import re
36
+ import sys
37
+ import io
38
+ import os
39
+ import csv
40
+ from pathlib import Path
41
+ from datetime import datetime
42
+ from dataclasses import dataclass, field, asdict
43
+ from typing import List, Dict, Optional, Tuple
44
+ from collections import Counter, defaultdict
45
+ from math import sqrt
46
+
47
+ # Force UTF-8
48
+ if sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8':
49
+ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
50
+
51
+
52
+ # ============================================================================
53
+ # DATA MODELS
54
+ # ============================================================================
55
+
56
+ @dataclass
57
+ class ColorToken:
58
+ """Represents an extracted color with context."""
59
+ hex: str
60
+ role: str = "unknown" # primary, secondary, accent, bg, text, border, etc.
61
+ frequency: int = 0 # how often it appears
62
+ contexts: List[str] = field(default_factory=list) # where it's used: ["button", "header", "link"]
63
+ contrast_white: float = 0.0 # contrast ratio against white
64
+ contrast_black: float = 0.0 # contrast ratio against black
65
+ wcag_aa: bool = False
66
+ wcag_aaa: bool = False
67
+
68
+
69
+ @dataclass
70
+ class TypographyToken:
71
+ """Represents extracted typography information."""
72
+ font_family: str
73
+ role: str = "unknown" # heading, body, mono, accent
74
+ weight: str = "400"
75
+ size_px: int = 16
76
+ line_height: float = 1.5
77
+ letter_spacing: str = "normal"
78
+ frequency: int = 0
79
+ source: str = "system" # google-fonts, adobe-fonts, system, custom
80
+
81
+
82
+ @dataclass
83
+ class SpacingToken:
84
+ """Represents extracted spacing values."""
85
+ value_px: int
86
+ css_variable: str = ""
87
+ frequency: int = 0
88
+ contexts: List[str] = field(default_factory=list) # padding, margin, gap
89
+
90
+
91
+ @dataclass
92
+ class ComponentPattern:
93
+ """Represents an extracted UI component pattern."""
94
+ name: str # button, card, input, modal, nav, etc.
95
+ variants: List[str] = field(default_factory=list) # primary, secondary, ghost
96
+ border_radius: str = ""
97
+ shadow: str = ""
98
+ padding: str = ""
99
+ transition: str = ""
100
+ hover_state: str = ""
101
+ css_snippet: str = ""
102
+
103
+
104
+ @dataclass
105
+ class LayoutPattern:
106
+ """Represents extracted layout information."""
107
+ max_width: str = "1200px"
108
+ grid_system: str = "12-column"
109
+ breakpoints: Dict[str, int] = field(default_factory=lambda: {
110
+ "mobile": 375,
111
+ "tablet": 768,
112
+ "desktop": 1024,
113
+ "wide": 1440
114
+ })
115
+ container_padding: str = "16px"
116
+ section_gap: str = "64px"
117
+
118
+
119
+ @dataclass
120
+ class ExtractedDesignSystem:
121
+ """Complete extracted design system."""
122
+ project_name: str
123
+ source_url: str = ""
124
+ extracted_at: str = ""
125
+ brand_voice: str = "" # formal, casual, playful, premium, technical
126
+ visual_density: str = "medium" # low, medium, high
127
+
128
+ colors: List[ColorToken] = field(default_factory=list)
129
+ typography: List[TypographyToken] = field(default_factory=list)
130
+ spacing: List[SpacingToken] = field(default_factory=list)
131
+ components: List[ComponentPattern] = field(default_factory=list)
132
+ layout: LayoutPattern = field(default_factory=LayoutPattern)
133
+
134
+ # Inferred properties
135
+ color_temperature: str = "" # warm, cool, neutral
136
+ design_era: str = "" # modern, classic, retro, futuristic
137
+ ui_style_match: str = "" # closest match to known UI styles
138
+ anti_patterns_detected: List[str] = field(default_factory=list)
139
+
140
+
141
+ # ============================================================================
142
+ # COLOR UTILITIES
143
+ # ============================================================================
144
+
145
+ class ColorUtils:
146
+ """Color analysis and contrast calculation utilities."""
147
+
148
+ @staticmethod
149
+ def hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
150
+ """Convert hex color to RGB tuple."""
151
+ hex_color = hex_color.lstrip('#')
152
+ if len(hex_color) == 3:
153
+ hex_color = ''.join(c * 2 for c in hex_color)
154
+ if len(hex_color) != 6:
155
+ return (0, 0, 0)
156
+ try:
157
+ return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
158
+ except ValueError:
159
+ return (0, 0, 0)
160
+
161
+ @staticmethod
162
+ def rgb_to_hex(r: int, g: int, b: int) -> str:
163
+ """Convert RGB to hex."""
164
+ return f"#{r:02x}{g:02x}{b:02x}"
165
+
166
+ @staticmethod
167
+ def relative_luminance(r: int, g: int, b: int) -> float:
168
+ """Calculate relative luminance per WCAG 2.0."""
169
+ def linearize(c):
170
+ c = c / 255.0
171
+ return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
172
+ return 0.2126 * linearize(r) + 0.7152 * linearize(g) + 0.0722 * linearize(b)
173
+
174
+ @classmethod
175
+ def contrast_ratio(cls, hex1: str, hex2: str) -> float:
176
+ """Calculate WCAG contrast ratio between two colors."""
177
+ r1, g1, b1 = cls.hex_to_rgb(hex1)
178
+ r2, g2, b2 = cls.hex_to_rgb(hex2)
179
+ l1 = cls.relative_luminance(r1, g1, b1)
180
+ l2 = cls.relative_luminance(r2, g2, b2)
181
+ lighter = max(l1, l2)
182
+ darker = min(l1, l2)
183
+ return (lighter + 0.05) / (darker + 0.05)
184
+
185
+ @classmethod
186
+ def is_wcag_aa(cls, fg_hex: str, bg_hex: str, large_text: bool = False) -> bool:
187
+ """Check WCAG AA compliance."""
188
+ ratio = cls.contrast_ratio(fg_hex, bg_hex)
189
+ return ratio >= 3.0 if large_text else ratio >= 4.5
190
+
191
+ @classmethod
192
+ def is_wcag_aaa(cls, fg_hex: str, bg_hex: str, large_text: bool = False) -> bool:
193
+ """Check WCAG AAA compliance."""
194
+ ratio = cls.contrast_ratio(fg_hex, bg_hex)
195
+ return ratio >= 4.5 if large_text else ratio >= 7.0
196
+
197
+ @staticmethod
198
+ def color_temperature(hex_color: str) -> str:
199
+ """Determine if a color is warm, cool, or neutral."""
200
+ r, g, b = ColorUtils.hex_to_rgb(hex_color)
201
+ if r > b + 30:
202
+ return "warm"
203
+ elif b > r + 30:
204
+ return "cool"
205
+ return "neutral"
206
+
207
+ @staticmethod
208
+ def color_category(hex_color: str) -> str:
209
+ """Categorize color into broad groups."""
210
+ r, g, b = ColorUtils.hex_to_rgb(hex_color)
211
+ # Grayscale detection
212
+ if abs(r - g) < 15 and abs(g - b) < 15 and abs(r - b) < 15:
213
+ if r < 50:
214
+ return "black"
215
+ elif r > 200:
216
+ return "white"
217
+ return "gray"
218
+ # Dominant channel
219
+ if r > g and r > b:
220
+ return "warm-red" if g < 100 else "warm-orange"
221
+ elif g > r and g > b:
222
+ return "green"
223
+ elif b > r and b > g:
224
+ return "blue"
225
+ return "mixed"
226
+
227
+
228
+ # ============================================================================
229
+ # CSS PARSER — Extract design tokens from raw CSS
230
+ # ============================================================================
231
+
232
+ class CSSParser:
233
+ """Parse CSS content and extract design tokens."""
234
+
235
+ # Regex patterns for CSS extraction
236
+ COLOR_PATTERNS = [
237
+ re.compile(r'#([0-9a-fA-F]{6})\b'),
238
+ re.compile(r'#([0-9a-fA-F]{3})\b'),
239
+ re.compile(r'rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)'),
240
+ re.compile(r'rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*[\d.]+\s*\)'),
241
+ re.compile(r'hsl\(\s*(\d+)\s*,\s*(\d+)%?\s*,\s*(\d+)%?\s*\)'),
242
+ ]
243
+
244
+ FONT_PATTERN = re.compile(
245
+ r'font-family\s*:\s*([^;]+);', re.IGNORECASE
246
+ )
247
+
248
+ FONT_SIZE_PATTERN = re.compile(
249
+ r'font-size\s*:\s*(\d+(?:\.\d+)?)(px|rem|em)', re.IGNORECASE
250
+ )
251
+
252
+ FONT_WEIGHT_PATTERN = re.compile(
253
+ r'font-weight\s*:\s*(\d+|bold|normal|lighter|bolder)', re.IGNORECASE
254
+ )
255
+
256
+ SPACING_PATTERN = re.compile(
257
+ r'(?:padding|margin|gap)\s*:\s*([\d.]+)(px|rem|em)', re.IGNORECASE
258
+ )
259
+
260
+ BORDER_RADIUS_PATTERN = re.compile(
261
+ r'border-radius\s*:\s*([^;]+);', re.IGNORECASE
262
+ )
263
+
264
+ BOX_SHADOW_PATTERN = re.compile(
265
+ r'box-shadow\s*:\s*([^;]+);', re.IGNORECASE
266
+ )
267
+
268
+ TRANSITION_PATTERN = re.compile(
269
+ r'transition\s*:\s*([^;]+);', re.IGNORECASE
270
+ )
271
+
272
+ CSS_VAR_PATTERN = re.compile(
273
+ r'--([a-zA-Z0-9_-]+)\s*:\s*([^;]+);'
274
+ )
275
+
276
+ GOOGLE_FONTS_PATTERN = re.compile(
277
+ r'fonts\.googleapis\.com/css2?\?family=([^"\'&\s]+)', re.IGNORECASE
278
+ )
279
+
280
+ MAX_WIDTH_PATTERN = re.compile(
281
+ r'max-width\s*:\s*(\d+)(px|rem)', re.IGNORECASE
282
+ )
283
+
284
+ MEDIA_QUERY_PATTERN = re.compile(
285
+ r'@media[^{]*(?:min-width|max-width)\s*:\s*(\d+)px', re.IGNORECASE
286
+ )
287
+
288
+ def __init__(self):
289
+ self.colors: Counter = Counter()
290
+ self.color_contexts: Dict[str, List[str]] = defaultdict(list)
291
+ self.fonts: Counter = Counter()
292
+ self.font_sizes: Counter = Counter()
293
+ self.font_weights: Counter = Counter()
294
+ self.spacings: Counter = Counter()
295
+ self.border_radii: Counter = Counter()
296
+ self.shadows: List[str] = []
297
+ self.transitions: List[str] = []
298
+ self.css_variables: Dict[str, str] = {}
299
+ self.google_fonts: List[str] = []
300
+ self.max_widths: List[int] = []
301
+ self.breakpoints: List[int] = []
302
+
303
+ def parse_css(self, css_content: str, context: str = "stylesheet"):
304
+ """Parse CSS content and extract all tokens."""
305
+ self._extract_css_variables(css_content)
306
+ self._extract_colors(css_content, context)
307
+ self._extract_fonts(css_content)
308
+ self._extract_spacing(css_content)
309
+ self._extract_borders(css_content)
310
+ self._extract_shadows(css_content)
311
+ self._extract_transitions(css_content)
312
+ self._extract_layout(css_content)
313
+
314
+ def parse_html(self, html_content: str):
315
+ """Extract design tokens from HTML (inline styles, class hints, font imports)."""
316
+ # Extract Google Fonts
317
+ for match in self.GOOGLE_FONTS_PATTERN.finditer(html_content):
318
+ font_names = match.group(1).replace('+', ' ').split('|')
319
+ for name in font_names:
320
+ clean_name = name.split(':')[0].strip()
321
+ if clean_name:
322
+ self.google_fonts.append(clean_name)
323
+
324
+ # Extract inline styles
325
+ inline_style_pattern = re.compile(r'style\s*=\s*"([^"]*)"', re.IGNORECASE)
326
+ for match in inline_style_pattern.finditer(html_content):
327
+ self.parse_css(match.group(1), context="inline")
328
+
329
+ # Extract <style> blocks
330
+ style_block_pattern = re.compile(r'<style[^>]*>(.*?)</style>', re.DOTALL | re.IGNORECASE)
331
+ for match in style_block_pattern.finditer(html_content):
332
+ self.parse_css(match.group(1), context="style-block")
333
+
334
+ # Detect Tailwind classes for color extraction
335
+ tailwind_color_pattern = re.compile(
336
+ r'(?:bg|text|border|ring|shadow)-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(\d+)',
337
+ re.IGNORECASE
338
+ )
339
+ tailwind_colors = tailwind_color_pattern.findall(html_content)
340
+ # Note: we track Tailwind color usage patterns but can't resolve to hex without config
341
+
342
+ def _extract_css_variables(self, css: str):
343
+ for match in self.CSS_VAR_PATTERN.finditer(css):
344
+ var_name = match.group(1)
345
+ var_value = match.group(2).strip()
346
+ self.css_variables[var_name] = var_value
347
+
348
+ def _extract_colors(self, css: str, context: str):
349
+ # Hex colors
350
+ for pattern in self.COLOR_PATTERNS[:2]:
351
+ for match in pattern.finditer(css):
352
+ hex_val = match.group(1)
353
+ if len(hex_val) == 3:
354
+ hex_val = ''.join(c * 2 for c in hex_val)
355
+ hex_color = f"#{hex_val.lower()}"
356
+ self.colors[hex_color] += 1
357
+ self.color_contexts[hex_color].append(context)
358
+
359
+ # RGB colors → convert to hex
360
+ for match in self.COLOR_PATTERNS[2].finditer(css):
361
+ r, g, b = int(match.group(1)), int(match.group(2)), int(match.group(3))
362
+ hex_color = ColorUtils.rgb_to_hex(r, g, b)
363
+ self.colors[hex_color] += 1
364
+ self.color_contexts[hex_color].append(context)
365
+
366
+ # RGBA → convert to hex (ignore alpha for token extraction)
367
+ for match in self.COLOR_PATTERNS[3].finditer(css):
368
+ r, g, b = int(match.group(1)), int(match.group(2)), int(match.group(3))
369
+ hex_color = ColorUtils.rgb_to_hex(r, g, b)
370
+ self.colors[hex_color] += 1
371
+ self.color_contexts[hex_color].append(context)
372
+
373
+ def _extract_fonts(self, css: str):
374
+ for match in self.FONT_PATTERN.finditer(css):
375
+ font_list = match.group(1).strip()
376
+ # Get first font in the stack
377
+ primary_font = font_list.split(',')[0].strip().strip("'\"")
378
+ if primary_font and primary_font.lower() not in ('inherit', 'initial', 'unset'):
379
+ self.fonts[primary_font] += 1
380
+
381
+ for match in self.FONT_SIZE_PATTERN.finditer(css):
382
+ size = float(match.group(1))
383
+ unit = match.group(2)
384
+ if unit == 'rem':
385
+ size = size * 16 # Convert to px (assuming 16px base)
386
+ elif unit == 'em':
387
+ size = size * 16
388
+ self.font_sizes[int(size)] += 1
389
+
390
+ for match in self.FONT_WEIGHT_PATTERN.finditer(css):
391
+ weight = match.group(1)
392
+ weight_map = {'normal': '400', 'bold': '700', 'lighter': '300', 'bolder': '800'}
393
+ weight = weight_map.get(weight.lower(), weight)
394
+ self.font_weights[weight] += 1
395
+
396
+ def _extract_spacing(self, css: str):
397
+ for match in self.SPACING_PATTERN.finditer(css):
398
+ size = float(match.group(1))
399
+ unit = match.group(2)
400
+ if unit == 'rem':
401
+ size = size * 16
402
+ elif unit == 'em':
403
+ size = size * 16
404
+ self.spacings[int(size)] += 1
405
+
406
+ def _extract_borders(self, css: str):
407
+ for match in self.BORDER_RADIUS_PATTERN.finditer(css):
408
+ radius = match.group(1).strip()
409
+ self.border_radii[radius] += 1
410
+
411
+ def _extract_shadows(self, css: str):
412
+ for match in self.BOX_SHADOW_PATTERN.finditer(css):
413
+ shadow = match.group(1).strip()
414
+ if shadow.lower() != 'none':
415
+ self.shadows.append(shadow)
416
+
417
+ def _extract_transitions(self, css: str):
418
+ for match in self.TRANSITION_PATTERN.finditer(css):
419
+ transition = match.group(1).strip()
420
+ if transition.lower() != 'none':
421
+ self.transitions.append(transition)
422
+
423
+ def _extract_layout(self, css: str):
424
+ for match in self.MAX_WIDTH_PATTERN.finditer(css):
425
+ width = int(match.group(1))
426
+ unit = match.group(2)
427
+ if unit == 'rem':
428
+ width = width * 16
429
+ self.max_widths.append(width)
430
+
431
+ for match in self.MEDIA_QUERY_PATTERN.finditer(css):
432
+ self.breakpoints.append(int(match.group(1)))
433
+
434
+
435
+ # ============================================================================
436
+ # DESIGN SYSTEM ANALYZER — Infer roles and patterns from raw tokens
437
+ # ============================================================================
438
+
439
+ class DesignSystemAnalyzer:
440
+ """Analyze extracted tokens and infer design system structure."""
441
+
442
+ def __init__(self, parser: CSSParser, project_name: str, source_url: str = ""):
443
+ self.parser = parser
444
+ self.project_name = project_name
445
+ self.source_url = source_url
446
+
447
+ def analyze(self) -> ExtractedDesignSystem:
448
+ """Run full analysis and return structured design system."""
449
+ ds = ExtractedDesignSystem(
450
+ project_name=self.project_name,
451
+ source_url=self.source_url,
452
+ extracted_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
453
+ )
454
+
455
+ ds.colors = self._analyze_colors()
456
+ ds.typography = self._analyze_typography()
457
+ ds.spacing = self._analyze_spacing()
458
+ ds.components = self._analyze_components()
459
+ ds.layout = self._analyze_layout()
460
+ ds.color_temperature = self._infer_color_temperature(ds.colors)
461
+ ds.brand_voice = self._infer_brand_voice(ds)
462
+ ds.visual_density = self._infer_visual_density(ds)
463
+ ds.design_era = self._infer_design_era(ds)
464
+ ds.ui_style_match = self._match_ui_style(ds)
465
+ ds.anti_patterns_detected = self._detect_anti_patterns(ds)
466
+
467
+ return ds
468
+
469
+ def _analyze_colors(self) -> List[ColorToken]:
470
+ """Analyze colors and infer their roles."""
471
+ tokens = []
472
+ # Sort by frequency
473
+ sorted_colors = self.parser.colors.most_common(20)
474
+
475
+ for i, (hex_color, freq) in enumerate(sorted_colors):
476
+ category = ColorUtils.color_category(hex_color)
477
+ contexts = self.parser.color_contexts.get(hex_color, [])
478
+
479
+ # Infer role based on frequency, category, and position
480
+ role = self._infer_color_role(hex_color, freq, category, i, sorted_colors)
481
+
482
+ contrast_w = ColorUtils.contrast_ratio(hex_color, "#ffffff")
483
+ contrast_b = ColorUtils.contrast_ratio(hex_color, "#000000")
484
+
485
+ token = ColorToken(
486
+ hex=hex_color,
487
+ role=role,
488
+ frequency=freq,
489
+ contexts=contexts[:5],
490
+ contrast_white=round(contrast_w, 2),
491
+ contrast_black=round(contrast_b, 2),
492
+ wcag_aa=ColorUtils.is_wcag_aa(hex_color, "#ffffff"),
493
+ wcag_aaa=ColorUtils.is_wcag_aaa(hex_color, "#ffffff")
494
+ )
495
+ tokens.append(token)
496
+
497
+ return tokens
498
+
499
+ def _infer_color_role(self, hex_color: str, freq: int, category: str,
500
+ position: int, all_colors: list) -> str:
501
+ """Infer the role of a color in the design system."""
502
+ r, g, b = ColorUtils.hex_to_rgb(hex_color)
503
+
504
+ # White/near-white = background
505
+ if r > 240 and g > 240 and b > 240:
506
+ return "background"
507
+
508
+ # Black/near-black = text
509
+ if r < 50 and g < 50 and b < 50:
510
+ return "text-primary"
511
+
512
+ # Dark gray = text-secondary
513
+ if category == "gray" and r < 120:
514
+ return "text-secondary"
515
+
516
+ # Light gray = border or background-secondary
517
+ if category == "gray" and r > 180:
518
+ return "border" if freq < 10 else "background-secondary"
519
+
520
+ # Medium gray = text-tertiary
521
+ if category == "gray":
522
+ return "text-tertiary"
523
+
524
+ # First chromatic color = primary
525
+ chromatic_position = 0
526
+ for c_hex, c_freq in all_colors:
527
+ cat = ColorUtils.color_category(c_hex)
528
+ if cat not in ("black", "white", "gray"):
529
+ if c_hex == hex_color:
530
+ break
531
+ chromatic_position += 1
532
+
533
+ if chromatic_position == 0:
534
+ return "primary"
535
+ elif chromatic_position == 1:
536
+ return "secondary"
537
+ elif chromatic_position == 2:
538
+ return "accent"
539
+ elif chromatic_position == 3:
540
+ return "cta"
541
+
542
+ return "decorative"
543
+
544
+ def _analyze_typography(self) -> List[TypographyToken]:
545
+ """Analyze typography and infer roles."""
546
+ tokens = []
547
+ sorted_fonts = self.parser.fonts.most_common(5)
548
+ sorted_sizes = self.parser.font_sizes.most_common(10)
549
+
550
+ for i, (font_name, freq) in enumerate(sorted_fonts):
551
+ # Determine if Google Font
552
+ source = "google-fonts" if font_name in self.parser.google_fonts else "system"
553
+
554
+ # Infer role
555
+ if i == 0 and len(sorted_fonts) > 1:
556
+ role = "body" # Most frequent = body
557
+ elif i == 1:
558
+ role = "heading" # Second = heading
559
+ elif "mono" in font_name.lower() or "code" in font_name.lower():
560
+ role = "mono"
561
+ else:
562
+ role = "accent"
563
+
564
+ # If only 1 font, it's both
565
+ if len(sorted_fonts) == 1:
566
+ role = "body+heading"
567
+
568
+ # Find most common size for this role context
569
+ size = sorted_sizes[0][0] if sorted_sizes else 16
570
+
571
+ token = TypographyToken(
572
+ font_family=font_name,
573
+ role=role,
574
+ weight=self.parser.font_weights.most_common(1)[0][0] if self.parser.font_weights else "400",
575
+ size_px=size,
576
+ frequency=freq,
577
+ source=source
578
+ )
579
+ tokens.append(token)
580
+
581
+ return tokens
582
+
583
+ def _analyze_spacing(self) -> List[SpacingToken]:
584
+ """Analyze spacing values and detect scale."""
585
+ tokens = []
586
+ sorted_spacings = self.parser.spacings.most_common(15)
587
+
588
+ # Detect if 4px or 8px base
589
+ values = [s[0] for s in sorted_spacings]
590
+ base_4_count = sum(1 for v in values if v % 4 == 0)
591
+ base_8_count = sum(1 for v in values if v % 8 == 0)
592
+
593
+ base = 4 if base_4_count > base_8_count else 8
594
+
595
+ for value, freq in sorted_spacings:
596
+ # Generate CSS variable name
597
+ if value <= 4:
598
+ var_name = "--space-xs"
599
+ elif value <= 8:
600
+ var_name = "--space-sm"
601
+ elif value <= 16:
602
+ var_name = "--space-md"
603
+ elif value <= 24:
604
+ var_name = "--space-lg"
605
+ elif value <= 32:
606
+ var_name = "--space-xl"
607
+ elif value <= 48:
608
+ var_name = "--space-2xl"
609
+ else:
610
+ var_name = "--space-3xl"
611
+
612
+ token = SpacingToken(
613
+ value_px=value,
614
+ css_variable=var_name,
615
+ frequency=freq
616
+ )
617
+ tokens.append(token)
618
+
619
+ return tokens
620
+
621
+ def _analyze_components(self) -> List[ComponentPattern]:
622
+ """Infer component patterns from extracted data."""
623
+ components = []
624
+
625
+ # Button pattern
626
+ most_common_radius = self.parser.border_radii.most_common(1)
627
+ radius = most_common_radius[0][0] if most_common_radius else "8px"
628
+
629
+ # Most common transition
630
+ common_transition = "all 200ms ease"
631
+ if self.parser.transitions:
632
+ common_transition = self.parser.transitions[0]
633
+
634
+ # Most common shadow
635
+ common_shadow = "0 1px 3px rgba(0,0,0,0.1)"
636
+ if self.parser.shadows:
637
+ common_shadow = self.parser.shadows[0]
638
+
639
+ # Find primary and secondary colors
640
+ primary_color = "#2563EB"
641
+ text_color = "#1E293B"
642
+ bg_color = "#FFFFFF"
643
+ for token_data in self.parser.colors.most_common(20):
644
+ hex_c = token_data[0]
645
+ cat = ColorUtils.color_category(hex_c)
646
+ if cat not in ("black", "white", "gray") and primary_color == "#2563EB":
647
+ primary_color = hex_c
648
+ r, g, b = ColorUtils.hex_to_rgb(hex_c)
649
+ if r > 240 and g > 240 and b > 240 and bg_color == "#FFFFFF":
650
+ bg_color = hex_c
651
+ if r < 50 and g < 50 and b < 50 and text_color == "#1E293B":
652
+ text_color = hex_c
653
+
654
+ components.append(ComponentPattern(
655
+ name="button",
656
+ variants=["primary", "secondary", "ghost"],
657
+ border_radius=radius,
658
+ shadow=common_shadow,
659
+ padding="12px 24px",
660
+ transition=common_transition,
661
+ hover_state="opacity: 0.9; transform: translateY(-1px)",
662
+ css_snippet=f""".btn-primary {{
663
+ background: {primary_color};
664
+ color: white;
665
+ padding: 12px 24px;
666
+ border-radius: {radius};
667
+ font-weight: 600;
668
+ transition: {common_transition};
669
+ cursor: pointer;
670
+ }}"""
671
+ ))
672
+
673
+ components.append(ComponentPattern(
674
+ name="card",
675
+ variants=["default", "elevated", "outlined"],
676
+ border_radius=radius,
677
+ shadow=common_shadow,
678
+ padding="24px",
679
+ transition=common_transition,
680
+ hover_state="box-shadow: 0 10px 15px rgba(0,0,0,0.1); transform: translateY(-2px)",
681
+ css_snippet=f""".card {{
682
+ background: {bg_color};
683
+ border-radius: {radius};
684
+ padding: 24px;
685
+ box-shadow: {common_shadow};
686
+ transition: {common_transition};
687
+ }}"""
688
+ ))
689
+
690
+ components.append(ComponentPattern(
691
+ name="input",
692
+ variants=["default", "error", "disabled"],
693
+ border_radius=radius,
694
+ padding="12px 16px",
695
+ transition=common_transition,
696
+ css_snippet=f""".input {{
697
+ padding: 12px 16px;
698
+ border: 1px solid #E2E8F0;
699
+ border-radius: {radius};
700
+ font-size: 16px;
701
+ transition: border-color 200ms ease;
702
+ }}
703
+ .input:focus {{
704
+ border-color: {primary_color};
705
+ outline: none;
706
+ box-shadow: 0 0 0 3px {primary_color}20;
707
+ }}"""
708
+ ))
709
+
710
+ return components
711
+
712
+ def _analyze_layout(self) -> LayoutPattern:
713
+ """Analyze layout patterns."""
714
+ layout = LayoutPattern()
715
+
716
+ if self.parser.max_widths:
717
+ # Use most common max-width
718
+ most_common = Counter(self.parser.max_widths).most_common(1)
719
+ if most_common:
720
+ layout.max_width = f"{most_common[0][0]}px"
721
+
722
+ if self.parser.breakpoints:
723
+ sorted_bp = sorted(set(self.parser.breakpoints))
724
+ if len(sorted_bp) >= 1:
725
+ layout.breakpoints["mobile"] = sorted_bp[0]
726
+ if len(sorted_bp) >= 2:
727
+ layout.breakpoints["tablet"] = sorted_bp[1]
728
+ if len(sorted_bp) >= 3:
729
+ layout.breakpoints["desktop"] = sorted_bp[2]
730
+ if len(sorted_bp) >= 4:
731
+ layout.breakpoints["wide"] = sorted_bp[3]
732
+
733
+ return layout
734
+
735
+ def _infer_color_temperature(self, colors: List[ColorToken]) -> str:
736
+ """Infer overall color temperature."""
737
+ temps = {"warm": 0, "cool": 0, "neutral": 0}
738
+ for color in colors:
739
+ if color.role not in ("background", "text-primary", "text-secondary", "border"):
740
+ temp = ColorUtils.color_temperature(color.hex)
741
+ temps[temp] += color.frequency
742
+ return max(temps, key=temps.get)
743
+
744
+ def _infer_brand_voice(self, ds: ExtractedDesignSystem) -> str:
745
+ """Infer brand voice from visual signals."""
746
+ signals = []
747
+
748
+ # Color-based signals
749
+ if ds.color_temperature == "warm":
750
+ signals.append("friendly")
751
+ elif ds.color_temperature == "cool":
752
+ signals.append("professional")
753
+
754
+ # Typography signals
755
+ for t in ds.typography:
756
+ name_lower = t.font_family.lower()
757
+ if any(kw in name_lower for kw in ["serif", "garamond", "georgia", "times", "playfair", "cormorant"]):
758
+ signals.append("premium")
759
+ elif any(kw in name_lower for kw in ["mono", "code", "source", "jetbrains", "fira"]):
760
+ signals.append("technical")
761
+ elif any(kw in name_lower for kw in ["comic", "fredoka", "bubblegum", "pacifico"]):
762
+ signals.append("playful")
763
+
764
+ # Shadow depth signals
765
+ if len(self.parser.shadows) > 5:
766
+ signals.append("layered")
767
+ elif len(self.parser.shadows) == 0:
768
+ signals.append("flat")
769
+
770
+ # Determine dominant voice
771
+ if "premium" in signals:
772
+ return "premium"
773
+ elif "technical" in signals:
774
+ return "technical"
775
+ elif "playful" in signals:
776
+ return "playful"
777
+ elif "professional" in signals:
778
+ return "formal"
779
+ return "casual"
780
+
781
+ def _infer_visual_density(self, ds: ExtractedDesignSystem) -> str:
782
+ """Infer visual density from spacing."""
783
+ if not ds.spacing:
784
+ return "medium"
785
+ avg_spacing = sum(s.value_px for s in ds.spacing) / len(ds.spacing)
786
+ if avg_spacing < 12:
787
+ return "high"
788
+ elif avg_spacing > 24:
789
+ return "low"
790
+ return "medium"
791
+
792
+ def _infer_design_era(self, ds: ExtractedDesignSystem) -> str:
793
+ """Infer design era/trend."""
794
+ radius_values = list(self.parser.border_radii.keys())
795
+ has_large_radius = any("16" in r or "20" in r or "24" in r or "full" in r or "9999" in r for r in radius_values)
796
+ has_shadows = len(self.parser.shadows) > 0
797
+ has_glassmorphism = any("backdrop" in str(s).lower() or "blur" in str(s).lower() for s in self.parser.shadows + list(self.parser.css_variables.values()))
798
+
799
+ if has_glassmorphism:
800
+ return "modern-glass"
801
+ elif has_large_radius and has_shadows:
802
+ return "modern-soft"
803
+ elif not has_shadows and not has_large_radius:
804
+ return "modern-flat"
805
+ return "modern"
806
+
807
+ def _match_ui_style(self, ds: ExtractedDesignSystem) -> str:
808
+ """Match to closest known UI style from ui-ux-pro-max library."""
809
+ era = ds.design_era
810
+ voice = ds.brand_voice
811
+ density = ds.visual_density
812
+
813
+ style_map = {
814
+ ("modern-glass", "premium", "low"): "Glassmorphism + Liquid Glass",
815
+ ("modern-glass", "professional", "medium"): "Glassmorphism",
816
+ ("modern-glass", "technical", "high"): "Glassmorphism + Dark Mode",
817
+ ("modern-soft", "friendly", "low"): "Soft UI Evolution",
818
+ ("modern-soft", "premium", "low"): "Neumorphism",
819
+ ("modern-soft", "casual", "medium"): "Claymorphism",
820
+ ("modern-flat", "professional", "medium"): "Minimalism",
821
+ ("modern-flat", "technical", "high"): "Flat Design",
822
+ ("modern-flat", "playful", "medium"): "Vibrant & Block-based",
823
+ ("modern", "premium", "low"): "Minimalism + Glassmorphism",
824
+ ("modern", "professional", "medium"): "Minimalism",
825
+ ("modern", "casual", "medium"): "Flat Design",
826
+ }
827
+
828
+ key = (era, voice, density)
829
+ if key in style_map:
830
+ return style_map[key]
831
+
832
+ # Fallback: match by era
833
+ era_fallback = {
834
+ "modern-glass": "Glassmorphism",
835
+ "modern-soft": "Soft UI Evolution",
836
+ "modern-flat": "Minimalism",
837
+ "modern": "Flat Design"
838
+ }
839
+ return era_fallback.get(era, "Minimalism")
840
+
841
+ def _detect_anti_patterns(self, ds: ExtractedDesignSystem) -> List[str]:
842
+ """Detect UX anti-patterns in the extracted system."""
843
+ issues = []
844
+
845
+ # Check color contrast
846
+ bg_colors = [c for c in ds.colors if c.role == "background"]
847
+ text_colors = [c for c in ds.colors if "text" in c.role]
848
+ if bg_colors and text_colors:
849
+ for text in text_colors:
850
+ for bg in bg_colors:
851
+ ratio = ColorUtils.contrast_ratio(text.hex, bg.hex)
852
+ if ratio < 4.5:
853
+ issues.append(f"Low contrast: {text.hex} on {bg.hex} (ratio: {ratio:.1f}, need >= 4.5)")
854
+
855
+ # Check too many colors
856
+ chromatic = [c for c in ds.colors if c.role not in ("background", "text-primary", "text-secondary", "border")]
857
+ if len(chromatic) > 6:
858
+ issues.append(f"Too many accent colors ({len(chromatic)}). Recommend <= 5 for consistency.")
859
+
860
+ # Check font count
861
+ if len(ds.typography) > 3:
862
+ issues.append(f"Too many fonts ({len(ds.typography)}). Recommend <= 3 (heading + body + optional mono).")
863
+
864
+ # Check spacing consistency
865
+ if ds.spacing:
866
+ values = [s.value_px for s in ds.spacing]
867
+ base_4 = sum(1 for v in values if v % 4 == 0)
868
+ ratio = base_4 / len(values) if values else 0
869
+ if ratio < 0.5:
870
+ issues.append("Inconsistent spacing scale. Recommend using 4px or 8px base unit.")
871
+
872
+ # Check missing transitions
873
+ if not self.parser.transitions:
874
+ issues.append("No transitions detected. Add 150-300ms transitions for hover/focus states.")
875
+
876
+ return issues
877
+
878
+
879
+ # ============================================================================
880
+ # OUTPUT FORMATTERS
881
+ # ============================================================================
882
+
883
+ class OutputFormatter:
884
+ """Format extracted design system for various outputs."""
885
+
886
+ @staticmethod
887
+ def to_markdown(ds: ExtractedDesignSystem) -> str:
888
+ """Generate comprehensive EXTRACTED.md file."""
889
+ lines = []
890
+
891
+ lines.append(f"# Extracted Design System: {ds.project_name}")
892
+ lines.append("")
893
+ lines.append(f"> **Source:** {ds.source_url or 'Local analysis'}")
894
+ lines.append(f"> **Extracted:** {ds.extracted_at}")
895
+ lines.append(f"> **Brand Voice:** {ds.brand_voice}")
896
+ lines.append(f"> **Visual Density:** {ds.visual_density}")
897
+ lines.append(f"> **Color Temperature:** {ds.color_temperature}")
898
+ lines.append(f"> **Design Era:** {ds.design_era}")
899
+ lines.append(f"> **Closest UI Style:** {ds.ui_style_match}")
900
+ lines.append("")
901
+ lines.append("---")
902
+ lines.append("")
903
+
904
+ # Colors
905
+ lines.append("## Color Palette")
906
+ lines.append("")
907
+ lines.append("| Hex | Role | Frequency | Contrast (White) | WCAG AA | WCAG AAA |")
908
+ lines.append("|-----|------|-----------|-------------------|---------|----------|")
909
+ for c in ds.colors[:12]:
910
+ lines.append(f"| `{c.hex}` | {c.role} | {c.frequency} | {c.contrast_white} | {'Pass' if c.wcag_aa else 'Fail'} | {'Pass' if c.wcag_aaa else 'Fail'} |")
911
+ lines.append("")
912
+
913
+ # CSS Variables for colors
914
+ lines.append("### Color CSS Variables")
915
+ lines.append("")
916
+ lines.append("```css")
917
+ lines.append(":root {")
918
+ for c in ds.colors[:8]:
919
+ var_name = f"--color-{c.role.replace(' ', '-')}"
920
+ lines.append(f" {var_name}: {c.hex};")
921
+ lines.append("}")
922
+ lines.append("```")
923
+ lines.append("")
924
+
925
+ # Typography
926
+ lines.append("## Typography")
927
+ lines.append("")
928
+ lines.append("| Font | Role | Weight | Source |")
929
+ lines.append("|------|------|--------|--------|")
930
+ for t in ds.typography:
931
+ lines.append(f"| {t.font_family} | {t.role} | {t.weight} | {t.source} |")
932
+ lines.append("")
933
+
934
+ if ds.typography:
935
+ lines.append("### Typography CSS")
936
+ lines.append("")
937
+ lines.append("```css")
938
+ for t in ds.typography:
939
+ role_class = t.role.replace("+", "-")
940
+ lines.append(f".text-{role_class} {{")
941
+ lines.append(f" font-family: '{t.font_family}', sans-serif;")
942
+ lines.append(f" font-weight: {t.weight};")
943
+ lines.append(f"}}")
944
+ lines.append("")
945
+ lines.append("```")
946
+ lines.append("")
947
+
948
+ # Spacing
949
+ lines.append("## Spacing Scale")
950
+ lines.append("")
951
+ lines.append("| Value (px) | CSS Variable | Frequency |")
952
+ lines.append("|------------|--------------|-----------|")
953
+ for s in ds.spacing[:10]:
954
+ lines.append(f"| {s.value_px}px | `{s.css_variable}` | {s.frequency} |")
955
+ lines.append("")
956
+
957
+ # Components
958
+ lines.append("## Component Patterns")
959
+ lines.append("")
960
+ for comp in ds.components:
961
+ lines.append(f"### {comp.name.title()}")
962
+ lines.append("")
963
+ lines.append(f"- **Variants:** {', '.join(comp.variants)}")
964
+ lines.append(f"- **Border Radius:** {comp.border_radius}")
965
+ if comp.shadow:
966
+ lines.append(f"- **Shadow:** {comp.shadow}")
967
+ if comp.transition:
968
+ lines.append(f"- **Transition:** {comp.transition}")
969
+ lines.append("")
970
+ lines.append("```css")
971
+ lines.append(comp.css_snippet)
972
+ lines.append("```")
973
+ lines.append("")
974
+
975
+ # Layout
976
+ lines.append("## Layout")
977
+ lines.append("")
978
+ lines.append(f"- **Max Width:** {ds.layout.max_width}")
979
+ lines.append(f"- **Grid System:** {ds.layout.grid_system}")
980
+ lines.append(f"- **Breakpoints:**")
981
+ for name, value in ds.layout.breakpoints.items():
982
+ lines.append(f" - {name}: {value}px")
983
+ lines.append("")
984
+
985
+ # Anti-patterns
986
+ if ds.anti_patterns_detected:
987
+ lines.append("## Anti-Patterns Detected")
988
+ lines.append("")
989
+ for issue in ds.anti_patterns_detected:
990
+ lines.append(f"- {issue}")
991
+ lines.append("")
992
+
993
+ # Recommendations
994
+ lines.append("## Recommendations")
995
+ lines.append("")
996
+ lines.append("Based on the analysis, here are recommendations to improve the design system:")
997
+ lines.append("")
998
+ lines.append(f"1. **UI Style Match:** Your design most closely matches **{ds.ui_style_match}**. "
999
+ f"Consider aligning fully with this style for consistency.")
1000
+ lines.append(f"2. **Brand Voice:** Detected **{ds.brand_voice}** voice. "
1001
+ f"Ensure all new components maintain this tone.")
1002
+ lines.append(f"3. **Color Temperature:** **{ds.color_temperature}**. "
1003
+ f"New accent colors should stay within this temperature range.")
1004
+ lines.append("")
1005
+
1006
+ return "\n".join(lines)
1007
+
1008
+ @staticmethod
1009
+ def to_skill(ds: ExtractedDesignSystem) -> str:
1010
+ """Generate a BRAND-SKILL.md file for AI coding tools."""
1011
+ lines = []
1012
+
1013
+ lines.append(f"# Brand Skill: {ds.project_name}")
1014
+ lines.append("")
1015
+ lines.append("> **AUTO-GENERATED** from extracted design system.")
1016
+ lines.append("> When building UI for this project, ALWAYS follow these rules.")
1017
+ lines.append("> These rules OVERRIDE generic style recommendations.")
1018
+ lines.append("")
1019
+ lines.append("---")
1020
+ lines.append("")
1021
+
1022
+ # Brand Identity
1023
+ lines.append("## Brand Identity")
1024
+ lines.append("")
1025
+ lines.append(f"- **Voice:** {ds.brand_voice}")
1026
+ lines.append(f"- **Visual Density:** {ds.visual_density}")
1027
+ lines.append(f"- **Color Temperature:** {ds.color_temperature}")
1028
+ lines.append(f"- **Base Style:** {ds.ui_style_match}")
1029
+ lines.append("")
1030
+
1031
+ # Mandatory Colors
1032
+ lines.append("## Mandatory Color Palette")
1033
+ lines.append("")
1034
+ lines.append("ALWAYS use these exact colors. Do NOT substitute with generic palettes.")
1035
+ lines.append("")
1036
+ lines.append("```css")
1037
+ lines.append(":root {")
1038
+ for c in ds.colors[:8]:
1039
+ var_name = f"--brand-{c.role.replace(' ', '-')}"
1040
+ lines.append(f" {var_name}: {c.hex};")
1041
+ lines.append("}")
1042
+ lines.append("```")
1043
+ lines.append("")
1044
+
1045
+ # Mandatory Typography
1046
+ lines.append("## Mandatory Typography")
1047
+ lines.append("")
1048
+ lines.append("ALWAYS use these fonts. Do NOT fall back to Inter/system fonts.")
1049
+ lines.append("")
1050
+ for t in ds.typography:
1051
+ lines.append(f"- **{t.role}:** `{t.font_family}` (weight: {t.weight}, source: {t.source})")
1052
+ lines.append("")
1053
+
1054
+ # Component Rules
1055
+ lines.append("## Component Rules")
1056
+ lines.append("")
1057
+ lines.append("All components MUST follow these patterns:")
1058
+ lines.append("")
1059
+ for comp in ds.components:
1060
+ lines.append(f"### {comp.name.title()}")
1061
+ lines.append(f"- Border radius: `{comp.border_radius}`")
1062
+ if comp.shadow:
1063
+ lines.append(f"- Shadow: `{comp.shadow}`")
1064
+ if comp.transition:
1065
+ lines.append(f"- Transition: `{comp.transition}`")
1066
+ lines.append(f"- Variants: {', '.join(comp.variants)}")
1067
+ lines.append("")
1068
+
1069
+ # Deviation Rules
1070
+ lines.append("## Deviation Policy")
1071
+ lines.append("")
1072
+ lines.append("If you MUST deviate from the brand skill:")
1073
+ lines.append("")
1074
+ lines.append("1. Document the deviation in a comment: `/* DEVIATION: reason */`")
1075
+ lines.append("2. Ensure the deviation maintains brand voice ({})".format(ds.brand_voice))
1076
+ lines.append("3. Keep color temperature consistent ({})".format(ds.color_temperature))
1077
+ lines.append("4. Log the deviation for design review")
1078
+ lines.append("")
1079
+
1080
+ # Anti-patterns
1081
+ lines.append("## Brand Anti-Patterns (NEVER DO)")
1082
+ lines.append("")
1083
+ if ds.anti_patterns_detected:
1084
+ for issue in ds.anti_patterns_detected:
1085
+ lines.append(f"- {issue}")
1086
+ lines.append("- Do NOT use colors outside the brand palette without documentation")
1087
+ lines.append("- Do NOT mix icon libraries")
1088
+ lines.append("- Do NOT use different border-radius values than defined above")
1089
+ lines.append("")
1090
+
1091
+ return "\n".join(lines)
1092
+
1093
+ @staticmethod
1094
+ def to_tailwind_config(ds: ExtractedDesignSystem) -> str:
1095
+ """Generate Tailwind CSS config from extracted tokens."""
1096
+ config = {
1097
+ "theme": {
1098
+ "extend": {
1099
+ "colors": {},
1100
+ "fontFamily": {},
1101
+ "borderRadius": {},
1102
+ "boxShadow": {},
1103
+ "spacing": {}
1104
+ }
1105
+ }
1106
+ }
1107
+
1108
+ # Colors
1109
+ for c in ds.colors[:8]:
1110
+ key = c.role.replace(" ", "-").replace("_", "-")
1111
+ config["theme"]["extend"]["colors"][key] = c.hex
1112
+
1113
+ # Typography
1114
+ for t in ds.typography:
1115
+ key = t.role.replace("+", "-")
1116
+ config["theme"]["extend"]["fontFamily"][key] = [t.font_family, "sans-serif"]
1117
+
1118
+ # Border radius
1119
+ if ds.components:
1120
+ for comp in ds.components:
1121
+ if comp.border_radius:
1122
+ config["theme"]["extend"]["borderRadius"]["brand"] = comp.border_radius
1123
+ break
1124
+
1125
+ # Spacing
1126
+ for s in ds.spacing[:8]:
1127
+ key = s.css_variable.replace("--space-", "")
1128
+ config["theme"]["extend"]["spacing"][key] = f"{s.value_px}px"
1129
+
1130
+ return f"""// tailwind.config.js — Auto-generated from {ds.project_name} design extraction
1131
+ // Generated: {ds.extracted_at}
1132
+
1133
+ /** @type {{import('tailwindcss').Config}} */
1134
+ module.exports = {json.dumps(config, indent=2)}
1135
+ """
1136
+
1137
+ @staticmethod
1138
+ def to_css_variables(ds: ExtractedDesignSystem) -> str:
1139
+ """Generate CSS custom properties file."""
1140
+ lines = []
1141
+ lines.append(f"/* {ds.project_name} — Design Tokens */")
1142
+ lines.append(f"/* Auto-extracted: {ds.extracted_at} */")
1143
+ lines.append(f"/* Source: {ds.source_url or 'local'} */")
1144
+ lines.append("")
1145
+ lines.append(":root {")
1146
+ lines.append(" /* Colors */")
1147
+ for c in ds.colors[:10]:
1148
+ var_name = f"--brand-{c.role.replace(' ', '-')}"
1149
+ lines.append(f" {var_name}: {c.hex};")
1150
+
1151
+ lines.append("")
1152
+ lines.append(" /* Typography */")
1153
+ for t in ds.typography:
1154
+ role = t.role.replace("+", "-")
1155
+ lines.append(f" --font-{role}: '{t.font_family}', sans-serif;")
1156
+ lines.append(f" --font-weight-{role}: {t.weight};")
1157
+
1158
+ lines.append("")
1159
+ lines.append(" /* Spacing */")
1160
+ for s in ds.spacing[:8]:
1161
+ lines.append(f" {s.css_variable}: {s.value_px}px;")
1162
+
1163
+ lines.append("")
1164
+ lines.append(" /* Shadows */")
1165
+ if ds.components:
1166
+ for comp in ds.components:
1167
+ if comp.shadow:
1168
+ lines.append(f" --shadow-{comp.name}: {comp.shadow};")
1169
+
1170
+ lines.append("")
1171
+ lines.append(" /* Border Radius */")
1172
+ if ds.components:
1173
+ for comp in ds.components:
1174
+ if comp.border_radius:
1175
+ lines.append(f" --radius-{comp.name}: {comp.border_radius};")
1176
+ break # Usually uniform
1177
+
1178
+ lines.append("")
1179
+ lines.append(" /* Transitions */")
1180
+ if ds.components:
1181
+ for comp in ds.components:
1182
+ if comp.transition:
1183
+ lines.append(f" --transition-default: {comp.transition};")
1184
+ break
1185
+
1186
+ lines.append("")
1187
+ lines.append(" /* Layout */")
1188
+ lines.append(f" --max-width: {ds.layout.max_width};")
1189
+ for name, value in ds.layout.breakpoints.items():
1190
+ lines.append(f" --breakpoint-{name}: {value}px;")
1191
+
1192
+ lines.append("}")
1193
+ lines.append("")
1194
+
1195
+ return "\n".join(lines)
1196
+
1197
+
1198
+ # ============================================================================
1199
+ # MAIN EXTRACTION PIPELINE
1200
+ # ============================================================================
1201
+
1202
+ class DesignSystemExtractor:
1203
+ """Main extraction pipeline orchestrator."""
1204
+
1205
+ def __init__(self, project_name: str):
1206
+ self.project_name = project_name
1207
+ self.parser = CSSParser()
1208
+
1209
+ def extract_from_css_files(self, css_files: List[str]) -> ExtractedDesignSystem:
1210
+ """Extract from local CSS files."""
1211
+ for filepath in css_files:
1212
+ path = Path(filepath)
1213
+ if path.exists() and path.suffix == '.css':
1214
+ with open(path, 'r', encoding='utf-8') as f:
1215
+ self.parser.parse_css(f.read(), context=path.name)
1216
+
1217
+ analyzer = DesignSystemAnalyzer(self.parser, self.project_name)
1218
+ return analyzer.analyze()
1219
+
1220
+ def extract_from_html_files(self, html_files: List[str]) -> ExtractedDesignSystem:
1221
+ """Extract from local HTML files."""
1222
+ for filepath in html_files:
1223
+ path = Path(filepath)
1224
+ if path.exists() and path.suffix in ('.html', '.htm', '.vue', '.svelte', '.jsx', '.tsx'):
1225
+ with open(path, 'r', encoding='utf-8') as f:
1226
+ content = f.read()
1227
+ self.parser.parse_html(content)
1228
+
1229
+ analyzer = DesignSystemAnalyzer(self.parser, self.project_name)
1230
+ return analyzer.analyze()
1231
+
1232
+ def extract_from_directory(self, directory: str) -> ExtractedDesignSystem:
1233
+ """Extract from all CSS/HTML files in a directory recursively."""
1234
+ dir_path = Path(directory)
1235
+ if not dir_path.exists():
1236
+ print(f"Error: Directory not found: {directory}", file=sys.stderr)
1237
+ sys.exit(1)
1238
+
1239
+ css_extensions = {'.css'}
1240
+ html_extensions = {'.html', '.htm', '.vue', '.svelte', '.jsx', '.tsx'}
1241
+
1242
+ file_count = 0
1243
+ for path in dir_path.rglob('*'):
1244
+ if path.suffix in css_extensions:
1245
+ try:
1246
+ with open(path, 'r', encoding='utf-8', errors='ignore') as f:
1247
+ self.parser.parse_css(f.read(), context=path.name)
1248
+ file_count += 1
1249
+ except Exception as e:
1250
+ print(f"Warning: Could not parse {path}: {e}", file=sys.stderr)
1251
+
1252
+ elif path.suffix in html_extensions:
1253
+ try:
1254
+ with open(path, 'r', encoding='utf-8', errors='ignore') as f:
1255
+ self.parser.parse_html(f.read())
1256
+ file_count += 1
1257
+ except Exception as e:
1258
+ print(f"Warning: Could not parse {path}: {e}", file=sys.stderr)
1259
+
1260
+ print(f"Analyzed {file_count} files from {directory}", file=sys.stderr)
1261
+
1262
+ analyzer = DesignSystemAnalyzer(self.parser, self.project_name, source_url=directory)
1263
+ return analyzer.analyze()
1264
+
1265
+ def extract_from_url(self, url: str) -> ExtractedDesignSystem:
1266
+ """Extract from a live URL by fetching HTML and linked CSS."""
1267
+ try:
1268
+ import urllib.request
1269
+ import urllib.parse
1270
+
1271
+ print(f"Fetching {url}...", file=sys.stderr)
1272
+
1273
+ # Fetch HTML
1274
+ req = urllib.request.Request(url, headers={
1275
+ 'User-Agent': 'Mozilla/5.0 (UI-UX-Pro-Max Extractor)'
1276
+ })
1277
+ with urllib.request.urlopen(req, timeout=15) as response:
1278
+ html_content = response.read().decode('utf-8', errors='ignore')
1279
+
1280
+ self.parser.parse_html(html_content)
1281
+
1282
+ # Find and fetch linked CSS files
1283
+ css_link_pattern = re.compile(
1284
+ r'<link[^>]*href=["\']([^"\']*\.css[^"\']*)["\']', re.IGNORECASE
1285
+ )
1286
+ for match in css_link_pattern.finditer(html_content):
1287
+ css_url = match.group(1)
1288
+ if not css_url.startswith('http'):
1289
+ css_url = urllib.parse.urljoin(url, css_url)
1290
+
1291
+ try:
1292
+ print(f" Fetching CSS: {css_url[:80]}...", file=sys.stderr)
1293
+ css_req = urllib.request.Request(css_url, headers={
1294
+ 'User-Agent': 'Mozilla/5.0 (UI-UX-Pro-Max Extractor)'
1295
+ })
1296
+ with urllib.request.urlopen(css_req, timeout=10) as css_response:
1297
+ css_content = css_response.read().decode('utf-8', errors='ignore')
1298
+ self.parser.parse_css(css_content, context=css_url.split('/')[-1])
1299
+ except Exception as e:
1300
+ print(f" Warning: Could not fetch CSS {css_url}: {e}", file=sys.stderr)
1301
+
1302
+ analyzer = DesignSystemAnalyzer(self.parser, self.project_name, source_url=url)
1303
+ return analyzer.analyze()
1304
+
1305
+ except ImportError:
1306
+ print("Error: urllib not available. Use --directory mode instead.", file=sys.stderr)
1307
+ sys.exit(1)
1308
+ except Exception as e:
1309
+ print(f"Error fetching URL: {e}", file=sys.stderr)
1310
+ sys.exit(1)
1311
+
1312
+
1313
+ # ============================================================================
1314
+ # CLI ENTRY POINT
1315
+ # ============================================================================
1316
+
1317
+ def main():
1318
+ parser = argparse.ArgumentParser(
1319
+ description="Extract design system from existing websites/apps",
1320
+ formatter_class=argparse.RawDescriptionHelpFormatter,
1321
+ epilog="""
1322
+ Examples:
1323
+ # Extract from URL
1324
+ python3 extractor.py --url https://example.com -p "MyBrand"
1325
+
1326
+ # Extract from local project directory
1327
+ python3 extractor.py --directory ./src -p "MyApp"
1328
+
1329
+ # Extract from specific CSS files
1330
+ python3 extractor.py --css style.css theme.css -p "MyProject"
1331
+
1332
+ # Generate complete skill set
1333
+ python3 extractor.py --url https://example.com --generate-skill -p "MyBrand"
1334
+
1335
+ # Export as Tailwind config
1336
+ python3 extractor.py --directory ./src -p "MyApp" --format tailwind
1337
+ """
1338
+ )
1339
+
1340
+ # Input sources (mutually exclusive)
1341
+ input_group = parser.add_mutually_exclusive_group(required=True)
1342
+ input_group.add_argument("--url", "-u", help="URL to analyze")
1343
+ input_group.add_argument("--directory", "-d", help="Local directory to analyze")
1344
+ input_group.add_argument("--css", nargs="+", help="Specific CSS files to analyze")
1345
+ input_group.add_argument("--html", nargs="+", help="Specific HTML files to analyze")
1346
+
1347
+ # Options
1348
+ parser.add_argument("--project-name", "-p", required=True, help="Project/brand name")
1349
+ parser.add_argument("--output", "-o", default=None, help="Output file path (default: stdout)")
1350
+ parser.add_argument("--format", "-f",
1351
+ choices=["markdown", "skill", "tailwind", "css-vars", "json"],
1352
+ default="markdown",
1353
+ help="Output format (default: markdown)")
1354
+ parser.add_argument("--generate-skill", action="store_true",
1355
+ help="Also generate BRAND-SKILL.md file")
1356
+ parser.add_argument("--persist", action="store_true",
1357
+ help="Save to design-system/ folder structure")
1358
+
1359
+ args = parser.parse_args()
1360
+
1361
+ # Initialize extractor
1362
+ extractor = DesignSystemExtractor(args.project_name)
1363
+
1364
+ # Extract based on input source
1365
+ if args.url:
1366
+ ds = extractor.extract_from_url(args.url)
1367
+ elif args.directory:
1368
+ ds = extractor.extract_from_directory(args.directory)
1369
+ elif args.css:
1370
+ ds = extractor.extract_from_css_files(args.css)
1371
+ elif args.html:
1372
+ ds = extractor.extract_from_html_files(args.html)
1373
+
1374
+ # Format output
1375
+ formatter = OutputFormatter()
1376
+ format_map = {
1377
+ "markdown": formatter.to_markdown,
1378
+ "skill": formatter.to_skill,
1379
+ "tailwind": formatter.to_tailwind_config,
1380
+ "css-vars": formatter.to_css_variables,
1381
+ "json": lambda ds: json.dumps(asdict(ds), indent=2, ensure_ascii=False, default=str),
1382
+ }
1383
+
1384
+ output = format_map[args.format](ds)
1385
+
1386
+ # Write output
1387
+ if args.output:
1388
+ output_path = Path(args.output)
1389
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1390
+ with open(output_path, 'w', encoding='utf-8') as f:
1391
+ f.write(output)
1392
+ print(f"Written to {output_path}", file=sys.stderr)
1393
+ else:
1394
+ print(output)
1395
+
1396
+ # Generate skill if requested
1397
+ if args.generate_skill and args.format != "skill":
1398
+ skill_output = formatter.to_skill(ds)
1399
+ if args.persist:
1400
+ project_slug = args.project_name.lower().replace(' ', '-')
1401
+ skill_dir = Path("design-system") / project_slug
1402
+ skill_dir.mkdir(parents=True, exist_ok=True)
1403
+
1404
+ # Write EXTRACTED.md
1405
+ extracted_path = skill_dir / "EXTRACTED.md"
1406
+ with open(extracted_path, 'w', encoding='utf-8') as f:
1407
+ f.write(formatter.to_markdown(ds))
1408
+ print(f"Written to {extracted_path}", file=sys.stderr)
1409
+
1410
+ # Write BRAND-SKILL.md
1411
+ skill_path = skill_dir / "BRAND-SKILL.md"
1412
+ with open(skill_path, 'w', encoding='utf-8') as f:
1413
+ f.write(skill_output)
1414
+ print(f"Written to {skill_path}", file=sys.stderr)
1415
+
1416
+ # Write tailwind config
1417
+ tailwind_path = skill_dir / "tailwind.config.js"
1418
+ with open(tailwind_path, 'w', encoding='utf-8') as f:
1419
+ f.write(formatter.to_tailwind_config(ds))
1420
+ print(f"Written to {tailwind_path}", file=sys.stderr)
1421
+
1422
+ # Write CSS variables
1423
+ css_path = skill_dir / "design-tokens.css"
1424
+ with open(css_path, 'w', encoding='utf-8') as f:
1425
+ f.write(formatter.to_css_variables(ds))
1426
+ print(f"Written to {css_path}", file=sys.stderr)
1427
+
1428
+ print(f"\nComplete design system persisted to design-system/{project_slug}/", file=sys.stderr)
1429
+ else:
1430
+ print("\n" + "=" * 60, file=sys.stderr)
1431
+ print("BRAND SKILL (use --persist to save to file):", file=sys.stderr)
1432
+ print("=" * 60, file=sys.stderr)
1433
+ print(skill_output)
1434
+
1435
+
1436
+ if __name__ == "__main__":
1437
+ main()