codymaster 4.8.0 → 7.0.0

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 (416) hide show
  1. package/CHANGELOG.md +331 -7
  2. package/README.md +226 -296
  3. package/dist/advisory-handoff.js +89 -0
  4. package/dist/advisory-report.js +105 -0
  5. package/dist/agent/antigravity.js +152 -0
  6. package/dist/agent/backend.js +2 -0
  7. package/dist/agent/claude.js +196 -0
  8. package/dist/agent/codex.js +204 -0
  9. package/dist/agent/copilot.js +284 -0
  10. package/dist/agent/cursor.js +211 -0
  11. package/dist/agent/factory.js +30 -0
  12. package/dist/agent/gemini.js +142 -0
  13. package/dist/agent/opencode.js +205 -0
  14. package/dist/agent/spawn-helper.js +237 -0
  15. package/dist/agent/version.js +25 -0
  16. package/dist/browse/adapter-factory.js +69 -0
  17. package/dist/browse/adapters/agent-browser-adapter.js +305 -0
  18. package/dist/browse/adapters/playwright-adapter.js +309 -0
  19. package/dist/browse/adapters/types.js +6 -0
  20. package/dist/browse/error-collector.js +132 -0
  21. package/dist/browse/event-log.js +109 -0
  22. package/dist/browse/index.js +17 -0
  23. package/dist/browse-server.js +204 -120
  24. package/dist/cli/command-registry.js +20 -0
  25. package/dist/cli/commands/bench.js +69 -0
  26. package/dist/cli/commands/brain.js +108 -0
  27. package/dist/cli/commands/dashboard.js +76 -2
  28. package/dist/cli/commands/engineering.js +326 -4
  29. package/dist/cli/commands/evolve.js +123 -0
  30. package/dist/cli/commands/install.js +160 -0
  31. package/dist/cli/commands/learn.js +181 -0
  32. package/dist/cli/commands/mcp-serve.js +104 -0
  33. package/dist/cli/commands/parallel.js +138 -0
  34. package/dist/cli/commands/quality.js +105 -0
  35. package/dist/cli/commands/stack.js +49 -0
  36. package/dist/cli/commands/update.js +159 -0
  37. package/dist/cli/update-check.js +94 -10
  38. package/dist/cm-config.js +0 -18
  39. package/dist/codybench/judges/automated.js +31 -0
  40. package/dist/codybench/runners/claude-code.js +32 -0
  41. package/dist/codybench/suites/memory-retention.js +85 -0
  42. package/dist/codybench/suites/tdd-regression.js +35 -0
  43. package/dist/codybench/suites/token-efficiency.js +55 -0
  44. package/dist/codybench/types.js +2 -0
  45. package/dist/context-db.js +157 -0
  46. package/dist/continuity.js +5 -7
  47. package/dist/dashboard.js +47 -6
  48. package/dist/data.js +35 -0
  49. package/dist/execution/tdd-gate.js +113 -0
  50. package/dist/execution-analyzer.js +138 -0
  51. package/dist/executor/cancel.js +34 -0
  52. package/dist/executor/gc.js +74 -0
  53. package/dist/executor/index.js +14 -0
  54. package/dist/executor/runner.js +70 -0
  55. package/dist/executor/workdir.js +31 -0
  56. package/dist/handoff/contracts.js +22 -0
  57. package/dist/handoff/index.js +18 -0
  58. package/dist/handoff/io.js +121 -0
  59. package/dist/index.js +7 -3
  60. package/dist/indexer/skills-lib.js +533 -0
  61. package/dist/indexer/skills-map.js +1374 -0
  62. package/dist/indexer/skills.js +16 -0
  63. package/dist/indexer/stack-detect.js +219 -0
  64. package/dist/install/copy.js +98 -0
  65. package/dist/install/engine.js +42 -0
  66. package/dist/install/paths.js +70 -0
  67. package/dist/install/platforms/_simple.js +85 -0
  68. package/dist/install/platforms/antigravity.js +91 -0
  69. package/dist/install/platforms/claude-code.js +107 -0
  70. package/dist/install/platforms/cursor.js +77 -0
  71. package/dist/install/platforms/index.js +27 -0
  72. package/dist/install/platforms/simple.js +163 -0
  73. package/dist/install/profiles.js +75 -0
  74. package/dist/install/types.js +2 -0
  75. package/dist/learning-promoter.js +246 -0
  76. package/dist/learnings.js +208 -0
  77. package/dist/mcp-context-server.js +230 -1
  78. package/dist/middleware/metrics.js +30 -0
  79. package/dist/middleware/security-headers.js +14 -0
  80. package/dist/realtime/event-bus.js +29 -0
  81. package/dist/realtime/ws-hub.js +91 -0
  82. package/dist/schemas/task-schema.js +48 -0
  83. package/dist/schemas/validate.js +18 -0
  84. package/dist/skill-chain.js +63 -1
  85. package/dist/skill-evolver.js +456 -0
  86. package/dist/skill-execution-cache.js +254 -0
  87. package/dist/skills-lock.js +96 -0
  88. package/dist/smart-brain-router.js +184 -0
  89. package/dist/sprint-pipeline.js +26 -0
  90. package/dist/storage/index.js +21 -0
  91. package/dist/storage/repos/activity-repo.js +46 -0
  92. package/dist/storage/repos/message-repo.js +39 -0
  93. package/dist/storage/repos/project-repo.js +56 -0
  94. package/dist/storage/repos/task-repo.js +142 -0
  95. package/dist/storage/services/project-service.js +49 -0
  96. package/dist/storage/services/task-service.js +97 -0
  97. package/dist/storage/sqlite.js +113 -0
  98. package/dist/storage-backend.js +10 -8
  99. package/dist/tier-classify.js +131 -0
  100. package/dist/token-budget.js +88 -0
  101. package/dist/ui/onboarding.js +51 -15
  102. package/dist/utils/cli-utils.js +7 -2
  103. package/dist/utils/design-taste.js +108 -0
  104. package/dist/utils/output-compress.js +143 -0
  105. package/dist/vibecoding-index.js +126 -0
  106. package/package.json +20 -6
  107. package/public/dashboard/app.js +52 -1
  108. package/scripts/build-skills-lock.mjs +88 -0
  109. package/scripts/build-skills.mjs +187 -28
  110. package/scripts/compress-skill.mjs +73 -0
  111. package/scripts/deprecate-skill.mjs +72 -0
  112. package/scripts/install.sh +170 -0
  113. package/scripts/mcp-bridge.js +2 -2
  114. package/scripts/postinstall.js +53 -335
  115. package/scripts/update-changelog.sh +88 -0
  116. package/scripts/validate-skills.mjs +101 -4
  117. package/skills/CLAUDE.md +0 -5
  118. package/skills/_shared/SKILL_TEMPLATE.md +62 -0
  119. package/skills/_shared/helpers.md +2 -8
  120. package/skills/cm-autopilot/scripts/autopilot.py +19 -2
  121. package/skills/cm-brainstorm-idea/SKILL.md +9 -0
  122. package/skills/cm-browse/SKILL.md +6 -0
  123. package/skills/cm-clean-code/SKILL.md +20 -0
  124. package/skills/cm-code-review/SKILL.md +21 -0
  125. package/skills/cm-codeintell/SKILL.md +9 -0
  126. package/skills/cm-conductor-worktrees/SKILL.archive.md +28 -0
  127. package/skills/cm-conductor-worktrees/SKILL.md +20 -18
  128. package/skills/cm-continuity/SKILL.md +41 -33
  129. package/skills/cm-dashboard/SKILL.archive.md +15 -0
  130. package/skills/cm-dashboard/SKILL.md +20 -9
  131. package/skills/cm-dashboard/ui/app.js +9 -1
  132. package/skills/cm-debugging/SKILL.md +9 -0
  133. package/skills/cm-design-studio/SKILL.archive.md +34 -0
  134. package/skills/cm-design-studio/SKILL.md +20 -24
  135. package/skills/cm-design-system/SKILL.md +1 -0
  136. package/skills/cm-ecosystem-roadmap/SKILL.md +4 -0
  137. package/skills/cm-engineering-meta/SKILL.archive.md +73 -0
  138. package/skills/cm-engineering-meta/SKILL.md +19 -62
  139. package/skills/cm-execution/SKILL.md +98 -0
  140. package/skills/cm-git-worktrees/SKILL.archive.md +157 -0
  141. package/skills/cm-git-worktrees/SKILL.md +15 -146
  142. package/skills/cm-guardian-runtime/SKILL.md +5 -1
  143. package/skills/cm-identity-guard/SKILL.md +8 -0
  144. package/skills/cm-mcp-engineering/SKILL.md +4 -0
  145. package/skills/cm-planning/SKILL.md +63 -92
  146. package/skills/cm-post-deploy-canary/SKILL.archive.md +22 -0
  147. package/skills/cm-post-deploy-canary/SKILL.md +20 -12
  148. package/skills/cm-project-bootstrap/SKILL.md +11 -0
  149. package/skills/cm-qa-visual-cli/SKILL.archive.md +22 -0
  150. package/skills/cm-qa-visual-cli/SKILL.md +19 -11
  151. package/skills/cm-quality-gate/SKILL.md +38 -0
  152. package/skills/cm-retro-cli/SKILL.md +4 -0
  153. package/skills/cm-safe-deploy/SKILL.md +9 -0
  154. package/skills/cm-second-opinion-cli/SKILL.archive.md +23 -0
  155. package/skills/cm-second-opinion-cli/SKILL.md +20 -13
  156. package/skills/cm-secret-shield/SKILL.archive.md +580 -0
  157. package/skills/cm-secret-shield/SKILL.md +15 -569
  158. package/skills/cm-security-gate/SKILL.archive.md +239 -0
  159. package/skills/cm-security-gate/SKILL.md +16 -228
  160. package/skills/cm-skill-chain/SKILL.md +25 -4
  161. package/skills/cm-skill-evolution/SKILL.md +83 -0
  162. package/skills/cm-skill-health/SKILL.archive.md +83 -0
  163. package/skills/cm-skill-health/SKILL.md +26 -0
  164. package/skills/cm-skill-index/SKILL.md +19 -3
  165. package/skills/cm-skill-mastery/SKILL.archive.md +156 -0
  166. package/skills/cm-skill-mastery/SKILL.md +16 -146
  167. package/skills/cm-skill-search/SKILL.archive.md +49 -0
  168. package/skills/cm-skill-search/SKILL.md +26 -0
  169. package/skills/cm-skill-share/SKILL.archive.md +58 -0
  170. package/skills/cm-skill-share/SKILL.md +26 -0
  171. package/skills/cm-sprint-bus/SKILL.md +13 -0
  172. package/skills/cm-start/SKILL.md +17 -10
  173. package/skills/cm-tdd/SKILL.md +21 -2
  174. package/skills/cm-terminal/SKILL.md +15 -0
  175. package/skills/cm-test-gate/SKILL.archive.md +245 -0
  176. package/skills/cm-test-gate/SKILL.md +15 -234
  177. package/skills/cm-ui-preview/SKILL.archive.md +153 -0
  178. package/skills/cm-ui-preview/SKILL.md +16 -143
  179. package/skills/cm-ux-master/cli/uxmaster/commands/mcp.py +1 -1
  180. package/skills/cm-ux-master/mcp/mcp-config.json +1 -1
  181. package/skills/cm-ux-master/mcp/server.py +2 -2
  182. package/skills/profiles/design.txt +1 -1
  183. package/skills/profiles/full.txt +4 -10
  184. package/skills/profiles/growth.txt +8 -8
  185. package/skills/profiles/knowledge.txt +1 -1
  186. package/skills/profiles/top35.json +41 -0
  187. package/adapters/antigravity.js +0 -15
  188. package/adapters/claude-code.js +0 -17
  189. package/adapters/cursor.js +0 -16
  190. package/install.sh +0 -1125
  191. package/scripts/viking-demo.ts +0 -105
  192. package/skills/cm-ads-tracker/SKILL.md +0 -401
  193. package/skills/cm-ads-tracker/evals/evals.json +0 -55
  194. package/skills/cm-ads-tracker/references/gtm-architecture.md +0 -321
  195. package/skills/cm-ads-tracker/references/industry-events.md +0 -294
  196. package/skills/cm-ads-tracker/references/platforms-api.md +0 -238
  197. package/skills/cm-ads-tracker/templates/capi-payload.md +0 -79
  198. package/skills/cm-ads-tracker/templates/datalayer-push.js +0 -104
  199. package/skills/cm-ads-tracker/templates/gtm-variables.js +0 -56
  200. package/skills/cm-auto-publisher/SKILL.md +0 -81
  201. package/skills/cm-booking-calendar/SKILL.md +0 -521
  202. package/skills/cm-booking-calendar/references/industry-patterns.md +0 -527
  203. package/skills/cm-booking-calendar/templates/booking-form.css +0 -626
  204. package/skills/cm-booking-calendar/templates/booking-form.html +0 -477
  205. package/skills/cm-booking-calendar/templates/calendar-engine.js +0 -419
  206. package/skills/cm-booking-calendar/templates/calendar-export.js +0 -395
  207. package/skills/cm-booking-calendar/templates/reminder-config.js +0 -629
  208. package/skills/cm-content-factory/.content-factory-state.json +0 -132
  209. package/skills/cm-content-factory/.git 2/logs/refs/heads/main +0 -1
  210. package/skills/cm-content-factory/.git 2/logs/refs/remotes/origin/main +0 -1
  211. package/skills/cm-content-factory/.git 2/objects/02/fb0956734b5f8ba3f918b7defd04a89cfe0076 +0 -0
  212. package/skills/cm-content-factory/.git 2/objects/08/1e129d75dc6feac6c02037272e6bd1a04e3324 +0 -0
  213. package/skills/cm-content-factory/.git 2/objects/0c/5393416f3c5e01c9a655a802bff0dd52f76f0a +0 -0
  214. package/skills/cm-content-factory/.git 2/objects/10/0b9be46978a946a77188f68be725098a122001 +0 -0
  215. package/skills/cm-content-factory/.git 2/objects/10/cf041167fc9843610eb3d90259ef3396315fdc +0 -0
  216. package/skills/cm-content-factory/.git 2/objects/12/5e19538dd6e1338ffe74f6c4c165b00435bf48 +0 -0
  217. package/skills/cm-content-factory/.git 2/objects/16/a9b9d0088d5c1347628b45a2620b479d8ad57c +0 -0
  218. package/skills/cm-content-factory/.git 2/objects/17/8c2a9ef93c33ae4eec9d58e82321f9229843a1 +0 -0
  219. package/skills/cm-content-factory/.git 2/objects/25/397ae41d09104d763bdcac2695209d85cdea89 +0 -0
  220. package/skills/cm-content-factory/.git 2/objects/2f/a836b7947f2d458e1f639788bf4bb0983a3305 +0 -0
  221. package/skills/cm-content-factory/.git 2/objects/3a/baaaf0a1c0909c0828335791557125fba911e0 +0 -0
  222. package/skills/cm-content-factory/.git 2/objects/42/2924221b81f5ce3c4e4daac9a64a24f9b01f9a +0 -0
  223. package/skills/cm-content-factory/.git 2/objects/42/ec0ce707447dc11446a34c9995fb8533801731 +0 -0
  224. package/skills/cm-content-factory/.git 2/objects/46/e43ce92866d56ce74b1d750db307cfe6154a15 +0 -0
  225. package/skills/cm-content-factory/.git 2/objects/48/5e41b633c63f55b8277bcc59f44f67681f671a +0 -0
  226. package/skills/cm-content-factory/.git 2/objects/49/49c596a3a89fa240642acd95dd3258e261eb09 +0 -0
  227. package/skills/cm-content-factory/.git 2/objects/50/9d42d8412ef8eaf7f7e138476bac2e4d10ce60 +0 -0
  228. package/skills/cm-content-factory/.git 2/objects/55/0c8c389d981b463ef849aeb792d8be3ccb6ec8 +0 -0
  229. package/skills/cm-content-factory/.git 2/objects/5d/82d3b18410cdda3ace3677436f0cb599dbe2d2 +0 -0
  230. package/skills/cm-content-factory/.git 2/objects/60/0617c58e871a38b33bf29e282d132bb3c381ad +0 -0
  231. package/skills/cm-content-factory/.git 2/objects/6a/8369a99c687b7245c92ffaf0e0f0dab9014504 +0 -0
  232. package/skills/cm-content-factory/.git 2/objects/79/bea435d40ab531c1aaf6be0432c6a5b7aaed21 +0 -0
  233. package/skills/cm-content-factory/.git 2/objects/7e/5ebd79251c2f14e4aceb86c74b6b6daae6b500 +0 -0
  234. package/skills/cm-content-factory/.git 2/objects/81/98a822a60178d6d5023ddb3e222cddf048742e +0 -0
  235. package/skills/cm-content-factory/.git 2/objects/86/0a0e1943dfe53411d2e499a1f16f46a96ef758 +0 -0
  236. package/skills/cm-content-factory/.git 2/objects/86/971fb55fdc081fdbae52376f0f13e57a4e9b04 +0 -0
  237. package/skills/cm-content-factory/.git 2/objects/88/b89dd609a0a03f8d4fe8bfde20d5b8fc1d326d +0 -0
  238. package/skills/cm-content-factory/.git 2/objects/90/8737edb6b7809e32cc01590b4e08ba42a9d40d +0 -0
  239. package/skills/cm-content-factory/.git 2/objects/93/d5a8a9a7d4fb7f11491cb596a6880528725118 +0 -0
  240. package/skills/cm-content-factory/.git 2/objects/98/46a2ab81d0c3b3eb00ef88fc56989aa7e9f316 +0 -0
  241. package/skills/cm-content-factory/.git 2/objects/9b/d8dd1e49cf274eaf9c555f3ab39dce7af5715e +0 -0
  242. package/skills/cm-content-factory/.git 2/objects/a1/13329fb0cec96ae78b222d33a24c3b5bc7fa1f +0 -0
  243. package/skills/cm-content-factory/.git 2/objects/a9/e6effe626e8a3aea3a8fc3364b492191c6e7d0 +0 -0
  244. package/skills/cm-content-factory/.git 2/objects/ad/6de7e48d9782cca9353d1ff0aa1aab7fe1df85 +0 -0
  245. package/skills/cm-content-factory/.git 2/objects/af/54ae316f771ff692e299ffcd8bf2f06b413b59 +0 -0
  246. package/skills/cm-content-factory/.git 2/objects/b0/4cb8b0b00dad633e731c1472161419e738d674 +0 -0
  247. package/skills/cm-content-factory/.git 2/objects/b3/094abb0b9ed46419b269e4a4e36a459690e3b0 +0 -0
  248. package/skills/cm-content-factory/.git 2/objects/b9/435c5d4baac2cfc5c83009ddd27b46b60db5f1 +0 -0
  249. package/skills/cm-content-factory/.git 2/objects/ba/5da17dbaec5ec2dcfdfd126aead518d1171d5c +0 -0
  250. package/skills/cm-content-factory/.git 2/objects/c0/bf58703aa258ba5dd63083bebaec8f223d844c +0 -0
  251. package/skills/cm-content-factory/.git 2/objects/c4/701a34edf1fc1bad58ccc57bd03f9426acb59a +0 -0
  252. package/skills/cm-content-factory/.git 2/objects/c7/5ccce9a4e5cc74d9b3174550cf6d993ca43638 +0 -0
  253. package/skills/cm-content-factory/.git 2/objects/c7/710d59b5a35b0f1f0a0399386643a0bd94c929 +0 -0
  254. package/skills/cm-content-factory/.git 2/objects/d1/fe58237112e953e5fec52da22cf38e08be3df9 +0 -5
  255. package/skills/cm-content-factory/.git 2/objects/d2/2bbe9fd2f74c95bc5583e803f5e435f1e2cd86 +0 -0
  256. package/skills/cm-content-factory/.git 2/objects/d7/e72852ea2bff74581dbf247d400120086229f4 +0 -0
  257. package/skills/cm-content-factory/.git 2/objects/d8/d4c3b5553e4fd72807e1d4b49ef07d9ef3ac35 +0 -0
  258. package/skills/cm-content-factory/.git 2/objects/dc/75050c2876f6a02ae2a53a3c886f395b622977 +0 -0
  259. package/skills/cm-content-factory/.git 2/objects/ee/e8546f95acec500187c08a28a8b9ee02db0dec +0 -0
  260. package/skills/cm-content-factory/.git 2/objects/ef/263c059208b416c2146434f10cb2b9fabcba16 +0 -0
  261. package/skills/cm-content-factory/.git 2/objects/f3/ae597e84d9a59b88acd21c99bde2eaf686d785 +0 -0
  262. package/skills/cm-content-factory/.git 2/objects/f3/f6f5673c821d3d8e76fa267a9e882e7a5387ea +0 -0
  263. package/skills/cm-content-factory/.git 2/objects/f9/6e6d0ad02624dd11d5848594d056caef7a5e8b +0 -0
  264. package/skills/cm-content-factory/.git 2/objects/ff/278988fc1edf0db3abcf18de795f4cc0b4f3e1 +0 -0
  265. package/skills/cm-content-factory/.git 2/refs/heads/main +0 -1
  266. package/skills/cm-content-factory/.git 2/refs/remotes/origin/main +0 -1
  267. package/skills/cm-content-factory/.pytest_cache 2/v/cache/nodeids +0 -76
  268. package/skills/cm-content-factory/.pytest_cache 2/v/cache/stepwise +0 -1
  269. package/skills/cm-content-factory/AGENTS.md +0 -61
  270. package/skills/cm-content-factory/CLAUDE.md +0 -63
  271. package/skills/cm-content-factory/CURSOR.md +0 -43
  272. package/skills/cm-content-factory/Content Factory.zip +0 -0
  273. package/skills/cm-content-factory/SKILL.md +0 -416
  274. package/skills/cm-content-factory/cf +0 -313
  275. package/skills/cm-content-factory/config.schema.json +0 -397
  276. package/skills/cm-content-factory/dashboard/app.js +0 -556
  277. package/skills/cm-content-factory/dashboard/index.html +0 -397
  278. package/skills/cm-content-factory/dashboard/style.css +0 -1211
  279. package/skills/cm-content-factory/examples/01-real-estate.config.json +0 -146
  280. package/skills/cm-content-factory/examples/02-personal-finance.config.json +0 -146
  281. package/skills/cm-content-factory/examples/03-health-wellness.config.json +0 -147
  282. package/skills/cm-content-factory/examples/04-saas-software.config.json +0 -147
  283. package/skills/cm-content-factory/examples/05-legal-services.config.json +0 -147
  284. package/skills/cm-content-factory/examples/06-insurance.config.json +0 -146
  285. package/skills/cm-content-factory/examples/07-ecommerce-dropship.config.json +0 -146
  286. package/skills/cm-content-factory/examples/08-online-education.config.json +0 -147
  287. package/skills/cm-content-factory/examples/09-crypto-defi.config.json +0 -147
  288. package/skills/cm-content-factory/examples/10-beauty-skincare.config.json +0 -147
  289. package/skills/cm-content-factory/examples/11-home-services.config.json +0 -146
  290. package/skills/cm-content-factory/examples/12-dental-clinic.config.json +0 -147
  291. package/skills/cm-content-factory/examples/13-pet-care.config.json +0 -147
  292. package/skills/cm-content-factory/examples/14-travel-hospitality.config.json +0 -147
  293. package/skills/cm-content-factory/examples/15-ai-automation.config.json +0 -147
  294. package/skills/cm-content-factory/examples/16-wedding-events.config.json +0 -147
  295. package/skills/cm-content-factory/examples/17-fitness-coaching.config.json +0 -148
  296. package/skills/cm-content-factory/examples/18-cybersecurity.config.json +0 -147
  297. package/skills/cm-content-factory/examples/19-food-restaurant.config.json +0 -148
  298. package/skills/cm-content-factory/examples/20-solar-energy.config.json +0 -147
  299. package/skills/cm-content-factory/examples/fitness-blog.config.json +0 -116
  300. package/skills/cm-content-factory/examples/tech-blog.config.json +0 -107
  301. package/skills/cm-content-factory/extensions/EXTENSION_GUIDE.md +0 -72
  302. package/skills/cm-content-factory/extensions/hooks.py +0 -126
  303. package/skills/cm-content-factory/extensions/openclaw_adapter.py +0 -132
  304. package/skills/cm-content-factory/landing/docs/content/changelog.md +0 -36
  305. package/skills/cm-content-factory/landing/docs/content/deployment.md +0 -46
  306. package/skills/cm-content-factory/landing/docs/content/execution-flow.md +0 -67
  307. package/skills/cm-content-factory/landing/docs/content/openspace.md +0 -27
  308. package/skills/cm-content-factory/landing/docs/content/openviking.md +0 -33
  309. package/skills/cm-content-factory/landing/docs/content/use-cases.md +0 -26
  310. package/skills/cm-content-factory/landing/docs/content/v5-intro.md +0 -28
  311. package/skills/cm-content-factory/landing/docs/index.html +0 -240
  312. package/skills/cm-content-factory/landing/index.html +0 -680
  313. package/skills/cm-content-factory/landing/script.js +0 -143
  314. package/skills/cm-content-factory/landing/style.css +0 -1216
  315. package/skills/cm-content-factory/landing/translations.js +0 -508
  316. package/skills/cm-content-factory/logs/events.jsonl +0 -11
  317. package/skills/cm-content-factory/profiles/_template.profile.json +0 -231
  318. package/skills/cm-content-factory/profiles/finance.profile.json +0 -278
  319. package/skills/cm-content-factory/profiles/legal.profile.json +0 -263
  320. package/skills/cm-content-factory/profiles/medical-research.profile.json +0 -321
  321. package/skills/cm-content-factory/profiles/technology.profile.json +0 -275
  322. package/skills/cm-content-factory/scripts/agent_dispatcher.py +0 -266
  323. package/skills/cm-content-factory/scripts/audit.py +0 -106
  324. package/skills/cm-content-factory/scripts/dashboard_server.py +0 -225
  325. package/skills/cm-content-factory/scripts/deploy.py +0 -146
  326. package/skills/cm-content-factory/scripts/extract.py +0 -132
  327. package/skills/cm-content-factory/scripts/landing_generator.py +0 -459
  328. package/skills/cm-content-factory/scripts/memory.py +0 -521
  329. package/skills/cm-content-factory/scripts/monetize.py +0 -239
  330. package/skills/cm-content-factory/scripts/pipeline.py +0 -357
  331. package/skills/cm-content-factory/scripts/plan.py +0 -163
  332. package/skills/cm-content-factory/scripts/publish.py +0 -145
  333. package/skills/cm-content-factory/scripts/research.py +0 -337
  334. package/skills/cm-content-factory/scripts/scaffold.py +0 -464
  335. package/skills/cm-content-factory/scripts/scoreboard.py +0 -336
  336. package/skills/cm-content-factory/scripts/seo.py +0 -90
  337. package/skills/cm-content-factory/scripts/state_manager.py +0 -320
  338. package/skills/cm-content-factory/scripts/token_manager.py +0 -268
  339. package/skills/cm-content-factory/scripts/validate.py +0 -221
  340. package/skills/cm-content-factory/scripts/wizard.py +0 -329
  341. package/skills/cm-content-factory/scripts/write.py +0 -93
  342. package/skills/cm-content-factory/sites/docs-site/src/assets/houston.webp +0 -0
  343. package/skills/cm-content-factory/sites/docs-site/src/content/docs/architecture.md +0 -90
  344. package/skills/cm-content-factory/sites/docs-site/src/content/docs/data-flow.md +0 -54
  345. package/skills/cm-content-factory/sites/docs-site/src/content/docs/deployment.md +0 -38
  346. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/index.md +0 -65
  347. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/lc-content-lifecycle.md +0 -48
  348. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/seq-write-mode.md +0 -39
  349. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/uj-first-batch.md +0 -42
  350. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-content-pipeline.md +0 -51
  351. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-learning-cycle.md +0 -52
  352. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/configuration.md +0 -86
  353. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/installation.md +0 -80
  354. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/intro.md +0 -58
  355. package/skills/cm-content-factory/sites/docs-site/src/content/docs/index.md +0 -102
  356. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/index.md +0 -45
  357. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/optimize-seo.md +0 -29
  358. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/scale-content-production.md +0 -55
  359. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/standardize-quality.md +0 -29
  360. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-cmo-huong.md +0 -41
  361. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-content-lead-khoa.md +0 -40
  362. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/index.md +0 -56
  363. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-content-manager-lan.md +0 -46
  364. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-seo-minh.md +0 -45
  365. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-writer-tu.md +0 -45
  366. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/content-pipeline.md +0 -108
  367. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/index.md +0 -22
  368. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/memory-system.md +0 -52
  369. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/seo-optimization.md +0 -58
  370. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/troubleshooting-guide.md +0 -92
  371. package/skills/cm-content-factory/sites/docs-site/src/styles/custom.css +0 -575
  372. package/skills/cm-content-factory/tests/conftest.py +0 -66
  373. package/skills/cm-content-factory/tests/test_agent_dispatcher.py +0 -125
  374. package/skills/cm-content-factory/tests/test_memory.py +0 -128
  375. package/skills/cm-content-factory/tests/test_pipeline.py +0 -107
  376. package/skills/cm-content-factory/tests/test_research.py +0 -56
  377. package/skills/cm-content-factory/tests/test_state_manager.py +0 -131
  378. package/skills/cm-content-factory/tests/test_token_manager.py +0 -110
  379. package/skills/cm-content-factory/tests/test_wizard.py +0 -121
  380. package/skills/cm-cro-methodology/SKILL.md +0 -290
  381. package/skills/cm-cro-methodology/references/COPYWRITING.md +0 -178
  382. package/skills/cm-cro-methodology/references/OBJECTIONS.md +0 -135
  383. package/skills/cm-cro-methodology/references/PERSUASION.md +0 -158
  384. package/skills/cm-cro-methodology/references/RESEARCH.md +0 -220
  385. package/skills/cm-cro-methodology/references/funnel-analysis.md +0 -365
  386. package/skills/cm-cro-methodology/references/testing-methodology.md +0 -330
  387. package/skills/cm-google-form/SKILL.md +0 -266
  388. package/skills/cm-google-form/templates/apps-script.js +0 -55
  389. package/skills/cm-google-form/templates/form-markup.html +0 -110
  390. package/skills/cm-google-form/templates/form-submit.js +0 -201
  391. package/skills/cm-google-form/templates/toast.css +0 -152
  392. package/skills/cm-growth-hacking/SKILL.md +0 -282
  393. package/skills/cm-growth-hacking/bottom-sheet-engine.md +0 -261
  394. package/skills/cm-growth-hacking/calendar-integration.md +0 -264
  395. package/skills/cm-growth-hacking/references/engagement-patterns.md +0 -346
  396. package/skills/cm-growth-hacking/templates/bottom-sheet.css +0 -528
  397. package/skills/cm-growth-hacking/templates/bottom-sheet.js +0 -269
  398. package/skills/cm-growth-hacking/templates/calendar-cta.js +0 -213
  399. package/skills/cm-growth-hacking/templates/tracking-events.js +0 -211
  400. package/skills/cm-growth-hacking/templates/trigger-manager.js +0 -254
  401. package/skills/cm-growth-hacking/tracking-events.md +0 -246
  402. package/skills/cm-growth-hacking/trigger-system.md +0 -342
  403. package/skills/cm-jtbd/SKILL.md +0 -98
  404. package/skills/cm-notebooklm/SKILL.md +0 -156
  405. package/skills/cm-notebooklm/references/command_reference.md +0 -94
  406. package/skills/cm-notebooklm/references/workflows.md +0 -60
  407. package/skills/cm-notebooklm/resources/knowledge_sources.md +0 -106
  408. package/skills/cm-notebooklm/scripts/brain-sync.sh +0 -453
  409. package/skills/cm-notebooklm/scripts/graduate_wisdom.py +0 -101
  410. package/skills/cm-readit/SKILL.md +0 -289
  411. package/skills/cm-readit/audio-player.md +0 -206
  412. package/skills/cm-readit/examples/blog-reader.js +0 -352
  413. package/skills/cm-readit/examples/voice-cro.js +0 -390
  414. package/skills/cm-readit/tts-engine.md +0 -262
  415. package/skills/cm-readit/ui-patterns.md +0 -362
  416. package/skills/cm-readit/voice-cro.md +0 -223
