jfl 0.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 (381) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +313 -0
  3. package/clawdbot-skill/README.md +328 -0
  4. package/clawdbot-skill/SKILL.md +362 -0
  5. package/clawdbot-skill/index.ts +486 -0
  6. package/clawdbot-skill/package.json +28 -0
  7. package/clawdbot-skill/skill.json +28 -0
  8. package/dist/commands/agents.d.ts +5 -0
  9. package/dist/commands/agents.d.ts.map +1 -0
  10. package/dist/commands/agents.js +399 -0
  11. package/dist/commands/agents.js.map +1 -0
  12. package/dist/commands/context-hub.d.ts +12 -0
  13. package/dist/commands/context-hub.d.ts.map +1 -0
  14. package/dist/commands/context-hub.js +642 -0
  15. package/dist/commands/context-hub.js.map +1 -0
  16. package/dist/commands/deploy.d.ts +5 -0
  17. package/dist/commands/deploy.d.ts.map +1 -0
  18. package/dist/commands/deploy.js +370 -0
  19. package/dist/commands/deploy.js.map +1 -0
  20. package/dist/commands/feedback.d.ts +2 -0
  21. package/dist/commands/feedback.d.ts.map +1 -0
  22. package/dist/commands/feedback.js +178 -0
  23. package/dist/commands/feedback.js.map +1 -0
  24. package/dist/commands/hud.d.ts +4 -0
  25. package/dist/commands/hud.d.ts.map +1 -0
  26. package/dist/commands/hud.js +262 -0
  27. package/dist/commands/hud.js.map +1 -0
  28. package/dist/commands/init.d.ts +4 -0
  29. package/dist/commands/init.d.ts.map +1 -0
  30. package/dist/commands/init.js +553 -0
  31. package/dist/commands/init.js.map +1 -0
  32. package/dist/commands/login.d.ts +23 -0
  33. package/dist/commands/login.d.ts.map +1 -0
  34. package/dist/commands/login.js +818 -0
  35. package/dist/commands/login.js.map +1 -0
  36. package/dist/commands/ralph.d.ts +9 -0
  37. package/dist/commands/ralph.d.ts.map +1 -0
  38. package/dist/commands/ralph.js +67 -0
  39. package/dist/commands/ralph.js.map +1 -0
  40. package/dist/commands/repair.d.ts +7 -0
  41. package/dist/commands/repair.d.ts.map +1 -0
  42. package/dist/commands/repair.js +283 -0
  43. package/dist/commands/repair.js.map +1 -0
  44. package/dist/commands/session-mgmt.d.ts +33 -0
  45. package/dist/commands/session-mgmt.d.ts.map +1 -0
  46. package/dist/commands/session-mgmt.js +404 -0
  47. package/dist/commands/session-mgmt.js.map +1 -0
  48. package/dist/commands/session.d.ts +2 -0
  49. package/dist/commands/session.d.ts.map +1 -0
  50. package/dist/commands/session.js +639 -0
  51. package/dist/commands/session.js.map +1 -0
  52. package/dist/commands/skills.d.ts +31 -0
  53. package/dist/commands/skills.d.ts.map +1 -0
  54. package/dist/commands/skills.js +314 -0
  55. package/dist/commands/skills.js.map +1 -0
  56. package/dist/commands/status.d.ts +2 -0
  57. package/dist/commands/status.d.ts.map +1 -0
  58. package/dist/commands/status.js +127 -0
  59. package/dist/commands/status.js.map +1 -0
  60. package/dist/commands/synopsis.d.ts +10 -0
  61. package/dist/commands/synopsis.d.ts.map +1 -0
  62. package/dist/commands/synopsis.js +277 -0
  63. package/dist/commands/synopsis.js.map +1 -0
  64. package/dist/commands/update.d.ts +10 -0
  65. package/dist/commands/update.d.ts.map +1 -0
  66. package/dist/commands/update.js +165 -0
  67. package/dist/commands/update.js.map +1 -0
  68. package/dist/commands/voice.d.ts +410 -0
  69. package/dist/commands/voice.d.ts.map +1 -0
  70. package/dist/commands/voice.js +4763 -0
  71. package/dist/commands/voice.js.map +1 -0
  72. package/dist/index.d.ts +9 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +512 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/mcp/context-hub-mcp.d.ts +11 -0
  77. package/dist/mcp/context-hub-mcp.d.ts.map +1 -0
  78. package/dist/mcp/context-hub-mcp.js +548 -0
  79. package/dist/mcp/context-hub-mcp.js.map +1 -0
  80. package/dist/telegram/voice.d.ts +146 -0
  81. package/dist/telegram/voice.d.ts.map +1 -0
  82. package/dist/telegram/voice.js +351 -0
  83. package/dist/telegram/voice.js.map +1 -0
  84. package/dist/types/skills.d.ts +44 -0
  85. package/dist/types/skills.d.ts.map +1 -0
  86. package/dist/types/skills.js +5 -0
  87. package/dist/types/skills.js.map +1 -0
  88. package/dist/ui/banner.d.ts +18 -0
  89. package/dist/ui/banner.d.ts.map +1 -0
  90. package/dist/ui/banner.js +323 -0
  91. package/dist/ui/banner.js.map +1 -0
  92. package/dist/ui/index.d.ts +8 -0
  93. package/dist/ui/index.d.ts.map +1 -0
  94. package/dist/ui/index.js +8 -0
  95. package/dist/ui/index.js.map +1 -0
  96. package/dist/ui/prompts.d.ts +52 -0
  97. package/dist/ui/prompts.d.ts.map +1 -0
  98. package/dist/ui/prompts.js +72 -0
  99. package/dist/ui/prompts.js.map +1 -0
  100. package/dist/ui/theme.d.ts +82 -0
  101. package/dist/ui/theme.d.ts.map +1 -0
  102. package/dist/ui/theme.js +142 -0
  103. package/dist/ui/theme.js.map +1 -0
  104. package/dist/utils/auth-guard.d.ts +66 -0
  105. package/dist/utils/auth-guard.d.ts.map +1 -0
  106. package/dist/utils/auth-guard.js +348 -0
  107. package/dist/utils/auth-guard.js.map +1 -0
  108. package/dist/utils/ensure-project.d.ts +11 -0
  109. package/dist/utils/ensure-project.d.ts.map +1 -0
  110. package/dist/utils/ensure-project.js +70 -0
  111. package/dist/utils/ensure-project.js.map +1 -0
  112. package/dist/utils/git.d.ts +73 -0
  113. package/dist/utils/git.d.ts.map +1 -0
  114. package/dist/utils/git.js +219 -0
  115. package/dist/utils/git.js.map +1 -0
  116. package/dist/utils/github-auth.d.ts +54 -0
  117. package/dist/utils/github-auth.d.ts.map +1 -0
  118. package/dist/utils/github-auth.js +375 -0
  119. package/dist/utils/github-auth.js.map +1 -0
  120. package/dist/utils/github-repo.d.ts +30 -0
  121. package/dist/utils/github-repo.d.ts.map +1 -0
  122. package/dist/utils/github-repo.js +219 -0
  123. package/dist/utils/github-repo.js.map +1 -0
  124. package/dist/utils/platform-auth.d.ts +81 -0
  125. package/dist/utils/platform-auth.d.ts.map +1 -0
  126. package/dist/utils/platform-auth.js +191 -0
  127. package/dist/utils/platform-auth.js.map +1 -0
  128. package/dist/utils/project-config.d.ts +43 -0
  129. package/dist/utils/project-config.d.ts.map +1 -0
  130. package/dist/utils/project-config.js +97 -0
  131. package/dist/utils/project-config.js.map +1 -0
  132. package/dist/utils/skill-registry.d.ts +49 -0
  133. package/dist/utils/skill-registry.d.ts.map +1 -0
  134. package/dist/utils/skill-registry.js +192 -0
  135. package/dist/utils/skill-registry.js.map +1 -0
  136. package/dist/utils/wallet.d.ts +62 -0
  137. package/dist/utils/wallet.d.ts.map +1 -0
  138. package/dist/utils/wallet.js +252 -0
  139. package/dist/utils/wallet.js.map +1 -0
  140. package/dist/utils/x402-client.d.ts +86 -0
  141. package/dist/utils/x402-client.d.ts.map +1 -0
  142. package/dist/utils/x402-client.js +265 -0
  143. package/dist/utils/x402-client.js.map +1 -0
  144. package/package.json +76 -0
  145. package/scripts/postinstall.js +116 -0
  146. package/scripts/test-onboarding.sh +121 -0
  147. package/scripts/voice-start.sh +128 -0
  148. package/scripts/voice-stop.sh +33 -0
  149. package/template/.claude/settings.json +92 -0
  150. package/template/.claude/skills/agent-browser/SKILL.md +116 -0
  151. package/template/.claude/skills/brand-architect/SKILL.md +240 -0
  152. package/template/.claude/skills/brand-architect/config.yaml +137 -0
  153. package/template/.claude/skills/campaign-hud/config.yaml +112 -0
  154. package/template/.claude/skills/content-creator/SKILL.md +294 -0
  155. package/template/.claude/skills/debug/MULTI_AGENT.md +360 -0
  156. package/template/.claude/skills/debug/SKILL.md +549 -0
  157. package/template/.claude/skills/fly-deploy/SKILL.md +676 -0
  158. package/template/.claude/skills/founder-video/SKILL.md +467 -0
  159. package/template/.claude/skills/hud/SKILL.md +157 -0
  160. package/template/.claude/skills/ralph-tui/SKILL.md +210 -0
  161. package/template/.claude/skills/react-best-practices/AGENTS.md +2249 -0
  162. package/template/.claude/skills/react-best-practices/README.md +123 -0
  163. package/template/.claude/skills/react-best-practices/SKILL.md +125 -0
  164. package/template/.claude/skills/react-best-practices/metadata.json +15 -0
  165. package/template/.claude/skills/react-best-practices/rules/_sections.md +46 -0
  166. package/template/.claude/skills/react-best-practices/rules/_template.md +28 -0
  167. package/template/.claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  168. package/template/.claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  169. package/template/.claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  170. package/template/.claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  171. package/template/.claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  172. package/template/.claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  173. package/template/.claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  174. package/template/.claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  175. package/template/.claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  176. package/template/.claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  177. package/template/.claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  178. package/template/.claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  179. package/template/.claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  180. package/template/.claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  181. package/template/.claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  182. package/template/.claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  183. package/template/.claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  184. package/template/.claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  185. package/template/.claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  186. package/template/.claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  187. package/template/.claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  188. package/template/.claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  189. package/template/.claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  190. package/template/.claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  191. package/template/.claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  192. package/template/.claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  193. package/template/.claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  194. package/template/.claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  195. package/template/.claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  196. package/template/.claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  197. package/template/.claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  198. package/template/.claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  199. package/template/.claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  200. package/template/.claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  201. package/template/.claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  202. package/template/.claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  203. package/template/.claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  204. package/template/.claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  205. package/template/.claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  206. package/template/.claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  207. package/template/.claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  208. package/template/.claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  209. package/template/.claude/skills/react-best-practices/rules/server-cache-react.md +26 -0
  210. package/template/.claude/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  211. package/template/.claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  212. package/template/.claude/skills/remotion-best-practices/SKILL.md +43 -0
  213. package/template/.claude/skills/remotion-best-practices/rules/3d.md +86 -0
  214. package/template/.claude/skills/remotion-best-practices/rules/animations.md +29 -0
  215. package/template/.claude/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  216. package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  217. package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  218. package/template/.claude/skills/remotion-best-practices/rules/assets.md +78 -0
  219. package/template/.claude/skills/remotion-best-practices/rules/audio.md +172 -0
  220. package/template/.claude/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
  221. package/template/.claude/skills/remotion-best-practices/rules/can-decode.md +75 -0
  222. package/template/.claude/skills/remotion-best-practices/rules/charts.md +58 -0
  223. package/template/.claude/skills/remotion-best-practices/rules/compositions.md +146 -0
  224. package/template/.claude/skills/remotion-best-practices/rules/display-captions.md +126 -0
  225. package/template/.claude/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  226. package/template/.claude/skills/remotion-best-practices/rules/fonts.md +152 -0
  227. package/template/.claude/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  228. package/template/.claude/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  229. package/template/.claude/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
  230. package/template/.claude/skills/remotion-best-practices/rules/gifs.md +138 -0
  231. package/template/.claude/skills/remotion-best-practices/rules/images.md +130 -0
  232. package/template/.claude/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
  233. package/template/.claude/skills/remotion-best-practices/rules/lottie.md +68 -0
  234. package/template/.claude/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
  235. package/template/.claude/skills/remotion-best-practices/rules/measuring-text.md +143 -0
  236. package/template/.claude/skills/remotion-best-practices/rules/sequencing.md +106 -0
  237. package/template/.claude/skills/remotion-best-practices/rules/tailwind.md +11 -0
  238. package/template/.claude/skills/remotion-best-practices/rules/text-animations.md +20 -0
  239. package/template/.claude/skills/remotion-best-practices/rules/timing.md +179 -0
  240. package/template/.claude/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
  241. package/template/.claude/skills/remotion-best-practices/rules/transitions.md +122 -0
  242. package/template/.claude/skills/remotion-best-practices/rules/trimming.md +53 -0
  243. package/template/.claude/skills/remotion-best-practices/rules/videos.md +171 -0
  244. package/template/.claude/skills/search/SKILL.md +220 -0
  245. package/template/.claude/skills/spec/SKILL.md +377 -0
  246. package/template/.claude/skills/startup/SKILL.md +310 -0
  247. package/template/.claude/skills/web-architect/SKILL.md +309 -0
  248. package/template/.claude/skills/x-algorithm/SKILL.md +305 -0
  249. package/template/.jfl/config.json +8 -0
  250. package/template/.mcp.json +11 -0
  251. package/template/CLAUDE.md +960 -0
  252. package/template/content/.gitkeep +0 -0
  253. package/template/context-hub +3 -0
  254. package/template/knowledge/BRAND_BRIEF.md +124 -0
  255. package/template/knowledge/BRAND_DECISIONS.md +168 -0
  256. package/template/knowledge/NARRATIVE.md +114 -0
  257. package/template/knowledge/ROADMAP.md +128 -0
  258. package/template/knowledge/THESIS.md +108 -0
  259. package/template/knowledge/VISION.md +74 -0
  260. package/template/knowledge/VOICE_AND_TONE.md +146 -0
  261. package/template/previews/.gitkeep +0 -0
  262. package/template/scripts/session/auto-commit.sh +245 -0
  263. package/template/scripts/session/auto-merge.sh +325 -0
  264. package/template/scripts/session/jfl-doctor.sh +587 -0
  265. package/template/scripts/session/session-end.sh +194 -0
  266. package/template/scripts/session/session-init.sh +163 -0
  267. package/template/scripts/session/session-sync.sh +167 -0
  268. package/template/scripts/session/test-context-preservation.sh +160 -0
  269. package/template/skills/agent-browser/SKILL.md +116 -0
  270. package/template/skills/brand-architect/SKILL.md +240 -0
  271. package/template/skills/brand-architect/config.yaml +137 -0
  272. package/template/skills/campaign-hud/config.yaml +112 -0
  273. package/template/skills/content-creator/SKILL.md +294 -0
  274. package/template/skills/debug/MULTI_AGENT.md +360 -0
  275. package/template/skills/debug/SKILL.md +549 -0
  276. package/template/skills/fly-deploy/SKILL.md +676 -0
  277. package/template/skills/founder-video/SKILL.md +467 -0
  278. package/template/skills/hud/SKILL.md +204 -0
  279. package/template/skills/ralph-tui/SKILL.md +210 -0
  280. package/template/skills/react-best-practices/AGENTS.md +2249 -0
  281. package/template/skills/react-best-practices/README.md +123 -0
  282. package/template/skills/react-best-practices/SKILL.md +125 -0
  283. package/template/skills/react-best-practices/metadata.json +15 -0
  284. package/template/skills/react-best-practices/rules/_sections.md +46 -0
  285. package/template/skills/react-best-practices/rules/_template.md +28 -0
  286. package/template/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  287. package/template/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  288. package/template/skills/react-best-practices/rules/async-api-routes.md +38 -0
  289. package/template/skills/react-best-practices/rules/async-defer-await.md +80 -0
  290. package/template/skills/react-best-practices/rules/async-dependencies.md +36 -0
  291. package/template/skills/react-best-practices/rules/async-parallel.md +28 -0
  292. package/template/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  293. package/template/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  294. package/template/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  295. package/template/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  296. package/template/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  297. package/template/skills/react-best-practices/rules/bundle-preload.md +50 -0
  298. package/template/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  299. package/template/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  300. package/template/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  301. package/template/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  302. package/template/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  303. package/template/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  304. package/template/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  305. package/template/skills/react-best-practices/rules/js-early-exit.md +50 -0
  306. package/template/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  307. package/template/skills/react-best-practices/rules/js-index-maps.md +37 -0
  308. package/template/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  309. package/template/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  310. package/template/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  311. package/template/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  312. package/template/skills/react-best-practices/rules/rendering-activity.md +26 -0
  313. package/template/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  314. package/template/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  315. package/template/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  316. package/template/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  317. package/template/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  318. package/template/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  319. package/template/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  320. package/template/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  321. package/template/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  322. package/template/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  323. package/template/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  324. package/template/skills/react-best-practices/rules/rerender-memo.md +44 -0
  325. package/template/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  326. package/template/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  327. package/template/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  328. package/template/skills/react-best-practices/rules/server-cache-react.md +26 -0
  329. package/template/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  330. package/template/skills/react-best-practices/rules/server-serialization.md +38 -0
  331. package/template/skills/remotion-best-practices/SKILL.md +43 -0
  332. package/template/skills/remotion-best-practices/rules/3d.md +86 -0
  333. package/template/skills/remotion-best-practices/rules/animations.md +29 -0
  334. package/template/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  335. package/template/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  336. package/template/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  337. package/template/skills/remotion-best-practices/rules/assets.md +78 -0
  338. package/template/skills/remotion-best-practices/rules/audio.md +172 -0
  339. package/template/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
  340. package/template/skills/remotion-best-practices/rules/can-decode.md +75 -0
  341. package/template/skills/remotion-best-practices/rules/charts.md +58 -0
  342. package/template/skills/remotion-best-practices/rules/compositions.md +146 -0
  343. package/template/skills/remotion-best-practices/rules/display-captions.md +126 -0
  344. package/template/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  345. package/template/skills/remotion-best-practices/rules/fonts.md +152 -0
  346. package/template/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  347. package/template/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  348. package/template/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
  349. package/template/skills/remotion-best-practices/rules/gifs.md +138 -0
  350. package/template/skills/remotion-best-practices/rules/images.md +130 -0
  351. package/template/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
  352. package/template/skills/remotion-best-practices/rules/lottie.md +68 -0
  353. package/template/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
  354. package/template/skills/remotion-best-practices/rules/measuring-text.md +143 -0
  355. package/template/skills/remotion-best-practices/rules/sequencing.md +106 -0
  356. package/template/skills/remotion-best-practices/rules/tailwind.md +11 -0
  357. package/template/skills/remotion-best-practices/rules/text-animations.md +20 -0
  358. package/template/skills/remotion-best-practices/rules/timing.md +179 -0
  359. package/template/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
  360. package/template/skills/remotion-best-practices/rules/transitions.md +122 -0
  361. package/template/skills/remotion-best-practices/rules/trimming.md +53 -0
  362. package/template/skills/remotion-best-practices/rules/videos.md +171 -0
  363. package/template/skills/search/SKILL.md +220 -0
  364. package/template/skills/spec/SKILL.md +377 -0
  365. package/template/skills/startup/SKILL.md +310 -0
  366. package/template/skills/web-architect/SKILL.md +309 -0
  367. package/template/skills/x-algorithm/SKILL.md +305 -0
  368. package/template/suggestions/.gitkeep +0 -0
  369. package/template/templates/QUICKSTART_SKILL_TO_PRODUCT.md +242 -0
  370. package/template/templates/brand/BRAND_BRIEF.md +124 -0
  371. package/template/templates/brand/BRAND_DECISIONS.md +168 -0
  372. package/template/templates/brand/BRAND_GUIDELINES.md +251 -0
  373. package/template/templates/brand/VOICE_AND_TONE.md +146 -0
  374. package/template/templates/brand/global.css +240 -0
  375. package/template/templates/collaboration/CONTRIBUTOR.md +74 -0
  376. package/template/templates/collaboration/CRM.md +97 -0
  377. package/template/templates/collaboration/TASKS.md +83 -0
  378. package/template/templates/strategic/NARRATIVE.md +114 -0
  379. package/template/templates/strategic/ROADMAP.md +128 -0
  380. package/template/templates/strategic/THESIS.md +108 -0
  381. package/template/templates/strategic/VISION.md +74 -0
