opencode-skills-collection 3.1.0 → 3.1.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 (277) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +84 -1
  2. package/bundled-skills/android-ui-journey-testing/SKILL.md +191 -0
  3. package/bundled-skills/ask-matt/SKILL.md +92 -0
  4. package/bundled-skills/bugs-are-annoying/SKILL.md +137 -0
  5. package/bundled-skills/codebase-design/DEEPENING.md +37 -0
  6. package/bundled-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
  7. package/bundled-skills/codebase-design/SKILL.md +145 -0
  8. package/bundled-skills/competitor-analysis/LICENSE.txt +21 -0
  9. package/bundled-skills/competitor-analysis/SKILL.md +434 -0
  10. package/bundled-skills/competitor-analysis/references/battle-card-subagent.md +127 -0
  11. package/bundled-skills/competitor-analysis/references/battle-card.md +91 -0
  12. package/bundled-skills/competitor-analysis/references/example-research.md +130 -0
  13. package/bundled-skills/competitor-analysis/references/report-template.html +127 -0
  14. package/bundled-skills/competitor-analysis/references/research-patterns.md +217 -0
  15. package/bundled-skills/competitor-analysis/references/workflow.md +434 -0
  16. package/bundled-skills/competitor-analysis/scripts/capture_screenshots.mjs +142 -0
  17. package/bundled-skills/competitor-analysis/scripts/compile_report.mjs +929 -0
  18. package/bundled-skills/competitor-analysis/scripts/extract_vs_names.mjs +140 -0
  19. package/bundled-skills/competitor-analysis/scripts/gate_candidates.mjs +194 -0
  20. package/bundled-skills/competitor-analysis/scripts/list_urls.mjs +90 -0
  21. package/bundled-skills/competitor-analysis/scripts/md_utils.mjs +50 -0
  22. package/bundled-skills/competitor-analysis/scripts/merge_partials.mjs +291 -0
  23. package/bundled-skills/competitor-analysis/scripts/package.json +6 -0
  24. package/bundled-skills/design-it/3d-ui/SKILL.md +259 -0
  25. package/bundled-skills/design-it/SKILL.md +170 -0
  26. package/bundled-skills/design-it/ai-native-ui/SKILL.md +295 -0
  27. package/bundled-skills/design-it/aurora-ui/SKILL.md +307 -0
  28. package/bundled-skills/design-it/bento-ui/SKILL.md +314 -0
  29. package/bundled-skills/design-it/brutalism/SKILL.md +270 -0
  30. package/bundled-skills/design-it/brutalist-typography/SKILL.md +287 -0
  31. package/bundled-skills/design-it/card-based-design/SKILL.md +262 -0
  32. package/bundled-skills/design-it/claymorphism/SKILL.md +287 -0
  33. package/bundled-skills/design-it/color-blocking/SKILL.md +278 -0
  34. package/bundled-skills/design-it/command-center-ui/SKILL.md +345 -0
  35. package/bundled-skills/design-it/cyber-y2k/SKILL.md +312 -0
  36. package/bundled-skills/design-it/cyberpunk-ui/SKILL.md +262 -0
  37. package/bundled-skills/design-it/dark-mode/SKILL.md +289 -0
  38. package/bundled-skills/design-it/dashboard-design/SKILL.md +331 -0
  39. package/bundled-skills/design-it/data-dense-design/SKILL.md +322 -0
  40. package/bundled-skills/design-it/duotone-design/SKILL.md +248 -0
  41. package/bundled-skills/design-it/editorial-design/SKILL.md +328 -0
  42. package/bundled-skills/design-it/flat-design/SKILL.md +221 -0
  43. package/bundled-skills/design-it/flat-design-2/SKILL.md +240 -0
  44. package/bundled-skills/design-it/floating-ui/SKILL.md +299 -0
  45. package/bundled-skills/design-it/frutiger-aero/SKILL.md +274 -0
  46. package/bundled-skills/design-it/glassmorphism/SKILL.md +272 -0
  47. package/bundled-skills/design-it/gradient-design/SKILL.md +309 -0
  48. package/bundled-skills/design-it/high-contrast/SKILL.md +288 -0
  49. package/bundled-skills/design-it/holographic-ui/SKILL.md +310 -0
  50. package/bundled-skills/design-it/isometric-design/SKILL.md +228 -0
  51. package/bundled-skills/design-it/layered-design/SKILL.md +247 -0
  52. package/bundled-skills/design-it/material-design/SKILL.md +275 -0
  53. package/bundled-skills/design-it/maximalism/SKILL.md +297 -0
  54. package/bundled-skills/design-it/minimalism/SKILL.md +267 -0
  55. package/bundled-skills/design-it/monochromatic-ui/SKILL.md +296 -0
  56. package/bundled-skills/design-it/neo-brutalism/SKILL.md +270 -0
  57. package/bundled-skills/design-it/neumorphism/SKILL.md +248 -0
  58. package/bundled-skills/design-it/retro-design/SKILL.md +283 -0
  59. package/bundled-skills/design-it/retro-futurism/SKILL.md +259 -0
  60. package/bundled-skills/design-it/sci-fi-interface/SKILL.md +309 -0
  61. package/bundled-skills/design-it/skeuomorphism/SKILL.md +280 -0
  62. package/bundled-skills/design-it/soft-pastel/SKILL.md +307 -0
  63. package/bundled-skills/design-it/spatial-computing-ui/SKILL.md +300 -0
  64. package/bundled-skills/design-it/spatial-design/SKILL.md +268 -0
  65. package/bundled-skills/design-it/swiss-design/SKILL.md +293 -0
  66. package/bundled-skills/design-it/synthwave/SKILL.md +257 -0
  67. package/bundled-skills/design-it/tile-design/SKILL.md +297 -0
  68. package/bundled-skills/design-it/typography-first/SKILL.md +247 -0
  69. package/bundled-skills/design-it/vaporwave/SKILL.md +331 -0
  70. package/bundled-skills/design-it/vibrant-maximalism/SKILL.md +291 -0
  71. package/bundled-skills/design-it/widget-based-design/SKILL.md +274 -0
  72. package/bundled-skills/design-it/y2k-design/SKILL.md +268 -0
  73. package/bundled-skills/diagnosing-bugs/SKILL.md +165 -0
  74. package/bundled-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  75. package/bundled-skills/docs/contributors/skill-scoring.md +235 -0
  76. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  77. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  78. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  79. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  80. package/bundled-skills/docs/users/bundles.md +1 -1
  81. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  82. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  83. package/bundled-skills/docs/users/getting-started.md +1 -1
  84. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  85. package/bundled-skills/docs/users/usage.md +4 -4
  86. package/bundled-skills/docs/users/visual-guide.md +4 -4
  87. package/bundled-skills/domain-modeling/ADR-FORMAT.md +47 -0
  88. package/bundled-skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  89. package/bundled-skills/domain-modeling/SKILL.md +105 -0
  90. package/bundled-skills/grill-me/SKILL.md +36 -0
  91. package/bundled-skills/grill-with-docs/SKILL.md +36 -0
  92. package/bundled-skills/grilling/SKILL.md +39 -0
  93. package/bundled-skills/handoff/SKILL.md +45 -0
  94. package/bundled-skills/image-generator/.env.example +7 -0
  95. package/bundled-skills/image-generator/SKILL.md +509 -0
  96. package/bundled-skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
  97. package/bundled-skills/improve-codebase-architecture/SKILL.md +97 -0
  98. package/bundled-skills/learn/SKILL.md +156 -0
  99. package/bundled-skills/lesson-generator/SKILL.md +90 -0
  100. package/bundled-skills/llm-council/.env.example +7 -0
  101. package/bundled-skills/llm-council/SKILL.md +602 -0
  102. package/bundled-skills/loop-library/SKILL.md +205 -0
  103. package/bundled-skills/loop-library/agents/openai.yaml +4 -0
  104. package/bundled-skills/loop-library/references/catalog.md +270 -0
  105. package/bundled-skills/mailtrap-managing-contacts/SKILL.md +112 -0
  106. package/bundled-skills/mailtrap-sending-emails/SKILL.md +167 -0
  107. package/bundled-skills/mailtrap-setting-up-sending-domain/SKILL.md +77 -0
  108. package/bundled-skills/mailtrap-testing-with-sandbox/SKILL.md +110 -0
  109. package/bundled-skills/prototype/LOGIC.md +79 -0
  110. package/bundled-skills/prototype/SKILL.md +62 -0
  111. package/bundled-skills/prototype/UI.md +112 -0
  112. package/bundled-skills/setup-matt-pocock-skills/SKILL.md +158 -0
  113. package/bundled-skills/setup-matt-pocock-skills/domain.md +51 -0
  114. package/bundled-skills/setup-matt-pocock-skills/issue-tracker-github.md +34 -0
  115. package/bundled-skills/setup-matt-pocock-skills/issue-tracker-gitlab.md +35 -0
  116. package/bundled-skills/setup-matt-pocock-skills/issue-tracker-local.md +19 -0
  117. package/bundled-skills/setup-matt-pocock-skills/triage-labels.md +15 -0
  118. package/bundled-skills/survey-generator/LICENSE +21 -0
  119. package/bundled-skills/survey-generator/SKILL.md +143 -0
  120. package/bundled-skills/survey-generator/build_artifact.py +208 -0
  121. package/bundled-skills/survey-generator/examples/agentic-engineering/research_bundle.json +1196 -0
  122. package/bundled-skills/survey-generator/examples/agentic-engineering/survey.html +706 -0
  123. package/bundled-skills/survey-generator/style_spec.json +85 -0
  124. package/bundled-skills/survey-generator/templates/research_bundle_template.json +69 -0
  125. package/bundled-skills/tdd/SKILL.md +139 -0
  126. package/bundled-skills/tdd/mocking.md +59 -0
  127. package/bundled-skills/tdd/refactoring.md +10 -0
  128. package/bundled-skills/tdd/tests.md +61 -0
  129. package/bundled-skills/teach/GLOSSARY-FORMAT.md +35 -0
  130. package/bundled-skills/teach/LEARNING-RECORD-FORMAT.md +46 -0
  131. package/bundled-skills/teach/MISSION-FORMAT.md +31 -0
  132. package/bundled-skills/teach/RESOURCES-FORMAT.md +32 -0
  133. package/bundled-skills/teach/SKILL.md +169 -0
  134. package/bundled-skills/to-issues/SKILL.md +115 -0
  135. package/bundled-skills/to-prd/SKILL.md +104 -0
  136. package/bundled-skills/tools-page-seo-optimizer/SKILL.md +616 -0
  137. package/bundled-skills/triage/AGENT-BRIEF.md +207 -0
  138. package/bundled-skills/triage/OUT-OF-SCOPE.md +105 -0
  139. package/bundled-skills/triage/SKILL.md +143 -0
  140. package/bundled-skills/vibecode-production-qa-validator/SKILL.md +371 -141
  141. package/bundled-skills/wiki-builder/SKILL.md +157 -0
  142. package/bundled-skills/wiki-builder/agents/openai.yaml +5 -0
  143. package/bundled-skills/wiki-builder/references/wiki-flavors.md +98 -0
  144. package/bundled-skills/wiki-builder/scripts/init_wiki.sh +105 -0
  145. package/bundled-skills/wiki-builder/templates/index.md +20 -0
  146. package/bundled-skills/wiki-builder/templates/maintenance-log.md +7 -0
  147. package/bundled-skills/wiki-builder/templates/prompts/compile-concept-page.md +12 -0
  148. package/bundled-skills/wiki-builder/templates/prompts/compile-index.md +11 -0
  149. package/bundled-skills/wiki-builder/templates/prompts/compile-source-page.md +12 -0
  150. package/bundled-skills/wiki-builder/templates/prompts/lint-wiki.md +10 -0
  151. package/bundled-skills/wiki-builder/templates/prompts/query-and-file.md +11 -0
  152. package/bundled-skills/wiki-builder/templates/sources.md +9 -0
  153. package/bundled-skills/wiki-builder/templates/wiki.config.md +53 -0
  154. package/bundled-skills/writing-great-skills/GLOSSARY.md +181 -0
  155. package/bundled-skills/writing-great-skills/SKILL.md +111 -0
  156. package/bundled-skills/yao-meta-skill/SKILL.md +86 -0
  157. package/bundled-skills/yao-meta-skill/agents/interface.yaml +26 -0
  158. package/bundled-skills/yao-meta-skill/manifest.json +24 -0
  159. package/bundled-skills/yao-meta-skill/references/artifact-design-doctrine.md +49 -0
  160. package/bundled-skills/yao-meta-skill/references/authoring-discipline.md +78 -0
  161. package/bundled-skills/yao-meta-skill/references/autonomous-adaptation.md +65 -0
  162. package/bundled-skills/yao-meta-skill/references/distribution-registry-method.md +60 -0
  163. package/bundled-skills/yao-meta-skill/references/eval-playbook.md +69 -0
  164. package/bundled-skills/yao-meta-skill/references/gate-selection.md +68 -0
  165. package/bundled-skills/yao-meta-skill/references/governance.md +134 -0
  166. package/bundled-skills/yao-meta-skill/references/human-review-template.md +54 -0
  167. package/bundled-skills/yao-meta-skill/references/intent-dialogue.md +138 -0
  168. package/bundled-skills/yao-meta-skill/references/iteration-philosophy.md +30 -0
  169. package/bundled-skills/yao-meta-skill/references/non-skill-decision-tree.md +39 -0
  170. package/bundled-skills/yao-meta-skill/references/operating-modes.md +107 -0
  171. package/bundled-skills/yao-meta-skill/references/output-eval-method.md +113 -0
  172. package/bundled-skills/yao-meta-skill/references/output-quality-risk.md +41 -0
  173. package/bundled-skills/yao-meta-skill/references/output-visual-quality.md +53 -0
  174. package/bundled-skills/yao-meta-skill/references/packaging-contracts.md +70 -0
  175. package/bundled-skills/yao-meta-skill/references/pattern-extraction-doctrine.md +76 -0
  176. package/bundled-skills/yao-meta-skill/references/platform-capability-matrix.md +49 -0
  177. package/bundled-skills/yao-meta-skill/references/prompt-engineering-doctrine.md +76 -0
  178. package/bundled-skills/yao-meta-skill/references/qa-ladder.md +57 -0
  179. package/bundled-skills/yao-meta-skill/references/reference-scan.md +126 -0
  180. package/bundled-skills/yao-meta-skill/references/regression-cause-taxonomy.md +80 -0
  181. package/bundled-skills/yao-meta-skill/references/resource-boundaries.md +120 -0
  182. package/bundled-skills/yao-meta-skill/references/review-studio-method.md +87 -0
  183. package/bundled-skills/yao-meta-skill/references/review-waiver-method.md +76 -0
  184. package/bundled-skills/yao-meta-skill/references/runtime-conformance-method.md +21 -0
  185. package/bundled-skills/yao-meta-skill/references/skill-archetypes.md +86 -0
  186. package/bundled-skills/yao-meta-skill/references/skill-atlas-method.md +35 -0
  187. package/bundled-skills/yao-meta-skill/references/skill-engineering-method.md +210 -0
  188. package/bundled-skills/yao-meta-skill/references/skill-ir-method.md +41 -0
  189. package/bundled-skills/yao-meta-skill/references/skillops-decision-policy.md +53 -0
  190. package/bundled-skills/yao-meta-skill/references/systems-thinking-doctrine.md +75 -0
  191. package/bundled-skills/yao-meta-skill/references/telemetry-drift-method.md +182 -0
  192. package/bundled-skills/yao-meta-skill/references/trust-security-method.md +79 -0
  193. package/bundled-skills/yao-meta-skill/references/user-memory-policy.md +35 -0
  194. package/bundled-skills/youtube-notetaker/SKILL.md +209 -0
  195. package/bundled-skills/youtube-notetaker/reference/artifact.html +269 -0
  196. package/bundled-skills/youtube-notetaker/scripts/contact_sheet.py +53 -0
  197. package/bundled-skills/youtube-notetaker/scripts/detect_slides.sh +19 -0
  198. package/bundled-skills/youtube-notetaker/scripts/download.sh +24 -0
  199. package/bundled-skills/youtube-notetaker/scripts/extract_slides.py +43 -0
  200. package/bundled-skills/youtube-notetaker/scripts/serve.py +173 -0
  201. package/bundled-skills/youtube-notetaker/scripts/setup.sh +27 -0
  202. package/bundled-skills/youtube-notetaker/scripts/verify.sh +31 -0
  203. package/bundled-skills/youtube-notetaker/scripts/vtt_to_transcript.py +59 -0
  204. package/bundled-skills/youtube-notetaker/scripts/write_library_item.py +69 -0
  205. package/package.json +1 -1
  206. package/skills_index.json +1956 -286
  207. package/bundled-skills/ai-md/SKILL.md +0 -523
  208. package/bundled-skills/atlas-contract/SKILL.md +0 -650
  209. package/bundled-skills/busybox-on-windows/SKILL.md +0 -40
  210. package/bundled-skills/monte-carlo-prevent/SKILL.md +0 -257
  211. package/bundled-skills/monte-carlo-prevent/references/TROUBLESHOOTING.md +0 -23
  212. package/bundled-skills/monte-carlo-prevent/references/parameters.md +0 -32
  213. package/bundled-skills/monte-carlo-prevent/references/workflows.md +0 -478
  214. package/bundled-skills/monte-carlo-push-ingestion/SKILL.md +0 -372
  215. package/bundled-skills/monte-carlo-push-ingestion/references/anomaly-detection.md +0 -87
  216. package/bundled-skills/monte-carlo-push-ingestion/references/custom-lineage.md +0 -203
  217. package/bundled-skills/monte-carlo-push-ingestion/references/direct-http-api.md +0 -207
  218. package/bundled-skills/monte-carlo-push-ingestion/references/prerequisites.md +0 -150
  219. package/bundled-skills/monte-carlo-push-ingestion/references/push-lineage.md +0 -160
  220. package/bundled-skills/monte-carlo-push-ingestion/references/push-metadata.md +0 -158
  221. package/bundled-skills/monte-carlo-push-ingestion/references/push-query-logs.md +0 -219
  222. package/bundled-skills/monte-carlo-push-ingestion/references/validation.md +0 -257
  223. package/bundled-skills/monte-carlo-push-ingestion/scripts/sample_verify.py +0 -357
  224. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_lineage.py +0 -70
  225. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_metadata.py +0 -65
  226. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_query_logs.py +0 -70
  227. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_lineage.py +0 -214
  228. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_metadata.py +0 -160
  229. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_query_logs.py +0 -164
  230. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_lineage.py +0 -198
  231. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_metadata.py +0 -193
  232. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_query_logs.py +0 -207
  233. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_metadata.py +0 -71
  234. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_query_logs.py +0 -64
  235. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_metadata.py +0 -253
  236. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_query_logs.py +0 -149
  237. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_metadata.py +0 -190
  238. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_query_logs.py +0 -208
  239. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_lineage.py +0 -83
  240. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_metadata.py +0 -77
  241. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_query_logs.py +0 -83
  242. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_lineage.py +0 -240
  243. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_metadata.py +0 -212
  244. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_query_logs.py +0 -204
  245. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_lineage.py +0 -192
  246. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_metadata.py +0 -178
  247. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_query_logs.py +0 -200
  248. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_lineage.py +0 -119
  249. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_metadata.py +0 -119
  250. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_query_logs.py +0 -117
  251. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_lineage.py +0 -265
  252. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_metadata.py +0 -313
  253. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_query_logs.py +0 -284
  254. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_lineage.py +0 -309
  255. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_metadata.py +0 -245
  256. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_query_logs.py +0 -255
  257. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_lineage.py +0 -78
  258. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_metadata.py +0 -80
  259. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_query_logs.py +0 -88
  260. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_lineage.py +0 -235
  261. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_metadata.py +0 -219
  262. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_query_logs.py +0 -239
  263. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_lineage.py +0 -178
  264. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_metadata.py +0 -178
  265. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_query_logs.py +0 -196
  266. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_lineage.py +0 -154
  267. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_metadata.py +0 -137
  268. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_query_logs.py +0 -137
  269. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_lineage.py +0 -349
  270. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_metadata.py +0 -329
  271. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_query_logs.py +0 -254
  272. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_lineage.py +0 -307
  273. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_metadata.py +0 -228
  274. package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_query_logs.py +0 -248
  275. package/bundled-skills/monte-carlo-push-ingestion/scripts/test_template_sdk_usage.py +0 -340
  276. package/bundled-skills/skill-optimizer/SKILL.md +0 -271
  277. package/bundled-skills/using-superpowers/SKILL.md +0 -98
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Merges per-lane partial markdown files into one consolidated file per competitor.
4
+ //
5
+ // The 5-lane subagent fan-out writes partials to: {OUTPUT_DIR}/partials/{slug}.{lane}.md
6
+ // lane ∈ { marketing, discussion, social, news, technical }
7
+ //
8
+ // Each partial has its own YAML frontmatter + sections. The marketing partial owns
9
+ // the canonical frontmatter (pricing, features, etc.); other lanes contribute only
10
+ // Mentions / Benchmarks / Findings bullets. The merge:
11
+ // 1. Starts from marketing.md's frontmatter as the canonical header
12
+ // 2. Appends body sections in the canonical order (Product, Pricing, Features,
13
+ // Positioning, Comparison, Mentions, Benchmarks, Research Findings)
14
+ // 3. Unions all Mentions bullets across lanes, dedups by URL, sorts by date desc
15
+ // 4. Unions all Research Findings bullets across lanes
16
+ // 5. Unions all Benchmarks bullets
17
+ // 6. Writes the consolidated file to {OUTPUT_DIR}/{slug}.md
18
+ //
19
+ // Usage: node merge_partials.mjs <research-dir>
20
+
21
+ import { readdirSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
22
+ import { join } from 'path';
23
+ import { parseFrontmatter, parseBody, parseSections } from './md_utils.mjs';
24
+
25
+ const args = process.argv.slice(2);
26
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
27
+ console.error(`Usage: node merge_partials.mjs <research-dir>
28
+
29
+ Reads {dir}/partials/{slug}.{lane}.md files and writes consolidated
30
+ {dir}/{slug}.md per competitor. Lanes: marketing, discussion, social, news, technical.`);
31
+ process.exit(args.includes('--help') || args.includes('-h') ? 0 : 1);
32
+ }
33
+
34
+ const dir = args[0];
35
+ const partialsDir = join(dir, 'partials');
36
+
37
+ const LANES = ['marketing', 'discussion', 'social', 'news', 'technical', 'battle'];
38
+
39
+ function extractBullets(sectionText) {
40
+ if (!sectionText) return [];
41
+ const out = [];
42
+ for (const raw of sectionText.split('\n')) {
43
+ const line = raw.trim();
44
+ // Accept either "- ..." or numbered-list "1. ..." — normalize both to "- ...".
45
+ if (line.startsWith('- ')) out.push(line);
46
+ else {
47
+ const m = line.match(/^\d+\.\s+(.*)$/);
48
+ if (m) out.push('- ' + m[1]);
49
+ }
50
+ }
51
+ return out;
52
+ }
53
+
54
+ // Normalize Mentions bullet lines to the canonical format that `compile_report.mjs`
55
+ // parses: `- **[SourceType]** Title | Snippet (source: URL, YYYY-MM-DD)`.
56
+ //
57
+ // Lane subagents deviate in practice — we've observed at least three variants:
58
+ // A) discussion-style: `- **HN** — [Title](url) — snippet`
59
+ // B) news-style: `- **2025-08-06** — [News] Outlet — "title" — url`
60
+ // C) canonical: `- **[SourceType]** Title | Snippet (source: URL, YYYY-MM-DD)`
61
+ // Rather than fighting prompt drift, normalize at merge time so downstream stays clean.
62
+ function normalizeMentionBullet(line) {
63
+ // Already canonical — nothing to do.
64
+ if (/^-\s*\*\*\[\w+\]\*\*/.test(line)) return line;
65
+
66
+ const urlMatch = line.match(/https?:\/\/\S+/);
67
+ const url = urlMatch ? urlMatch[0].replace(/[).,\]\s]+$/, '') : '';
68
+ const dateMatch = line.match(/\b(\d{4}-\d{2}-\d{2})\b/);
69
+ const date = dateMatch ? dateMatch[1] : '';
70
+
71
+ // Pattern A — `- **SourceType** — [Title](url) — snippet` (e.g. discussion lane)
72
+ // **SourceType** is bold but without the brackets we want in canonical form.
73
+ let m = line.match(/^-\s*\*\*([^*]+)\*\*\s*[—\-]\s*\[([^\]]+)\]\(([^)]+)\)\s*(?:[—\-]\s*(.*))?$/);
74
+ if (m) {
75
+ const [, rawType, title, linkUrl, snippet] = m;
76
+ const sourceType = rawType.trim().replace(/^\[|\]$/g, '');
77
+ const snippetStr = snippet && snippet.trim() ? ` | ${snippet.trim()}` : '';
78
+ const dateStr = date ? `, ${date}` : '';
79
+ return `- **[${sourceType}]** ${title.trim()}${snippetStr} (source: ${linkUrl}${dateStr})`;
80
+ }
81
+
82
+ // Pattern B — `- **YYYY-MM-DD** — [SourceType] Outlet — "title" — url` (e.g. news lane)
83
+ m = line.match(/^-\s*\*\*(\d{4}-\d{2}-\d{2})\*\*\s*[—\-]\s*\[(\w+)\]\s+([^—]+?)\s*[—\-]\s*"?([^"]+?)"?\s*(?:[—\-]\s*(\S+))?\s*$/);
84
+ if (m) {
85
+ const [, dateStr, sourceType, outlet, title, trailingUrl] = m;
86
+ const finalUrl = trailingUrl && trailingUrl.startsWith('http') ? trailingUrl : url;
87
+ const snippet = outlet.trim();
88
+ return `- **[${sourceType}]** ${title.trim()}${snippet ? ` | ${snippet}` : ''} (source: ${finalUrl || ''}, ${dateStr})`;
89
+ }
90
+
91
+ // Pattern C — generic fallback: find any `**X**` tag + URL and format canonically.
92
+ m = line.match(/^-\s*\*\*([^*]+)\*\*\s*(.*)/);
93
+ if (m && url) {
94
+ const rawType = m[1].trim().replace(/^\[|\]$/g, '');
95
+ // If the leading token is a date, try to pull a later **type** off the rest.
96
+ let sourceType = rawType;
97
+ if (/^\d{4}-\d{2}-\d{2}$/.test(rawType)) {
98
+ const innerType = m[2].match(/\[(\w+)\]/);
99
+ if (innerType) sourceType = innerType[1];
100
+ }
101
+ const linkTextM = m[2].match(/\[([^\]]+)\]/);
102
+ const title = linkTextM ? linkTextM[1] : m[2].replace(url, '').replace(/[—"]+/g, '').replace(/^\W+|\W+$/g, '').slice(0, 100);
103
+ const dateStr = date ? `, ${date}` : '';
104
+ return `- **[${sourceType}]** ${title.trim()} (source: ${url}${dateStr})`;
105
+ }
106
+
107
+ // Last resort — leave line untouched (preserves data even if un-parseable).
108
+ return line;
109
+ }
110
+
111
+ function urlOf(bullet) {
112
+ const m = bullet.match(/\(source:\s*([^,)]+)/);
113
+ return m ? m[1].trim() : null;
114
+ }
115
+
116
+ function dateOf(bullet) {
117
+ const m = bullet.match(/\(source:\s*[^,)]+,\s*(\d{4}-\d{2}-\d{2})/);
118
+ return m ? m[1] : '';
119
+ }
120
+
121
+ let files;
122
+ try { files = readdirSync(partialsDir); } catch {
123
+ console.error(`No partials directory at ${partialsDir} — nothing to merge.`);
124
+ process.exit(0);
125
+ }
126
+
127
+ // Group partials by slug
128
+ const bySlug = new Map();
129
+ for (const f of files) {
130
+ if (!f.endsWith('.md')) continue;
131
+ const m = f.match(/^(.+)\.([a-z]+)\.md$/);
132
+ if (!m) continue;
133
+ const slug = m[1];
134
+ const lane = m[2];
135
+ if (!LANES.includes(lane)) continue;
136
+ if (!bySlug.has(slug)) bySlug.set(slug, {});
137
+ const content = readFileSync(join(partialsDir, f), 'utf-8');
138
+ bySlug.get(slug)[lane] = { fm: parseFrontmatter(content), body: parseBody(content) };
139
+ }
140
+
141
+ let merged = 0;
142
+ for (const [slug, lanes] of bySlug.entries()) {
143
+ const marketing = lanes.marketing;
144
+ if (!marketing || !marketing.fm) {
145
+ console.error(`[skip] ${slug}: no marketing partial — cannot form canonical frontmatter`);
146
+ continue;
147
+ }
148
+
149
+ // Union body sections
150
+ const allSections = {};
151
+ for (const lane of LANES) {
152
+ if (!lanes[lane]) continue;
153
+ const secs = parseSections(lanes[lane].body);
154
+ for (const [k, v] of Object.entries(secs)) {
155
+ if (!allSections[k]) allSections[k] = [];
156
+ allSections[k].push(v);
157
+ }
158
+ }
159
+
160
+ // Normalize → dedup Mentions by URL, sort by date desc
161
+ const rawBullets = (allSections['Mentions'] || []).flatMap(s => extractBullets(s));
162
+ const mentionBullets = rawBullets.map(normalizeMentionBullet);
163
+ const seenUrls = new Set();
164
+ const dedupedMentions = [];
165
+ for (const b of mentionBullets) {
166
+ const u = urlOf(b);
167
+ const key = u || b; // fallback to bullet text if no URL
168
+ if (seenUrls.has(key)) continue;
169
+ seenUrls.add(key);
170
+ dedupedMentions.push(b);
171
+ }
172
+ dedupedMentions.sort((a, b) => {
173
+ const da = dateOf(a), db = dateOf(b);
174
+ if (da && db) return db.localeCompare(da);
175
+ if (da) return -1;
176
+ if (db) return 1;
177
+ return 0;
178
+ });
179
+
180
+ // Dedup Benchmarks by URL
181
+ const benchmarkBullets = (allSections['Benchmarks'] || []).flatMap(s => extractBullets(s));
182
+ const seenBench = new Set();
183
+ const dedupedBench = [];
184
+ for (const b of benchmarkBullets) {
185
+ const m = b.match(/https?:\/\/\S+/);
186
+ const key = m ? m[0] : b;
187
+ if (seenBench.has(key)) continue;
188
+ seenBench.add(key);
189
+ dedupedBench.push(b);
190
+ }
191
+
192
+ // Dedup Findings loosely (by exact text)
193
+ const findingBullets = (allSections['Research Findings'] || []).flatMap(s => extractBullets(s));
194
+ const dedupedFindings = [...new Set(findingBullets)];
195
+
196
+ // Merge/prefer marketing for Product/Pricing/Features/Positioning/Comparison
197
+ function first(key) {
198
+ const arr = allSections[key] || [];
199
+ return arr.length ? arr[0] : '';
200
+ }
201
+
202
+ // Rebuild frontmatter — whitelist canonical fields only. Non-marketing lane subagents
203
+ // sometimes leak ad-hoc meta fields (notes, searches_run, lane, etc.) into their partial's
204
+ // frontmatter; those are debug/summary fields, not canonical data. Drop them here.
205
+ const CANONICAL_FIELDS = [
206
+ 'competitor_name', 'website', 'pricing_url',
207
+ 'tagline', 'positioning', 'product_description', 'target_customer',
208
+ 'pricing_model', 'pricing_tiers', 'key_features', 'integrations',
209
+ 'headquarters', 'founded', 'employee_estimate', 'funding_info',
210
+ 'strategic_diff',
211
+ ];
212
+ // Subagents drift on canonical field names too. Common aliases observed in real runs:
213
+ // `competitor` → `competitor_name` (browsaur marketing subagent), `homepage` → `website`,
214
+ // `price_tiers` → `pricing_tiers`. Accept aliases silently.
215
+ //
216
+ // NOTE: a bare `pricing` key is mapped to `pricing_model`, NOT `pricing_tiers`. In practice
217
+ // subagents use `pricing` for a pricing *model* or prose summary ("usage-based", "$0.005/req")
218
+ // far more often than for an enumerated tier list, so routing it to `pricing_tiers` corrupted
219
+ // the structured tier data the overview/matrix render from. Use `price_tiers`/`pricing_tiers`
220
+ // explicitly for tiers.
221
+ const FIELD_ALIASES = {
222
+ 'competitor': 'competitor_name',
223
+ 'name': 'competitor_name',
224
+ 'company': 'competitor_name',
225
+ 'homepage': 'website',
226
+ 'url': 'website',
227
+ 'price_tiers': 'pricing_tiers',
228
+ 'pricing': 'pricing_model',
229
+ };
230
+ function canonicalValue(fm, key) {
231
+ if (fm[key]) return fm[key];
232
+ for (const [alias, canonical] of Object.entries(FIELD_ALIASES)) {
233
+ if (canonical === key && fm[alias]) return fm[alias];
234
+ }
235
+ return undefined;
236
+ }
237
+ const mergedFm = {};
238
+ for (const k of CANONICAL_FIELDS) {
239
+ const v = canonicalValue(marketing.fm, k);
240
+ if (v) mergedFm[k] = v;
241
+ }
242
+ // Other lanes may fill in canonical gaps (e.g. funding_info from news, strategic_diff from technical).
243
+ for (const lane of LANES) {
244
+ if (lane === 'marketing' || !lanes[lane] || !lanes[lane].fm) continue;
245
+ for (const k of CANONICAL_FIELDS) {
246
+ if (!mergedFm[k]) {
247
+ const v = canonicalValue(lanes[lane].fm, k);
248
+ if (v) mergedFm[k] = v;
249
+ }
250
+ }
251
+ }
252
+
253
+ const fmLines = Object.entries(mergedFm).map(([k, v]) => `${k}: ${v}`).join('\n');
254
+
255
+ // Comparison heading may be "Comparison vs Exa" etc — find any key starting with "Comparison"
256
+ const comparisonKey = Object.keys(allSections).find(k => k.startsWith('Comparison'));
257
+ // Battle lane is format-drifty: subagents emit `## Battle Card`, `# Battle Card: X vs Y`
258
+ // (h1 — not picked up by parseSections), or skip the wrapper and lead with `## Landmines`.
259
+ // Treat the ENTIRE battle partial body as the Battle Card section regardless of heading style,
260
+ // so sales enablement content always lands in the merged file.
261
+ let battleCardBody = '';
262
+ if (lanes.battle && lanes.battle.body) {
263
+ const body = lanes.battle.body.trim();
264
+ // Strip the FIRST heading line if it mentions "Battle Card" — handles h1/h2/h3 and any
265
+ // suffix (e.g. `## Battle Card — Serper`, `# Battle Card: Tavily`). Otherwise the
266
+ // canonical `## Battle Card` wrapper added below produces duplicate headings.
267
+ battleCardBody = body.replace(/^#{1,3}\s+Battle\s*Card\b[^\n]*\n+/m, '').trim();
268
+ }
269
+
270
+ const out = [
271
+ '---',
272
+ fmLines,
273
+ '---',
274
+ '',
275
+ first('Product') ? `## Product\n${first('Product')}\n` : '',
276
+ first('Pricing') ? `## Pricing\n${first('Pricing')}\n` : '',
277
+ first('Features') ? `## Features\n${first('Features')}\n` : '',
278
+ first('Positioning') ? `## Positioning\n${first('Positioning')}\n` : '',
279
+ comparisonKey && allSections[comparisonKey].length ? `## ${comparisonKey}\n${allSections[comparisonKey][0]}\n` : '',
280
+ battleCardBody ? `## Battle Card\n${battleCardBody}\n` : '',
281
+ dedupedMentions.length ? `## Mentions\n${dedupedMentions.join('\n')}\n` : '',
282
+ dedupedBench.length ? `## Benchmarks\n${dedupedBench.join('\n')}\n` : '',
283
+ dedupedFindings.length ? `## Research Findings\n${dedupedFindings.join('\n')}\n` : '',
284
+ ].filter(Boolean).join('\n');
285
+
286
+ writeFileSync(join(dir, `${slug}.md`), out);
287
+ merged += 1;
288
+ console.error(`[ok] ${slug}: ${dedupedMentions.length} mentions, ${dedupedBench.length} benchmarks, ${dedupedFindings.length} findings`);
289
+ }
290
+
291
+ console.log(JSON.stringify({ merged, competitors: bySlug.size }));
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "competitor-analysis-scripts",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module"
6
+ }
@@ -0,0 +1,259 @@
1
+ ---
2
+ name: 3d-ui
3
+ description: Web and App implementation guide for 3D UI. Trigger when user wants actual 3D objects, perspective effects, and spatial depth.
4
+ date_added: "2026-06-17"
5
+ risk: safe
6
+ source: self
7
+ source_type: self
8
+ ---
9
+
10
+ # 3D UI
11
+
12
+ > "Breaking the plane. Interfaces that exist in a three-dimensional, rotatable space."
13
+
14
+
15
+ ## When to Use
16
+ Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.
17
+
18
+ ## Core Principles
19
+ 1. **True Depth (Z-Axis Translation)**: Elements don't just have shadows; they physically move closer to or further from the camera.
20
+ 2. **Perspective**: Use CSS perspective or WebGL to create realistic vanishing points.
21
+ 3. **Interactive Rotation**: Elements should respond to mouse movement or device gyroscope by tilting or rotating in 3D space.
22
+
23
+ ## Visual DNA
24
+ - **Colors**: Bold, striking palettes like **Midnight Luxury** or **Industrial Chic**. 3D elements need high contrast to show their geometry.
25
+ - **Typography**: Bold, blocky, or extruded text.
26
+ - **Graphics**: Instead of flat icons, use rendered 3D assets (.glb, .gltf, or high-res PNGs of 3D objects).
27
+
28
+ ## Web Implementation
29
+ - Rely heavily on `perspective`, `transform-style: preserve-3d`, and `rotateX`/`rotateY`.
30
+ - **CSS Example**:
31
+ ```css
32
+ .perspective-container {
33
+ perspective: 1000px;
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ }
38
+
39
+ .card-3d {
40
+ width: 300px;
41
+ height: 400px;
42
+ transform-style: preserve-3d;
43
+ transition: transform 0.5s ease;
44
+
45
+ /* Initial slight rotation */
46
+ transform: rotateX(15deg) rotateY(-15deg);
47
+ }
48
+
49
+ .card-3d:hover {
50
+ /* Straighten out on hover */
51
+ transform: rotateX(0) rotateY(0) translateZ(50px);
52
+ }
53
+
54
+ /* Inner elements popping out */
55
+ .card-content {
56
+ transform: translateZ(30px); /* Pushes content 30px closer to viewer */
57
+ }
58
+ ```
59
+
60
+ ## App Implementation
61
+
62
+ ### SwiftUI
63
+ ```swift
64
+ struct Card3D: View {
65
+ @State private var dragOffset = CGSize.zero
66
+
67
+ var body: some View {
68
+ VStack {
69
+ Text("3D Card")
70
+ .font(.largeTitle.bold())
71
+ .foregroundColor(.white)
72
+ }
73
+ .frame(width: 300, height: 400)
74
+ .background(
75
+ LinearGradient(colors: [.blue, .purple], startPoint: .topLeading, endPoint: .bottomTrailing)
76
+ )
77
+ .cornerRadius(24)
78
+ .shadow(radius: 20)
79
+ // Magic 3D effect based on drag gesture
80
+ .rotation3DEffect(
81
+ .degrees(Double(dragOffset.width / 10)),
82
+ axis: (x: 0, y: 1, z: 0),
83
+ perspective: 0.5
84
+ )
85
+ .rotation3DEffect(
86
+ .degrees(Double(-dragOffset.height / 10)),
87
+ axis: (x: 1, y: 0, z: 0),
88
+ perspective: 0.5
89
+ )
90
+ .gesture(
91
+ DragGesture()
92
+ .onChanged { value in
93
+ withAnimation(.interactiveSpring()) {
94
+ dragOffset = value.translation
95
+ }
96
+ }
97
+ .onEnded { _ in
98
+ withAnimation(.spring()) {
99
+ dragOffset = .zero
100
+ }
101
+ }
102
+ )
103
+ }
104
+ }
105
+ ```
106
+ - SwiftUI makes this incredibly easy with `.rotation3DEffect()`.
107
+ - Use the `perspective` parameter (default 1/6, higher = more distorted) to control the camera distance.
108
+ - Link the rotation axes (`x`, `y`) to drag gestures or CoreMotion (gyroscope) for interactive 3D UI.
109
+
110
+ ### Flutter
111
+ ```dart
112
+ class Card3D extends StatefulWidget {
113
+ @override
114
+ State<Card3D> createState() => _Card3DState();
115
+ }
116
+
117
+ class _Card3DState extends State<Card3D> {
118
+ Offset _offset = Offset.zero;
119
+
120
+ @override
121
+ Widget build(BuildContext context) {
122
+ return GestureDetector(
123
+ onPanUpdate: (details) {
124
+ setState(() => _offset += details.delta);
125
+ },
126
+ onPanEnd: (_) {
127
+ setState(() => _offset = Offset.zero); // Snap back
128
+ },
129
+ child: TweenAnimationBuilder(
130
+ tween: Tween<Offset>(begin: Offset.zero, end: _offset),
131
+ duration: const Duration(milliseconds: 200),
132
+ curve: Curves.easeOut,
133
+ builder: (context, Offset offset, child) {
134
+ // Perspective Matrix
135
+ final transform = Matrix4.identity()
136
+ ..setEntry(3, 2, 0.001) // perspective
137
+ ..rotateX(-offset.dy * 0.01)
138
+ ..rotateY(offset.dx * 0.01);
139
+
140
+ return Transform(
141
+ transform: transform,
142
+ alignment: FractionalOffset.center,
143
+ child: Container(
144
+ width: 300,
145
+ height: 400,
146
+ decoration: BoxDecoration(
147
+ gradient: const LinearGradient(colors: [Colors.blue, Colors.purple]),
148
+ borderRadius: BorderRadius.circular(24),
149
+ boxShadow: const [BoxShadow(color: Colors.black45, blurRadius: 20)],
150
+ ),
151
+ alignment: Alignment.center,
152
+ child: const Text('3D Card',
153
+ style: TextStyle(color: Colors.white, fontSize: 32, fontWeight: FontWeight.bold)),
154
+ ),
155
+ );
156
+ },
157
+ ),
158
+ );
159
+ }
160
+ }
161
+ ```
162
+ - The secret to perspective in Flutter is `Matrix4.identity()..setEntry(3, 2, 0.001)`.
163
+ - Wrap the target container in a `Transform` widget and apply rotations on the X and Y axes.
164
+ - Use `TweenAnimationBuilder` to smooth out the return-to-center physics.
165
+
166
+ ### React Native
167
+ ```jsx
168
+ const Card3D = () => {
169
+ const pan = useRef(new Animated.ValueXY()).current;
170
+
171
+ const panResponder = useRef(
172
+ PanResponder.create({
173
+ onStartShouldSetPanResponder: () => true,
174
+ onPanResponderMove: Animated.event([null, { dx: pan.x, dy: pan.y }], { useNativeDriver: false }),
175
+ onPanResponderRelease: () => {
176
+ Animated.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: false }).start();
177
+ },
178
+ })
179
+ ).current;
180
+
181
+ // Map drag distance to degrees
182
+ const rotateX = pan.y.interpolate({ inputRange: [-200, 200], outputRange: ['20deg', '-20deg'] });
183
+ const rotateY = pan.x.interpolate({ inputRange: [-200, 200], outputRange: ['-20deg', '20deg'] });
184
+
185
+ return (
186
+ <Animated.View
187
+ {...panResponder.panHandlers}
188
+ style={{
189
+ width: 300, height: 400,
190
+ backgroundColor: '#6b21a8',
191
+ borderRadius: 24,
192
+ justifyContent: 'center', alignItems: 'center',
193
+ // Pseudo-3D transforms
194
+ transform: [
195
+ { perspective: 1000 },
196
+ { rotateX },
197
+ { rotateY }
198
+ ]
199
+ }}
200
+ >
201
+ <Text style={{ color: '#fff', fontSize: 32, fontWeight: '700' }}>3D Card</Text>
202
+ </Animated.View>
203
+ );
204
+ };
205
+ ```
206
+ - True 3D models require `react-three-fiber`.
207
+ - For UI perspective transforms, use the `transform` array: `[{ perspective: 1000 }, { rotateX: '...' }, { rotateY: '...' }]`.
208
+ - `perspective` MUST be the first item in the transform array for the effect to render correctly.
209
+
210
+ ### Jetpack Compose
211
+ ```kotlin
212
+ @Composable
213
+ fun Card3D() {
214
+ var offset by remember { mutableStateOf(Offset.Zero) }
215
+ val animatedOffset by animateOffsetAsState(
216
+ targetValue = offset,
217
+ animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy)
218
+ )
219
+
220
+ Box(
221
+ modifier = Modifier
222
+ .size(300.dp, 400.dp)
223
+ .pointerInput(Unit) {
224
+ detectDragGestures(
225
+ onDrag = { change, dragAmount ->
226
+ change.consume()
227
+ offset += dragAmount
228
+ },
229
+ onDragEnd = { offset = Offset.Zero },
230
+ onDragCancel = { offset = Offset.Zero }
231
+ )
232
+ }
233
+ .graphicsLayer {
234
+ // Apply 3D rotation based on drag offset
235
+ rotationX = -animatedOffset.y * 0.1f
236
+ rotationY = animatedOffset.x * 0.1f
237
+ cameraDistance = 8f * density // Sets the perspective
238
+ }
239
+ .shadow(20.dp, RoundedCornerShape(24.dp))
240
+ .clip(RoundedCornerShape(24.dp))
241
+ .background(Brush.linearGradient(listOf(Color.Blue, Color.Magenta)))
242
+ ) {
243
+ Text("3D Card",
244
+ color = Color.White, fontSize = 32.sp, fontWeight = FontWeight.Bold,
245
+ modifier = Modifier.align(Alignment.Center))
246
+ }
247
+ }
248
+ ```
249
+ - Apply 3D transformations inside `Modifier.graphicsLayer { }`.
250
+ - Set `rotationX` and `rotationY` for the tilt.
251
+ - **Critical**: Set `cameraDistance` to establish the Z-axis perspective vanishing point. Usually `8f * density` is a good starting point.
252
+
253
+ ## Do's and Don'ts
254
+ - **DO**: Tie 3D rotation to user input (mouse move on web, device tilt on mobile) for maximum impact.
255
+ - **DON'T**: Make text itself 3D unless it's a massive headline. 3D text is generally unreadable at small sizes.
256
+
257
+ ## Limitations
258
+ - This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
259
+ - Ensure appropriate contrast ratios and responsive behaviors are verified separately.