@@ -1,266 +0,0 @@
1
- ---
2
- name: cm-google-form
3
- description: Google App Script form-to-sheet integration with auto-retry, toast notifications, and Zalo/contact fallback. Reusable across any static website.
4
- allowed-tools: Read, Write, Edit, Glob, Grep, Browser
5
- version: 1.0
6
- priority: HIGH
7
- ---
8
-
9
- # Google Forms → Sheet Integration Skill
10
-
11
- > **Connect HTML forms → Google Sheets via Google Apps Script.**
12
- > Auto-retry, toast UI, contact fallback on errors. Zero dependencies, works on any static site.
13
-
14
- ---
15
-
16
- ## 🎯 When to Use
17
-
18
- | Trigger | Action |
19
- |---------|--------|
20
- | User says "create form", "connect Google Sheet" | Activate this skill |
21
- | User says "form broken", "submit not working" | Debug using Phase 4-5 |
22
- | User says "add new form to page" | Start from Phase 2 |
23
- | User says "form for another website" | Start from Phase 1 |
24
-
25
- ---
26
-
27
- ## 📋 5-Phase Workflow
28
-
29
- ```
30
- Phase 1: DISCOVER → Scan forms, identify fields, determine sheet structure
31
- Phase 2: PLAN → Design sheet columns, map form fields, create deployment plan
32
- Phase 3: BUILD → Generate Apps Script + Frontend JS + Toast CSS
33
- Phase 4: INTEGRATE → Wire forms to JS, add CSS, deploy Apps Script
34
- Phase 5: VERIFY → Test submit, test retry, test error fallback
35
- ```
36
-
37
- > 🔴 **Rule:** NEVER skip Phase 1. Always read existing forms first.
38
-
39
- ---
40
-
41
- ## Phase 1: DISCOVER (Scan & Analyze)
42
-
43
- **Goal:** Understand what forms exist and what fields they have.
44
-
45
- ### Actions:
46
-
47
- 1. **Search for forms** in the project:
48
- ```
49
- grep -r "data-form-type\|onsubmit\|<form" --include="*.html" .
50
- ```
51
-
52
- 2. **For each form found, extract:**
53
-
54
- | Info | How to Find |
55
- |------|-------------|
56
- | Form type | `data-form-type` attribute |
57
- | Fields | `<input name="...">`, `<select name="...">` |
58
- | Submit handler | `onsubmit` attribute |
59
- | Page URL | File path |
60
-
61
- 3. **Ask user** (Socratic Gate):
62
- - How many separate Google Sheets? (1 shared sheet or separate?)
63
- - What columns does each sheet need?
64
- - Is there a fallback contact channel? (WhatsApp, Messenger, Hotline?)
65
- - Fallback contact URL (e.g., `https://wa.me/15551234567`)
66
-
67
- ### Output: Form Inventory Table
68
-
69
- ```markdown
70
- | # | Form Type | Pages | Fields | Target Sheet |
71
- |---|-----------|-------|--------|-------------|
72
- | 1 | massage | 7 | name, phone, branch, problem, time, package | Sheet Massage |
73
- | 2 | course | 1 | name, phone, goal | Course Sheet |
74
- ```
75
-
76
- ---
77
-
78
- ## Phase 2: PLAN (Design & Map)
79
-
80
- **Goal:** Map form fields → Sheet columns → Apps Script params.
81
-
82
- ### Sheet Column Design
83
-
84
- For each sheet, define columns in order:
85
-
86
- | Column | Source | Always Include |
87
- |--------|--------|---------------|
88
- | Timestamp | `new Date()` — auto | ✅ Yes |
89
- | (form fields) | `e.parameter.xxx` | From inventory |
90
- | Page Source | `e.parameter.url` | ✅ Yes |
91
-
92
- ### Naming Convention
93
-
94
- | Element | Convention |
95
- |---------|-----------|
96
- | Sheet tab name | `Data` |
97
- | Form attribute | `data-form-type="<type>"` |
98
- | Hidden URL field | `<input type="hidden" name="url" value="">` |
99
- | JS global function | `window.submitToGoogleSheet` |
100
-
101
- ### Deliverables Checklist
102
-
103
- - [ ] Apps Script code per sheet
104
- - [ ] Frontend JS with retry + toast
105
- - [ ] Toast CSS component
106
- - [ ] HTML form markup template
107
- - [ ] Deploy instructions
108
- - [ ] Verification test plan
109
-
110
- ---
111
-
112
- ## Phase 3: BUILD (Generate Code)
113
-
114
- ### 3A. Google Apps Script Template
115
-
116
- > See `templates/apps-script.js` for the full template.
117
-
118
- **Key rules:**
119
- - Always use `doPost(e)` — NOT `doGet`
120
- - Always wrap in `try/catch`
121
- - Always return JSON with `{status: "success"}` or `{status: "error", message: "..."}`
122
- - Column order MUST match `sheet.appendRow([...])` order
123
- - Tab name MUST match `SHEET_NAME` constant
124
-
125
- ### 3B. Frontend JavaScript
126
-
127
- > See `templates/form-submit.js` for the full template.
128
-
129
- **Key features:**
130
-
131
- | Feature | Detail |
132
- |---------|--------|
133
- | Auto-retry | 3 attempts, exponential backoff (1s → 2s → 4s) |
134
- | Toast UI | Success (green), Error (red), Retrying (amber) |
135
- | Phone validation | Vietnamese format: `/^0\d{8,10}$/` |
136
- | Button states | "Submitting..." → "Retrying (X/3)..." → reset |
137
- | CORS handling | Handles opaque responses from Apps Script |
138
- | Fallback | Zalo button in error toast |
139
- | Auto-dismiss | Success: 6s, Error: 15s, Retrying: 10s |
140
-
141
- ### 3C. Toast CSS
142
-
143
- > See `templates/toast.css` for the full template.
144
-
145
- **3 variants:** `--success`, `--error`, `--retrying`
146
-
147
- ### 3D. HTML Form Markup
148
-
149
- > See `templates/form-markup.html` for examples.
150
-
151
- **Required attributes:**
152
- ```html
153
- <form data-form-type="TYPE" onsubmit="window.submitToGoogleSheet(event)">
154
- <input type="hidden" name="url" value="">
155
- <!-- form fields with name="..." -->
156
- <button type="submit">Submit Text</button>
157
- </form>
158
- ```
159
-
160
- ---
161
-
162
- ## Phase 4: INTEGRATE (Wire Everything)
163
-
164
- ### Step-by-step:
165
-
166
- 1. **Add Toast CSS** → Append to main CSS file (e.g., `design-system.css`)
167
- 2. **Add Form JS** → Add to shared JS file or create `js/form-handler.js`
168
- 3. **Update HTML forms:**
169
- - Add `data-form-type="..."` attribute
170
- - Add `onsubmit="window.submitToGoogleSheet(event)"`
171
- - Add `<input type="hidden" name="url" value="">`
172
- - Ensure all inputs have `name="..."` matching Apps Script params
173
- 4. **Configure URLs:**
174
- - Replace placeholder URLs in JS with deployed Apps Script URLs
175
- 5. **Configure fallback contact:**
176
- - Replace Zalo URL in JS toast with project's contact URL
177
-
178
- ### Customization Points
179
-
180
- | Setting | Location | Default |
181
- |---------|----------|---------|
182
- | Apps Script URLs | JS `URLS` object | placeholder |
183
- | Fallback contact | Toast Zalo link | `https://zalo.me/...` |
184
- | Max retries | `fetchWithRetry` arg | 3 |
185
- | Phone regex | Validation block | `/^0\d{8,10}$/` |
186
- | Toast auto-dismiss | `showFormToast` timeouts | 6s/15s/10s |
187
- | Success message | `.then()` block | Customizable |
188
- | Error message | `.catch()` block | Customizable |
189
-
190
- ---
191
-
192
- ## Phase 5: VERIFY (Test & Report)
193
-
194
- ### Test Checklist
195
-
196
- | # | Test Case | Expected | Status |
197
- |---|-----------|----------|--------|
198
- | 1 | Submit valid form | Toast success (green) + Zalo opens | |
199
- | 2 | Submit invalid phone | Toast error "Invalid phone number" | |
200
- | 3 | Network offline | 3 retries → Toast error with Zalo button | |
201
- | 4 | Check Google Sheet | New row appears with correct data | |
202
- | 5 | Button states | Disabled during submit, resets after | |
203
- | 6 | Toast close button | Toast disappears on click | |
204
- | 7 | Mobile responsive | Toast visible above sticky CTA | |
205
- | 8 | Multiple forms same page | Each form submits independently | |
206
-
207
- ### How to Test Retry
208
-
209
- 1. Open DevTools → Network tab
210
- 2. Block domain `script.google.com`
211
- 3. Submit form → Should see 3 retry attempts
212
- 4. Unblock → Submit again → Should succeed
213
-
214
- ### Report Template
215
-
216
- ```markdown
217
- ## Form Integration Test Report
218
-
219
- **Date:** YYYY-MM-DD
220
- **Pages tested:** X/Y
221
-
222
- | Page | Form Type | Submit | Retry | Fallback | Sheet |
223
- |------|-----------|--------|-------|----------|-------|
224
- | index.html | massage | ✅ | ✅ | ✅ | ✅ |
225
- | khoa-hoc.html | course | ✅ | ✅ | ✅ | ✅ |
226
-
227
- **Issues found:** None / [list issues]
228
- **Resolution:** [fixes applied]
229
- ```
230
-
231
- ---
232
-
233
- ## ❌ Anti-Patterns
234
-
235
- | ❌ Don't | ✅ Do |
236
- |----------|------|
237
- | Use `alert()` for feedback | Use toast notifications |
238
- | No retry on failure | Auto-retry 3x with backoff |
239
- | Silently fail | Show error + contact fallback |
240
- | Hardcode form URLs | Use config object (`URLS`) |
241
- | Skip phone validation | Validate before submit |
242
- | Forget `name` attribute | Every input MUST have `name` |
243
- | Use `doGet` for form submit | Use `doPost` only |
244
- | Multiple submit handlers | One shared `submitToGoogleSheet` |
245
-
246
- ---
247
-
248
- ## 📑 Templates
249
-
250
- | File | Purpose |
251
- |------|---------|
252
- | `templates/apps-script.js` | Google Apps Script doPost handler |
253
- | `templates/form-submit.js` | Frontend JS with retry + toast |
254
- | `templates/toast.css` | Toast notification CSS component |
255
- | `templates/form-markup.html` | HTML form examples |
256
-
257
- ---
258
-
259
- ## 🔗 Related Skills
260
-
261
- | Need | Skill |
262
- |------|-------|
263
- | Form UI/UX design | `@[skills/cm-ux-master]` |
264
- | SEO for forms | `@[skills/cm-dockit]` |
265
- | Form security | `@[skills/vulnerability-scanner]` |
266
- | Deployment | `@[skills/deployment-procedures]` |
@@ -1,55 +0,0 @@
1
- /**
2
- * Google Apps Script — Form to Sheet Handler
3
- *
4
- * SETUP:
5
- * 1. Create Google Sheet with headers matching appendRow columns
6
- * 2. Extensions > Apps Script > paste this code
7
- * 3. Deploy > New deployment > Web app
8
- * - Execute as: Me
9
- * - Who has access: Anyone
10
- * 4. Copy the deployment URL → use in frontend URLS config
11
- *
12
- * CUSTOMIZATION:
13
- * - Change SHEET_NAME if tab is not "Data"
14
- * - Modify appendRow columns to match your form fields
15
- * - Add more e.parameter.xxx for additional fields
16
- */
17
-
18
- const SHEET_NAME = 'Data';
19
-
20
- function doPost(e) {
21
- try {
22
- const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
23
- if (!e || !e.parameter) {
24
- return ContentService.createTextOutput(JSON.stringify({ status: 'error', message: 'No data received' }))
25
- .setMimeType(ContentService.MimeType.JSON);
26
- }
27
-
28
- const p = e.parameter;
29
-
30
- // ═══════════════════════════════════════
31
- // CUSTOMIZE: Change columns below to match your form
32
- // Column order MUST match Sheet header row
33
- // ═══════════════════════════════════════
34
- sheet.appendRow([
35
- new Date(), // A: Thời gian (auto)
36
- p.name || '', // B: Họ tên
37
- p.phone || '', // C: SĐT
38
- // --- Add your custom fields below ---
39
- // p.email || '', // D: Email
40
- // p.branch || '', // E: Chi nhánh
41
- // p.problem || '', // F: Vấn đề
42
- // p.time || '', // G: Khung giờ
43
- // p.package || '', // H: Gói dịch vụ
44
- // p.goal || '', // I: Mục tiêu
45
- // --- End custom fields ---
46
- p.url || '' // Last: Nguồn trang (auto)
47
- ]);
48
-
49
- return ContentService.createTextOutput(JSON.stringify({ status: 'success' }))
50
- .setMimeType(ContentService.MimeType.JSON);
51
- } catch (err) {
52
- return ContentService.createTextOutput(JSON.stringify({ status: 'error', message: err.toString() }))
53
- .setMimeType(ContentService.MimeType.JSON);
54
- }
55
- }
@@ -1,110 +0,0 @@
1
- <!--
2
- Form Markup Templates — Google Apps Script Integration
3
-
4
- RULES:
5
- 1. Every form MUST have data-form-type="TYPE"
6
- 2. Every form MUST have onsubmit="window.submitToGoogleSheet(event)"
7
- 3. Every form MUST include <input type="hidden" name="url" value="">
8
- 4. Every input/select MUST have name="..." matching Apps Script params
9
- 5. One submit button with type="submit"
10
- -->
11
-
12
- <!-- ═══════════════════════════════════════ -->
13
- <!-- EXAMPLE 1: Service Booking (Massage) -->
14
- <!-- ═══════════════════════════════════════ -->
15
- <form data-form-type="massage" onsubmit="window.submitToGoogleSheet(event)">
16
- <input type="hidden" name="url" value="">
17
-
18
- <div class="form-group">
19
- <label class="form-label">Họ và tên</label>
20
- <input type="text" class="form-input" name="name" placeholder="Nhập họ tên" required>
21
- </div>
22
-
23
- <div class="form-group">
24
- <label class="form-label">Số điện thoại</label>
25
- <input type="tel" class="form-input" name="phone" placeholder="0xxx xxx xxx" required>
26
- </div>
27
-
28
- <div class="form-group">
29
- <label class="form-label">Chi nhánh</label>
30
- <select class="form-input" name="branch">
31
- <option>Chi nhánh 1</option>
32
- <option>Chi nhánh 2</option>
33
- </select>
34
- </div>
35
-
36
- <div class="form-group">
37
- <label class="form-label">Vấn đề quan tâm</label>
38
- <select class="form-input" name="problem">
39
- <option>Đau cổ vai gáy</option>
40
- <option>Mất ngủ</option>
41
- <option>Đau lưng</option>
42
- <option>Khác</option>
43
- </select>
44
- </div>
45
-
46
- <button type="submit" class="btn btn-primary btn-lg" style="width:100%;">Đặt Lịch Ngay</button>
47
-
48
- <p style="text-align:center;margin-top:12px;font-size:14px;color:#666;">
49
- Hoặc gọi: <a href="tel:0559669663" style="color:#C9A84C;font-weight:600;">0559.669.663</a>
50
- </p>
51
- </form>
52
-
53
-
54
- <!-- ═══════════════════════════════════════ -->
55
- <!-- EXAMPLE 2: Course Registration -->
56
- <!-- ═══════════════════════════════════════ -->
57
- <form data-form-type="course" onsubmit="window.submitToGoogleSheet(event)">
58
- <input type="hidden" name="url" value="">
59
-
60
- <div class="form-group">
61
- <label class="form-label">Họ và tên</label>
62
- <input type="text" class="form-input" name="name" placeholder="Nhập họ tên" required>
63
- </div>
64
-
65
- <div class="form-group">
66
- <label class="form-label">Số điện thoại</label>
67
- <input type="tel" class="form-input" name="phone" placeholder="0xxx xxx xxx" required>
68
- </div>
69
-
70
- <div class="form-group">
71
- <label class="form-label">Mục tiêu học</label>
72
- <select class="form-input" name="goal">
73
- <option>Chuyển nghề</option>
74
- <option>Nâng cấp kỹ năng</option>
75
- <option>Chăm sóc gia đình</option>
76
- </select>
77
- </div>
78
-
79
- <button type="submit" class="btn btn-primary btn-lg" style="width:100%;">Đăng Ký Tư Vấn</button>
80
- </form>
81
-
82
-
83
- <!-- ═══════════════════════════════════════ -->
84
- <!-- EXAMPLE 3: Simple Contact/Lead Form -->
85
- <!-- ═══════════════════════════════════════ -->
86
- <form data-form-type="contact" onsubmit="window.submitToGoogleSheet(event)">
87
- <input type="hidden" name="url" value="">
88
-
89
- <div class="form-group">
90
- <label class="form-label">Họ và tên</label>
91
- <input type="text" class="form-input" name="name" placeholder="Nhập họ tên" required>
92
- </div>
93
-
94
- <div class="form-group">
95
- <label class="form-label">Số điện thoại</label>
96
- <input type="tel" class="form-input" name="phone" placeholder="0xxx xxx xxx" required>
97
- </div>
98
-
99
- <div class="form-group">
100
- <label class="form-label">Email (tùy chọn)</label>
101
- <input type="email" class="form-input" name="email" placeholder="email@example.com">
102
- </div>
103
-
104
- <div class="form-group">
105
- <label class="form-label">Nội dung</label>
106
- <textarea class="form-input" name="message" rows="3" placeholder="Bạn cần hỗ trợ gì?"></textarea>
107
- </div>
108
-
109
- <button type="submit" class="btn btn-primary btn-lg" style="width:100%;">Gửi Yêu Cầu</button>
110
- </form>
@@ -1,201 +0,0 @@
1
- /**
2
- * Form Submission Handler — Auto Retry + Toast UI + Fallback
3
- *
4
- * Features:
5
- * - Auto retry 3x with exponential backoff (1s → 2s → 4s)
6
- * - Toast notifications (success/error/retrying) — no alert()
7
- * - Phone validation (Vietnamese format)
8
- * - Zalo/contact fallback on total failure
9
- * - CORS-safe: handles opaque responses from Google Apps Script
10
- *
11
- * USAGE:
12
- * 1. Include this script in your page (or append to shared.js)
13
- * 2. Add toast.css to your stylesheet
14
- * 3. Configure URLS object with your Apps Script deployment URLs
15
- * 4. Configure FALLBACK_CONTACT with your Zalo/contact URL
16
- * 5. Add forms with: data-form-type="xxx" onsubmit="window.submitToGoogleSheet(event)"
17
- */
18
-
19
- // ═══════════════════════════════════════
20
- // CONFIGURATION — Change these values
21
- // ═══════════════════════════════════════
22
- const FORM_CONFIG = {
23
- // Apps Script URLs per form type
24
- URLS: {
25
- // Add your deployed Apps Script URLs here
26
- // massage: 'https://script.google.com/macros/s/YOUR_ID/exec',
27
- // course: 'https://script.google.com/macros/s/YOUR_ID/exec',
28
- },
29
- // Fallback contact when form fails completely
30
- FALLBACK_CONTACT: {
31
- url: 'https://zalo.me/0559669663', // Change to your Zalo/Messenger/etc
32
- label: '💬 Nhắn tin Zalo ngay', // Button text
33
- },
34
- // Retry settings
35
- MAX_RETRIES: 3,
36
- // Phone validation regex (Vietnamese)
37
- PHONE_REGEX: /^0\d{8,10}$/,
38
- // Messages (Vietnamese — customize for your language)
39
- MESSAGES: {
40
- sending: 'Đang gửi...',
41
- retrying: (attempt, max) => `Đang thử lại (${attempt}/${max})...`,
42
- phoneInvalid: {
43
- title: 'Số điện thoại không hợp lệ',
44
- msg: 'Vui lòng nhập số điện thoại bắt đầu bằng 0, từ 9-11 chữ số.',
45
- },
46
- success: {
47
- title: 'Đăng ký thành công! 🎉',
48
- msg: 'Chúng tôi sẽ liên hệ bạn trong 30 phút. Nhắn Zalo để được tư vấn nhanh hơn!',
49
- },
50
- retryNotice: {
51
- title: 'Đang thử lại...',
52
- msg: (attempt, max) => `Lần ${attempt}/${max} — Vui lòng chờ trong giây lát.`,
53
- },
54
- error: {
55
- title: 'Gửi không thành công',
56
- msg: 'Hệ thống đang bận. Vui lòng nhắn tin Zalo để được hỗ trợ ngay — chúng tôi sẽ phản hồi trong 5 phút!',
57
- },
58
- },
59
- };
60
-
61
- // ═══════════════════════════════════════
62
- // TOAST NOTIFICATION SYSTEM
63
- // ═══════════════════════════════════════
64
-
65
- function getToastContainer() {
66
- let c = document.querySelector('.form-toast-container');
67
- if (!c) {
68
- c = document.createElement('div');
69
- c.className = 'form-toast-container';
70
- document.body.appendChild(c);
71
- }
72
- return c;
73
- }
74
-
75
- function showFormToast(type, title, msg, options = {}) {
76
- const container = getToastContainer();
77
- container.querySelectorAll('.form-toast').forEach(t => hideFormToast(t));
78
-
79
- const icons = { success: '✅', error: '❌', retrying: '⏳' };
80
- const toast = document.createElement('div');
81
- toast.className = `form-toast form-toast--${type}`;
82
-
83
- const fallback = FORM_CONFIG.FALLBACK_CONTACT;
84
- toast.innerHTML = `
85
- <span class="form-toast-icon">${icons[type] || '📋'}</span>
86
- <div class="form-toast-body">
87
- <div class="form-toast-title">${title}</div>
88
- <div class="form-toast-msg">${msg}</div>
89
- ${options.showFallback ? `<a href="${fallback.url}" target="_blank" class="form-toast-zalo">${fallback.label}</a>` : ''}
90
- </div>
91
- <button class="form-toast-close" aria-label="Close">✕</button>
92
- `;
93
-
94
- toast.querySelector('.form-toast-close').addEventListener('click', () => hideFormToast(toast));
95
- container.appendChild(toast);
96
-
97
- const dismissMs = { success: 6000, error: 15000, retrying: 10000 };
98
- setTimeout(() => hideFormToast(toast), dismissMs[type] || 8000);
99
-
100
- return toast;
101
- }
102
-
103
- function hideFormToast(toast) {
104
- if (!toast || !toast.parentNode) return;
105
- toast.classList.add('hiding');
106
- setTimeout(() => toast.remove(), 300);
107
- }
108
-
109
- // ═══════════════════════════════════════
110
- // FETCH WITH RETRY (Exponential Backoff)
111
- // ═══════════════════════════════════════
112
-
113
- async function fetchWithRetry(url, options, maxRetries, onRetry) {
114
- let lastError;
115
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
116
- try {
117
- const res = await fetch(url, options);
118
- if (res.type === 'opaque' || res.ok) return res;
119
- try {
120
- const data = await res.json();
121
- if (data.status === 'success') return res;
122
- throw new Error(data.message || 'Server error');
123
- } catch {
124
- if (res.type === 'opaque') return res;
125
- throw new Error(`HTTP ${res.status}`);
126
- }
127
- } catch (err) {
128
- lastError = err;
129
- if (attempt < maxRetries) {
130
- const delay = Math.pow(2, attempt - 1) * 1000;
131
- if (onRetry) onRetry(attempt, maxRetries);
132
- await new Promise(r => setTimeout(r, delay));
133
- }
134
- }
135
- }
136
- throw lastError;
137
- }
138
-
139
- // ═══════════════════════════════════════
140
- // FORM SUBMISSION HANDLER
141
- // ═══════════════════════════════════════
142
-
143
- window.submitToGoogleSheet = function (event) {
144
- event.preventDefault();
145
- const form = event.target;
146
- const btn = form.querySelector('button[type="submit"]');
147
- if (!btn || btn.disabled) return;
148
- const originalText = btn.innerText;
149
- const cfg = FORM_CONFIG;
150
- const msgs = cfg.MESSAGES;
151
-
152
- // Phone validation
153
- const phoneInput = form.querySelector('input[name="phone"]');
154
- if (phoneInput) {
155
- const phone = phoneInput.value.replace(/\s+/g, '');
156
- if (!cfg.PHONE_REGEX.test(phone)) {
157
- showFormToast('error', msgs.phoneInvalid.title, msgs.phoneInvalid.msg);
158
- phoneInput.focus();
159
- return;
160
- }
161
- }
162
-
163
- // Auto-fill source URL
164
- const urlInput = form.querySelector('input[name="url"]');
165
- if (urlInput) urlInput.value = window.location.href;
166
-
167
- const formType = form.getAttribute('data-form-type') || Object.keys(cfg.URLS)[0];
168
- const scriptURL = cfg.URLS[formType] || Object.values(cfg.URLS)[0];
169
-
170
- if (!scriptURL) {
171
- showFormToast('error', 'Lỗi cấu hình', 'Chưa cấu hình URL cho form type: ' + formType);
172
- return;
173
- }
174
-
175
- btn.innerText = msgs.sending;
176
- btn.disabled = true;
177
-
178
- fetchWithRetry(
179
- scriptURL,
180
- { method: 'POST', body: new FormData(form) },
181
- cfg.MAX_RETRIES,
182
- (attempt, max) => {
183
- btn.innerText = msgs.retrying(attempt, max);
184
- showFormToast('retrying', msgs.retryNotice.title, msgs.retryNotice.msg(attempt, max));
185
- }
186
- )
187
- .then(() => {
188
- showFormToast('success', msgs.success.title, msgs.success.msg, { showFallback: true });
189
- form.reset();
190
- setTimeout(() => {
191
- window.open(cfg.FALLBACK_CONTACT.url, '_blank');
192
- }, 1500);
193
- })
194
- .catch(() => {
195
- showFormToast('error', msgs.error.title, msgs.error.msg, { showFallback: true });
196
- })
197
- .finally(() => {
198
- btn.innerText = originalText;
199
- btn.disabled = false;
200
- });
201
- };