@@ -0,0 +1,229 @@
1
+ ---
2
+ name: extract-frames
3
+ description: Extract frames from videos at specific timestamps using Mediabunny
4
+ metadata:
5
+ tags: frames, extract, video, thumbnail, filmstrip, canvas
6
+ ---
7
+
8
+ # Extracting frames from videos
9
+
10
+ Use Mediabunny to extract frames from videos at specific timestamps. This is useful for generating thumbnails, filmstrips, or processing individual frames.
11
+
12
+ ## The `extractFrames()` function
13
+
14
+ This function can be copy-pasted into any project.
15
+
16
+ ```tsx
17
+ import {
18
+ ALL_FORMATS,
19
+ Input,
20
+ UrlSource,
21
+ VideoSample,
22
+ VideoSampleSink,
23
+ } from "mediabunny";
24
+
25
+ type Options = {
26
+ track: { width: number; height: number };
27
+ container: string;
28
+ durationInSeconds: number | null;
29
+ };
30
+
31
+ export type ExtractFramesTimestampsInSecondsFn = (
32
+ options: Options
33
+ ) => Promise<number[]> | number[];
34
+
35
+ export type ExtractFramesProps = {
36
+ src: string;
37
+ timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
38
+ onVideoSample: (sample: VideoSample) => void;
39
+ signal?: AbortSignal;
40
+ };
41
+
42
+ export async function extractFrames({
43
+ src,
44
+ timestampsInSeconds,
45
+ onVideoSample,
46
+ signal,
47
+ }: ExtractFramesProps): Promise<void> {
48
+ using input = new Input({
49
+ formats: ALL_FORMATS,
50
+ source: new UrlSource(src),
51
+ });
52
+
53
+ const [durationInSeconds, format, videoTrack] = await Promise.all([
54
+ input.computeDuration(),
55
+ input.getFormat(),
56
+ input.getPrimaryVideoTrack(),
57
+ ]);
58
+
59
+ if (!videoTrack) {
60
+ throw new Error("No video track found in the input");
61
+ }
62
+
63
+ if (signal?.aborted) {
64
+ throw new Error("Aborted");
65
+ }
66
+
67
+ const timestamps =
68
+ typeof timestampsInSeconds === "function"
69
+ ? await timestampsInSeconds({
70
+ track: {
71
+ width: videoTrack.displayWidth,
72
+ height: videoTrack.displayHeight,
73
+ },
74
+ container: format.name,
75
+ durationInSeconds,
76
+ })
77
+ : timestampsInSeconds;
78
+
79
+ if (timestamps.length === 0) {
80
+ return;
81
+ }
82
+
83
+ if (signal?.aborted) {
84
+ throw new Error("Aborted");
85
+ }
86
+
87
+ const sink = new VideoSampleSink(videoTrack);
88
+
89
+ for await (using videoSample of sink.samplesAtTimestamps(timestamps)) {
90
+ if (signal?.aborted) {
91
+ break;
92
+ }
93
+
94
+ if (!videoSample) {
95
+ continue;
96
+ }
97
+
98
+ onVideoSample(videoSample);
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## Basic usage
104
+
105
+ Extract frames at specific timestamps:
106
+
107
+ ```tsx
108
+ await extractFrames({
109
+ src: "https://remotion.media/video.mp4",
110
+ timestampsInSeconds: [0, 1, 2, 3, 4],
111
+ onVideoSample: (sample) => {
112
+ const canvas = document.createElement("canvas");
113
+ canvas.width = sample.displayWidth;
114
+ canvas.height = sample.displayHeight;
115
+ const ctx = canvas.getContext("2d");
116
+ sample.draw(ctx!, 0, 0);
117
+ },
118
+ });
119
+ ```
120
+
121
+ ## Creating a filmstrip
122
+
123
+ Use a callback function to dynamically calculate timestamps based on video metadata:
124
+
125
+ ```tsx
126
+ const canvasWidth = 500;
127
+ const canvasHeight = 80;
128
+ const fromSeconds = 0;
129
+ const toSeconds = 10;
130
+
131
+ await extractFrames({
132
+ src: "https://remotion.media/video.mp4",
133
+ timestampsInSeconds: async ({ track, durationInSeconds }) => {
134
+ const aspectRatio = track.width / track.height;
135
+ const amountOfFramesFit = Math.ceil(
136
+ canvasWidth / (canvasHeight * aspectRatio)
137
+ );
138
+ const segmentDuration = toSeconds - fromSeconds;
139
+ const timestamps: number[] = [];
140
+
141
+ for (let i = 0; i < amountOfFramesFit; i++) {
142
+ timestamps.push(
143
+ fromSeconds + (segmentDuration / amountOfFramesFit) * (i + 0.5)
144
+ );
145
+ }
146
+
147
+ return timestamps;
148
+ },
149
+ onVideoSample: (sample) => {
150
+ console.log(`Frame at ${sample.timestamp}s`);
151
+
152
+ const canvas = document.createElement("canvas");
153
+ canvas.width = sample.displayWidth;
154
+ canvas.height = sample.displayHeight;
155
+ const ctx = canvas.getContext("2d");
156
+ sample.draw(ctx!, 0, 0);
157
+ },
158
+ });
159
+ ```
160
+
161
+ ## Cancellation with AbortSignal
162
+
163
+ Cancel frame extraction after a timeout:
164
+
165
+ ```tsx
166
+ const controller = new AbortController();
167
+
168
+ setTimeout(() => controller.abort(), 5000);
169
+
170
+ try {
171
+ await extractFrames({
172
+ src: "https://remotion.media/video.mp4",
173
+ timestampsInSeconds: [0, 1, 2, 3, 4],
174
+ onVideoSample: (sample) => {
175
+ using frame = sample;
176
+ const canvas = document.createElement("canvas");
177
+ canvas.width = frame.displayWidth;
178
+ canvas.height = frame.displayHeight;
179
+ const ctx = canvas.getContext("2d");
180
+ frame.draw(ctx!, 0, 0);
181
+ },
182
+ signal: controller.signal,
183
+ });
184
+
185
+ console.log("Frame extraction complete!");
186
+ } catch (error) {
187
+ console.error("Frame extraction was aborted or failed:", error);
188
+ }
189
+ ```
190
+
191
+ ## Timeout with Promise.race
192
+
193
+ ```tsx
194
+ const controller = new AbortController();
195
+
196
+ const timeoutPromise = new Promise<never>((_, reject) => {
197
+ const timeoutId = setTimeout(() => {
198
+ controller.abort();
199
+ reject(new Error("Frame extraction timed out after 10 seconds"));
200
+ }, 10000);
201
+
202
+ controller.signal.addEventListener("abort", () => clearTimeout(timeoutId), {
203
+ once: true,
204
+ });
205
+ });
206
+
207
+ try {
208
+ await Promise.race([
209
+ extractFrames({
210
+ src: "https://remotion.media/video.mp4",
211
+ timestampsInSeconds: [0, 1, 2, 3, 4],
212
+ onVideoSample: (sample) => {
213
+ using frame = sample;
214
+ const canvas = document.createElement("canvas");
215
+ canvas.width = frame.displayWidth;
216
+ canvas.height = frame.displayHeight;
217
+ const ctx = canvas.getContext("2d");
218
+ frame.draw(ctx!, 0, 0);
219
+ },
220
+ signal: controller.signal,
221
+ }),
222
+ timeoutPromise,
223
+ ]);
224
+
225
+ console.log("Frame extraction complete!");
226
+ } catch (error) {
227
+ console.error("Frame extraction was aborted or failed:", error);
228
+ }
229
+ ```
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: fonts
3
+ description: Loading Google Fonts and local fonts in Remotion
4
+ metadata:
5
+ tags: fonts, google-fonts, typography, text
6
+ ---
7
+
8
+ # Using fonts in Remotion
9
+
10
+ ## Google Fonts with @remotion/google-fonts
11
+
12
+ The recommended way to use Google Fonts. It's type-safe and automatically blocks rendering until the font is ready.
13
+
14
+ ### Prerequisites
15
+
16
+ First, the @remotion/google-fonts package needs to be installed.
17
+ If it is not installed, use the following command:
18
+
19
+ ```bash
20
+ npx remotion add @remotion/google-fonts # If project uses npm
21
+ bunx remotion add @remotion/google-fonts # If project uses bun
22
+ yarn remotion add @remotion/google-fonts # If project uses yarn
23
+ pnpm exec remotion add @remotion/google-fonts # If project uses pnpm
24
+ ```
25
+
26
+ ```tsx
27
+ import { loadFont } from "@remotion/google-fonts/Lobster";
28
+
29
+ const { fontFamily } = loadFont();
30
+
31
+ export const MyComposition = () => {
32
+ return <div style={{ fontFamily }}>Hello World</div>;
33
+ };
34
+ ```
35
+
36
+ Preferrably, specify only needed weights and subsets to reduce file size:
37
+
38
+ ```tsx
39
+ import { loadFont } from "@remotion/google-fonts/Roboto";
40
+
41
+ const { fontFamily } = loadFont("normal", {
42
+ weights: ["400", "700"],
43
+ subsets: ["latin"],
44
+ });
45
+ ```
46
+
47
+ ### Waiting for font to load
48
+
49
+ Use `waitUntilDone()` if you need to know when the font is ready:
50
+
51
+ ```tsx
52
+ import { loadFont } from "@remotion/google-fonts/Lobster";
53
+
54
+ const { fontFamily, waitUntilDone } = loadFont();
55
+
56
+ await waitUntilDone();
57
+ ```
58
+
59
+ ## Local fonts with @remotion/fonts
60
+
61
+ For local font files, use the `@remotion/fonts` package.
62
+
63
+ ### Prerequisites
64
+
65
+ First, install @remotion/fonts:
66
+
67
+ ```bash
68
+ npx remotion add @remotion/fonts # If project uses npm
69
+ bunx remotion add @remotion/fonts # If project uses bun
70
+ yarn remotion add @remotion/fonts # If project uses yarn
71
+ pnpm exec remotion add @remotion/fonts # If project uses pnpm
72
+ ```
73
+
74
+ ### Loading a local font
75
+
76
+ Place your font file in the `public/` folder and use `loadFont()`:
77
+
78
+ ```tsx
79
+ import { loadFont } from "@remotion/fonts";
80
+ import { staticFile } from "remotion";
81
+
82
+ await loadFont({
83
+ family: "MyFont",
84
+ url: staticFile("MyFont-Regular.woff2"),
85
+ });
86
+
87
+ export const MyComposition = () => {
88
+ return <div style={{ fontFamily: "MyFont" }}>Hello World</div>;
89
+ };
90
+ ```
91
+
92
+ ### Loading multiple weights
93
+
94
+ Load each weight separately with the same family name:
95
+
96
+ ```tsx
97
+ import { loadFont } from "@remotion/fonts";
98
+ import { staticFile } from "remotion";
99
+
100
+ await Promise.all([
101
+ loadFont({
102
+ family: "Inter",
103
+ url: staticFile("Inter-Regular.woff2"),
104
+ weight: "400",
105
+ }),
106
+ loadFont({
107
+ family: "Inter",
108
+ url: staticFile("Inter-Bold.woff2"),
109
+ weight: "700",
110
+ }),
111
+ ]);
112
+ ```
113
+
114
+ ### Available options
115
+
116
+ ```tsx
117
+ loadFont({
118
+ family: "MyFont", // Required: name to use in CSS
119
+ url: staticFile("font.woff2"), // Required: font file URL
120
+ format: "woff2", // Optional: auto-detected from extension
121
+ weight: "400", // Optional: font weight
122
+ style: "normal", // Optional: normal or italic
123
+ display: "block", // Optional: font-display behavior
124
+ });
125
+ ```
126
+
127
+ ## Using in components
128
+
129
+ Call `loadFont()` at the top level of your component or in a separate file that's imported early:
130
+
131
+ ```tsx
132
+ import { loadFont } from "@remotion/google-fonts/Montserrat";
133
+
134
+ const { fontFamily } = loadFont("normal", {
135
+ weights: ["400", "700"],
136
+ subsets: ["latin"],
137
+ });
138
+
139
+ export const Title: React.FC<{ text: string }> = ({ text }) => {
140
+ return (
141
+ <h1
142
+ style={{
143
+ fontFamily,
144
+ fontSize: 80,
145
+ fontWeight: "bold",
146
+ }}
147
+ >
148
+ {text}
149
+ </h1>
150
+ );
151
+ };
152
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: get-audio-duration
3
+ description: Getting the duration of an audio file in seconds with Mediabunny
4
+ metadata:
5
+ tags: duration, audio, length, time, seconds, mp3, wav
6
+ ---
7
+
8
+ # Getting audio duration with Mediabunny
9
+
10
+ Mediabunny can extract the duration of an audio file. It works in browser, Node.js, and Bun environments.
11
+
12
+ ## Getting audio duration
13
+
14
+ ```tsx
15
+ import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
16
+
17
+ export const getAudioDuration = async (src: string) => {
18
+ const input = new Input({
19
+ formats: ALL_FORMATS,
20
+ source: new UrlSource(src, {
21
+ getRetryDelay: () => null,
22
+ }),
23
+ });
24
+
25
+ const durationInSeconds = await input.computeDuration();
26
+ return durationInSeconds;
27
+ };
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```tsx
33
+ const duration = await getAudioDuration("https://remotion.media/audio.mp3");
34
+ console.log(duration); // e.g. 180.5 (seconds)
35
+ ```
36
+
37
+ ## Using with local files
38
+
39
+ For local files, use `FileSource` instead of `UrlSource`:
40
+
41
+ ```tsx
42
+ import { Input, ALL_FORMATS, FileSource } from "mediabunny";
43
+
44
+ const input = new Input({
45
+ formats: ALL_FORMATS,
46
+ source: new FileSource(file), // File object from input or drag-drop
47
+ });
48
+
49
+ const durationInSeconds = await input.computeDuration();
50
+ ```
51
+
52
+ ## Using with staticFile in Remotion
53
+
54
+ ```tsx
55
+ import { staticFile } from "remotion";
56
+
57
+ const duration = await getAudioDuration(staticFile("audio.mp3"));
58
+ ```
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: get-video-dimensions
3
+ description: Getting the width and height of a video file with Mediabunny
4
+ metadata:
5
+ tags: dimensions, width, height, resolution, size, video
6
+ ---
7
+
8
+ # Getting video dimensions with Mediabunny
9
+
10
+ Mediabunny can extract the width and height of a video file. It works in browser, Node.js, and Bun environments.
11
+
12
+ ## Getting video dimensions
13
+
14
+ ```tsx
15
+ import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
16
+
17
+ export const getVideoDimensions = async (src: string) => {
18
+ const input = new Input({
19
+ formats: ALL_FORMATS,
20
+ source: new UrlSource(src, {
21
+ getRetryDelay: () => null,
22
+ }),
23
+ });
24
+
25
+ const videoTrack = await input.getPrimaryVideoTrack();
26
+ if (!videoTrack) {
27
+ throw new Error("No video track found");
28
+ }
29
+
30
+ return {
31
+ width: videoTrack.displayWidth,
32
+ height: videoTrack.displayHeight,
33
+ };
34
+ };
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ```tsx
40
+ const dimensions = await getVideoDimensions("https://remotion.media/video.mp4");
41
+ console.log(dimensions.width); // e.g. 1920
42
+ console.log(dimensions.height); // e.g. 1080
43
+ ```
44
+
45
+ ## Using with local files
46
+
47
+ For local files, use `FileSource` instead of `UrlSource`:
48
+
49
+ ```tsx
50
+ import { Input, ALL_FORMATS, FileSource } from "mediabunny";
51
+
52
+ const input = new Input({
53
+ formats: ALL_FORMATS,
54
+ source: new FileSource(file), // File object from input or drag-drop
55
+ });
56
+
57
+ const videoTrack = await input.getPrimaryVideoTrack();
58
+ const width = videoTrack.displayWidth;
59
+ const height = videoTrack.displayHeight;
60
+ ```
61
+
62
+ ## Using with staticFile in Remotion
63
+
64
+ ```tsx
65
+ import { staticFile } from "remotion";
66
+
67
+ const dimensions = await getVideoDimensions(staticFile("video.mp4"));
68
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: get-video-duration
3
+ description: Getting the duration of a video file in seconds with Mediabunny
4
+ metadata:
5
+ tags: duration, video, length, time, seconds
6
+ ---
7
+
8
+ # Getting video duration with Mediabunny
9
+
10
+ Mediabunny can extract the duration of a video file. It works in browser, Node.js, and Bun environments.
11
+
12
+ ## Getting video duration
13
+
14
+ ```tsx
15
+ import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
16
+
17
+ export const getVideoDuration = async (src: string) => {
18
+ const input = new Input({
19
+ formats: ALL_FORMATS,
20
+ source: new UrlSource(src, {
21
+ getRetryDelay: () => null,
22
+ }),
23
+ });
24
+
25
+ const durationInSeconds = await input.computeDuration();
26
+ return durationInSeconds;
27
+ };
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```tsx
33
+ const duration = await getVideoDuration("https://remotion.media/video.mp4");
34
+ console.log(duration); // e.g. 10.5 (seconds)
35
+ ```
36
+
37
+ ## Using with local files
38
+
39
+ For local files, use `FileSource` instead of `UrlSource`:
40
+
41
+ ```tsx
42
+ import { Input, ALL_FORMATS, FileSource } from "mediabunny";
43
+
44
+ const input = new Input({
45
+ formats: ALL_FORMATS,
46
+ source: new FileSource(file), // File object from input or drag-drop
47
+ });
48
+
49
+ const durationInSeconds = await input.computeDuration();
50
+ ```
51
+
52
+ ## Using with staticFile in Remotion
53
+
54
+ ```tsx
55
+ import { staticFile } from "remotion";
56
+
57
+ const duration = await getVideoDuration(staticFile("video.mp4"));
58
+ ```
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: gif
3
+ description: Displaying GIFs, APNG, AVIF and WebP in Remotion
4
+ metadata:
5
+ tags: gif, animation, images, animated, apng, avif, webp
6
+ ---
7
+
8
+ # Using Animated images in Remotion
9
+
10
+ ## Basic usage
11
+
12
+ Use `<AnimatedImage>` to display a GIF, APNG, AVIF or WebP image synchronized with Remotion's timeline:
13
+
14
+ ```tsx
15
+ import {AnimatedImage, staticFile} from 'remotion';
16
+
17
+ export const MyComposition = () => {
18
+ return <AnimatedImage src={staticFile('animation.gif')} width={500} height={500} />;
19
+ };
20
+ ```
21
+
22
+ Remote URLs are also supported (must have CORS enabled):
23
+
24
+ ```tsx
25
+ <AnimatedImage src="https://example.com/animation.gif" width={500} height={500} />
26
+ ```
27
+
28
+ ## Sizing and fit
29
+
30
+ Control how the image fills its container with the `fit` prop:
31
+
32
+ ```tsx
33
+ // Stretch to fill (default)
34
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="fill" />
35
+
36
+ // Maintain aspect ratio, fit inside container
37
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="contain" />
38
+
39
+ // Fill container, crop if needed
40
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={300} fit="cover" />
41
+ ```
42
+
43
+ ## Playback speed
44
+
45
+ Use `playbackRate` to control the animation speed:
46
+
47
+ ```tsx
48
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={500} playbackRate={2} /> {/* 2x speed */}
49
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={500} playbackRate={0.5} /> {/* Half speed */}
50
+ ```
51
+
52
+ ## Looping behavior
53
+
54
+ Control what happens when the animation finishes:
55
+
56
+ ```tsx
57
+ // Loop indefinitely (default)
58
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="loop" />
59
+
60
+ // Play once, show final frame
61
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="pause-after-finish" />
62
+
63
+ // Play once, then clear canvas
64
+ <AnimatedImage src={staticFile("animation.gif")} width={500} height={500} loopBehavior="clear-after-finish" />
65
+ ```
66
+
67
+ ## Styling
68
+
69
+ Use the `style` prop for additional CSS (use `width` and `height` props for sizing):
70
+
71
+ ```tsx
72
+ <AnimatedImage
73
+ src={staticFile('animation.gif')}
74
+ width={500}
75
+ height={500}
76
+ style={{
77
+ borderRadius: 20,
78
+ position: 'absolute',
79
+ top: 100,
80
+ left: 50,
81
+ }}
82
+ />
83
+ ```
84
+
85
+ ## Getting GIF duration
86
+
87
+ Use `getGifDurationInSeconds()` from `@remotion/gif` to get the duration of a GIF.
88
+
89
+ ```bash
90
+ npx remotion add @remotion/gif # If project uses npm
91
+ bunx remotion add @remotion/gif # If project uses bun
92
+ yarn remotion add @remotion/gif # If project uses yarn
93
+ pnpm exec remotion add @remotion/gif # If project uses pnpm
94
+ ```
95
+
96
+ ```tsx
97
+ import {getGifDurationInSeconds} from '@remotion/gif';
98
+ import {staticFile} from 'remotion';
99
+
100
+ const duration = await getGifDurationInSeconds(staticFile('animation.gif'));
101
+ console.log(duration); // e.g. 2.5
102
+ ```
103
+
104
+ This is useful for setting the composition duration to match the GIF:
105
+
106
+ ```tsx
107
+ import {getGifDurationInSeconds} from '@remotion/gif';
108
+ import {staticFile, CalculateMetadataFunction} from 'remotion';
109
+
110
+ const calculateMetadata: CalculateMetadataFunction = async () => {
111
+ const duration = await getGifDurationInSeconds(staticFile('animation.gif'));
112
+ return {
113
+ durationInFrames: Math.ceil(duration * 30),
114
+ };
115
+ };
116
+ ```
117
+
118
+ ## Alternative
119
+
120
+ If `<AnimatedImage>` does not work (only supported in Chrome and Firefox), you can use `<Gif>` from `@remotion/gif` instead.
121
+
122
+ ```bash
123
+ npx remotion add @remotion/gif # If project uses npm
124
+ bunx remotion add @remotion/gif # If project uses bun
125
+ yarn remotion add @remotion/gif # If project uses yarn
126
+ pnpm exec remotion add @remotion/gif # If project uses pnpm
127
+ ```
128
+
129
+ ```tsx
130
+ import {Gif} from '@remotion/gif';
131
+ import {staticFile} from 'remotion';
132
+
133
+ export const MyComposition = () => {
134
+ return <Gif src={staticFile('animation.gif')} width={500} height={500} />;
135
+ };
136
+ ```
137
+
138
+ The `<Gif>` component has the same props as `<AnimatedImage>` but only supports GIF files.