@vfrey/vfrey 0.0.1 → 1.0.0-beta.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 (610) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +78 -3
  3. package/accounts.example.json +61 -0
  4. package/accounts.first-run.json +41 -0
  5. package/bin/vfrey.mjs +36 -0
  6. package/integration-tools/README.md +43 -0
  7. package/integration-tools/image/pillow.md +32 -0
  8. package/integration-tools/image/playwright.md +33 -0
  9. package/integration-tools/image/resvg.md +36 -0
  10. package/integration-tools/image/satori.md +36 -0
  11. package/integration-tools/image/sharp.md +38 -0
  12. package/integration-tools/video/blender.md +34 -0
  13. package/integration-tools/video/ffmpeg.md +41 -0
  14. package/integration-tools/video/manim.md +37 -0
  15. package/integration-tools/video/motion-canvas.md +37 -0
  16. package/integration-tools/video/remotion.md +50 -0
  17. package/integration-tools/video/revideo.md +32 -0
  18. package/package.json +74 -6
  19. package/skills/vfrey-orchestrator/SKILL.md +15 -0
  20. package/skills/vfrey-orchestrator/channel-video/SKILL.md +41 -0
  21. package/skills/vfrey-product/SKILL.md +63 -0
  22. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-one.svg +14 -0
  23. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-two.svg +22 -0
  24. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/index.html +70 -0
  25. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-one.svg +14 -0
  26. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-two.svg +22 -0
  27. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/index.tsx +49 -0
  28. package/skills/vfrey-product/examples/concurrency-vs-parallelism/script.json +15 -0
  29. package/skills/vfrey-product/examples/octopus-facts/index.html +60 -0
  30. package/skills/vfrey-product/examples/octopus-facts/octopus.svg +8 -0
  31. package/skills/vfrey-product/examples/octopus-facts/script.json +14 -0
  32. package/skills/vfrey-product/push/SKILL.md +15 -0
  33. package/skills/vfrey-product/scenes/NOTICE +5 -0
  34. package/skills/vfrey-product/scenes/blocks.md +57 -0
  35. package/skills/vfrey-product/scenes/craft.md +118 -0
  36. package/skills/vfrey-product/scenes/motion.md +88 -0
  37. package/src/analytics/dashboard.ts +109 -0
  38. package/src/analytics/index.ts +260 -0
  39. package/src/api/client.ts +361 -0
  40. package/src/api/cloud-files.ts +197 -0
  41. package/src/api/cloud-runs.ts +75 -0
  42. package/src/api/cloud.ts +413 -0
  43. package/src/api/commands.ts +330 -0
  44. package/src/api/config.ts +34 -0
  45. package/src/api/creators.ts +463 -0
  46. package/src/api/credentials.ts +152 -0
  47. package/src/api/mail.ts +333 -0
  48. package/src/api/topics.ts +207 -0
  49. package/src/api/types.ts +273 -0
  50. package/src/cli.ts +468 -0
  51. package/src/cloud/bundle.ts +70 -0
  52. package/src/cloud/cloudrun-executor.ts +237 -0
  53. package/src/cloud/executor.ts +281 -0
  54. package/src/cloud/gcs-sign.ts +76 -0
  55. package/src/cloud/job.ts +106 -0
  56. package/src/cloud/remote-job.ts +67 -0
  57. package/src/cloud/render-job.ts +191 -0
  58. package/src/config.ts +309 -0
  59. package/src/dashboard-link.ts +180 -0
  60. package/src/dashboard-start.ts +103 -0
  61. package/src/desk/channel.ts +64 -0
  62. package/src/desk/cli.ts +216 -0
  63. package/src/desk/creators-route.ts +129 -0
  64. package/src/desk/fonts/JetBrainsMono-OFL.txt +93 -0
  65. package/src/desk/fonts/google-sans-flex-latin.woff2 +0 -0
  66. package/src/desk/fonts/jetbrains-mono-medium.woff2 +0 -0
  67. package/src/desk/http.ts +460 -0
  68. package/src/desk/mail-route.ts +103 -0
  69. package/src/desk/overlay.ts +112 -0
  70. package/src/desk/preview.ts +422 -0
  71. package/src/desk/screens.ts +149 -0
  72. package/src/desk/secrets.ts +143 -0
  73. package/src/desk/series.ts +127 -0
  74. package/src/desk/state.ts +77 -0
  75. package/src/desk/studio-route.ts +119 -0
  76. package/src/desk/tick-runner.ts +66 -0
  77. package/src/desk/tick.ts +56 -0
  78. package/src/desk/topics-route.ts +41 -0
  79. package/src/desk/ui/app.css +505 -0
  80. package/src/desk/ui/app.js +185 -0
  81. package/src/desk/ui/apple-icon.png +0 -0
  82. package/src/desk/ui/components.js +79 -0
  83. package/src/desk/ui/core.js +156 -0
  84. package/src/desk/ui/favicon.ico +0 -0
  85. package/src/desk/ui/icon.svg +1 -0
  86. package/src/desk/ui/icons.js +49 -0
  87. package/src/desk/ui/index.html +41 -0
  88. package/src/desk/ui/metrics-math.d.ts +22 -0
  89. package/src/desk/ui/metrics-math.js +135 -0
  90. package/src/desk/ui/theme.js +5 -0
  91. package/src/desk/ui/views-creators.js +209 -0
  92. package/src/desk/ui/views-keys.js +114 -0
  93. package/src/desk/ui/views-mail.js +188 -0
  94. package/src/desk/ui/views-misc.js +123 -0
  95. package/src/desk/ui/views-review.js +119 -0
  96. package/src/desk/ui/views-runs.js +350 -0
  97. package/src/desk/ui/views-screens.js +163 -0
  98. package/src/desk/ui/views-series.js +318 -0
  99. package/src/desk/ui/views-topics.js +87 -0
  100. package/src/desk/verbs.ts +361 -0
  101. package/src/doctor.ts +212 -0
  102. package/src/drain.ts +14 -0
  103. package/src/engage/index.ts +217 -0
  104. package/src/generate/index.ts +110 -0
  105. package/src/generate/script.ts +152 -0
  106. package/src/generate/title.ts +78 -0
  107. package/src/help.ts +252 -0
  108. package/src/home.ts +45 -0
  109. package/src/llm/client.ts +177 -0
  110. package/src/log.ts +7 -0
  111. package/src/oauth/tokens.ts +189 -0
  112. package/src/oauth/vault.ts +72 -0
  113. package/src/pipeline/review.ts +642 -0
  114. package/src/pipeline/run.ts +443 -0
  115. package/src/pipeline/series-guard.ts +26 -0
  116. package/src/pipeline/source-fetch.ts +69 -0
  117. package/src/pipeline/stages.ts +728 -0
  118. package/src/pipeline/topics-source.ts +90 -0
  119. package/src/product/commands.ts +296 -0
  120. package/src/product/config-file.ts +38 -0
  121. package/src/product/engine-choice.ts +89 -0
  122. package/src/product/engines.ts +103 -0
  123. package/src/product/insights.ts +50 -0
  124. package/src/product/keys.ts +67 -0
  125. package/src/product/paths.ts +18 -0
  126. package/src/product/probes.ts +88 -0
  127. package/src/product/push-flow.ts +90 -0
  128. package/src/product/render-video.ts +21 -0
  129. package/src/product/short.ts +62 -0
  130. package/src/product/update.ts +32 -0
  131. package/src/project/canonical.ts +14 -0
  132. package/src/project/commands.ts +177 -0
  133. package/src/project/dashboard-status.ts +28 -0
  134. package/src/project/discover.ts +19 -0
  135. package/src/project/index-file.ts +73 -0
  136. package/src/project/marker.ts +92 -0
  137. package/src/project/migrate.ts +201 -0
  138. package/src/project/names.ts +27 -0
  139. package/src/project/notice.ts +16 -0
  140. package/src/project/open.ts +88 -0
  141. package/src/project/scaffold.ts +112 -0
  142. package/src/project/templates.ts +42 -0
  143. package/src/project/videos.ts +64 -0
  144. package/src/publish/facebook.ts +91 -0
  145. package/src/publish/index.ts +12 -0
  146. package/src/publish/instagram.ts +97 -0
  147. package/src/publish/rate.ts +62 -0
  148. package/src/publish/session.ts +242 -0
  149. package/src/publish/tiktok.ts +202 -0
  150. package/src/publish/youtube.ts +177 -0
  151. package/src/queue/desk-ops.ts +1170 -0
  152. package/src/queue/seal.ts +3 -0
  153. package/src/queue/store.ts +1006 -0
  154. package/src/remotion/AiLabel.tsx +26 -0
  155. package/src/remotion/Root.tsx +73 -0
  156. package/src/remotion/defaults.ts +26 -0
  157. package/src/remotion/films/claude/ClaudeFilm.tsx +1014 -0
  158. package/src/remotion/films/engine/EngineMark.tsx +17 -0
  159. package/src/remotion/films/rea/ReaShort.tsx +552 -0
  160. package/src/remotion/films/rea/drawings.tsx +907 -0
  161. package/src/remotion/films/rea/timing.ts +144 -0
  162. package/src/remotion/index.ts +4 -0
  163. package/src/remotion/templates/EditorialSplit.tsx +39 -0
  164. package/src/remotion/templates/KineticType.tsx +39 -0
  165. package/src/remotion/templates/SignalBoard.tsx +50 -0
  166. package/src/remotion/timing.ts +22 -0
  167. package/src/render/chrome.ts +78 -0
  168. package/src/render/engine-mark.ts +29 -0
  169. package/src/render/framey-template.ts +130 -0
  170. package/src/render/html-engine.ts +149 -0
  171. package/src/render/node-crypto-stub.ts +11 -0
  172. package/src/render/probe.ts +29 -0
  173. package/src/render/props.ts +17 -0
  174. package/src/render/vertical-short.ts +35 -0
  175. package/src/render/webpack.ts +33 -0
  176. package/src/render/worker.ts +65 -0
  177. package/src/scene/assets/fonts/TitanOne-OFL.txt +94 -0
  178. package/src/scene/assets/fonts/titan-one.woff2 +0 -0
  179. package/src/scene/assets/gsap/LICENSE.txt +8 -0
  180. package/src/scene/assets/gsap/gsap.min.js +11 -0
  181. package/src/scene/audio.ts +54 -0
  182. package/src/scene/blocks/LICENSE +190 -0
  183. package/src/scene/blocks/NOTICE +5 -0
  184. package/src/scene/blocks/bar-chart-race/bar-chart-race.html +585 -0
  185. package/src/scene/blocks/beat-freeze-cut/beat-freeze-cut.html +874 -0
  186. package/src/scene/blocks/camcorder-hud/camcorder-hud.html +164 -0
  187. package/src/scene/blocks/camera-dolly-zoom/camera-dolly-zoom.html +355 -0
  188. package/src/scene/blocks/code-diff/code-diff.html +817 -0
  189. package/src/scene/blocks/code-snippet-apple-terminal-pro/code-snippet-apple-terminal-pro.html +248 -0
  190. package/src/scene/blocks/code-typing/code-typing.html +764 -0
  191. package/src/scene/blocks/data-chart/data-chart.html +452 -0
  192. package/src/scene/blocks/flowchart-vertical/flowchart-vertical.html +454 -0
  193. package/src/scene/blocks/hw-scribble-transition/hw-scribble-transition.html +153 -0
  194. package/src/scene/blocks/index.json +824 -0
  195. package/src/scene/blocks/lt-accent-underline/lt-accent-underline.html +107 -0
  196. package/src/scene/blocks/lt-bold-block/lt-bold-block.html +109 -0
  197. package/src/scene/blocks/lt-clean-bar/lt-clean-bar.html +112 -0
  198. package/src/scene/blocks/lt-dark-card/lt-dark-card.html +111 -0
  199. package/src/scene/blocks/lt-kicker-name/lt-kicker-name.html +114 -0
  200. package/src/scene/blocks/lt-mask-reveal/lt-mask-reveal.html +120 -0
  201. package/src/scene/blocks/lt-neon-border/lt-neon-border.html +391 -0
  202. package/src/scene/blocks/lt-stack-bars/lt-stack-bars.html +109 -0
  203. package/src/scene/blocks/macos-notification/macos-notification.html +194 -0
  204. package/src/scene/blocks/mk-background/mk-background.html +236 -0
  205. package/src/scene/blocks/mk-callout-highlight/mk-callout-highlight.html +183 -0
  206. package/src/scene/blocks/mk-clone-wall-transition/mk-clone-wall-transition.html +226 -0
  207. package/src/scene/blocks/mk-line-graph/mk-line-graph.html +293 -0
  208. package/src/scene/blocks/mk-progress-stat/mk-progress-stat.html +186 -0
  209. package/src/scene/blocks/mk-specs-list/mk-specs-list.html +223 -0
  210. package/src/scene/blocks/news-ticker/news-ticker.html +409 -0
  211. package/src/scene/blocks/organic-light-leak-overlay/organic-light-leak-overlay.html +126 -0
  212. package/src/scene/blocks/oscilloscope-trace/oscilloscope-trace.html +519 -0
  213. package/src/scene/blocks/snow/snow.html +205 -0
  214. package/src/scene/blocks/split-flap-board/split-flap-board.html +347 -0
  215. package/src/scene/blocks/spotify-card/spotify-card.html +294 -0
  216. package/src/scene/blocks/starfield/starfield.html +188 -0
  217. package/src/scene/blocks/thread-message-stack/thread-message-stack.html +239 -0
  218. package/src/scene/blocks/week-in-merges/week-in-merges.html +470 -0
  219. package/src/scene/blocks/x-post/x-post.html +437 -0
  220. package/src/scene/blocks/yt-comment-card/yt-comment-card.html +319 -0
  221. package/src/scene/blocks/yt-lcd-background/yt-lcd-background.html +307 -0
  222. package/src/scene/blocks/yt-prism-title/yt-prism-title.html +205 -0
  223. package/src/scene/blocks.ts +229 -0
  224. package/src/scene/command.ts +272 -0
  225. package/src/scene/figure.ts +181 -0
  226. package/src/scene/glyphs.ts +107 -0
  227. package/src/scene/init.ts +86 -0
  228. package/src/scene/inspect/css-tree.d.ts +6 -0
  229. package/src/scene/inspect/page-scripts.ts +272 -0
  230. package/src/scene/inspect/report.ts +405 -0
  231. package/src/scene/inspect/run.ts +200 -0
  232. package/src/scene/inspect/source.ts +236 -0
  233. package/src/scene/label.ts +131 -0
  234. package/src/scene/net-guard.ts +74 -0
  235. package/src/scene/render.ts +292 -0
  236. package/src/scene/runtime/browser.ts +199 -0
  237. package/src/scene/runtime/core.ts +181 -0
  238. package/src/scene/runtime/react.tsx +115 -0
  239. package/src/scene/runtime/transitions.ts +133 -0
  240. package/src/scene/sanitize.ts +181 -0
  241. package/src/scene/scene.ts +152 -0
  242. package/src/scene/studio-command.ts +48 -0
  243. package/src/scene/studio-skin.ts +59 -0
  244. package/src/scene/studio.ts +337 -0
  245. package/src/scene/supply.ts +111 -0
  246. package/src/scene/timing.ts +288 -0
  247. package/src/scene/transitions/LICENSE +190 -0
  248. package/src/scene/transitions/NOTICE +5 -0
  249. package/src/scene/transitions/SOURCE.json +24 -0
  250. package/src/scene/transitions/transitions.global.js +38 -0
  251. package/src/scene/transitions.ts +26 -0
  252. package/src/service/all-projects.ts +153 -0
  253. package/src/service/commands.ts +256 -0
  254. package/src/service/due.ts +82 -0
  255. package/src/service/lock.ts +101 -0
  256. package/src/service/log-file.ts +56 -0
  257. package/src/service/state.ts +41 -0
  258. package/src/service/units.ts +90 -0
  259. package/src/service/worker.ts +51 -0
  260. package/src/skill-agents.ts +74 -0
  261. package/src/skill-install.ts +334 -0
  262. package/src/sync-write.ts +21 -0
  263. package/src/tick-report.ts +205 -0
  264. package/src/tts.ts +124 -0
  265. package/vendor/@vfrey/contracts/dist/account.d.ts +97 -0
  266. package/vendor/@vfrey/contracts/dist/account.js +27 -0
  267. package/vendor/@vfrey/contracts/dist/checks.d.ts +8 -0
  268. package/vendor/@vfrey/contracts/dist/checks.js +1 -0
  269. package/vendor/@vfrey/contracts/dist/credentials/crypto.d.ts +4 -0
  270. package/vendor/@vfrey/contracts/dist/credentials/crypto.js +38 -0
  271. package/vendor/@vfrey/contracts/dist/domain/advice-persona.d.ts +10 -0
  272. package/vendor/@vfrey/contracts/dist/domain/advice-persona.js +24 -0
  273. package/vendor/@vfrey/contracts/dist/domain/backoff.d.ts +13 -0
  274. package/vendor/@vfrey/contracts/dist/domain/backoff.js +27 -0
  275. package/vendor/@vfrey/contracts/dist/domain/cadence.d.ts +29 -0
  276. package/vendor/@vfrey/contracts/dist/domain/cadence.js +95 -0
  277. package/vendor/@vfrey/contracts/dist/domain/creators.d.ts +146 -0
  278. package/vendor/@vfrey/contracts/dist/domain/creators.js +2 -0
  279. package/vendor/@vfrey/contracts/dist/domain/disclosure.d.ts +127 -0
  280. package/vendor/@vfrey/contracts/dist/domain/disclosure.js +250 -0
  281. package/vendor/@vfrey/contracts/dist/domain/errors.d.ts +34 -0
  282. package/vendor/@vfrey/contracts/dist/domain/errors.js +68 -0
  283. package/vendor/@vfrey/contracts/dist/domain/redact.d.ts +1 -0
  284. package/vendor/@vfrey/contracts/dist/domain/redact.js +21 -0
  285. package/vendor/@vfrey/contracts/dist/domain/revenue.d.ts +13 -0
  286. package/vendor/@vfrey/contracts/dist/domain/revenue.js +16 -0
  287. package/vendor/@vfrey/contracts/dist/domain/safety.d.ts +20 -0
  288. package/vendor/@vfrey/contracts/dist/domain/safety.js +61 -0
  289. package/vendor/@vfrey/contracts/dist/domain/similarity.d.ts +13 -0
  290. package/vendor/@vfrey/contracts/dist/domain/similarity.js +100 -0
  291. package/vendor/@vfrey/contracts/dist/domain/templates.d.ts +18 -0
  292. package/vendor/@vfrey/contracts/dist/domain/templates.js +67 -0
  293. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.d.ts +19 -0
  294. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.js +52 -0
  295. package/vendor/@vfrey/contracts/dist/domain/topics.d.ts +78 -0
  296. package/vendor/@vfrey/contracts/dist/domain/topics.js +4 -0
  297. package/vendor/@vfrey/contracts/dist/domain/types.d.ts +216 -0
  298. package/vendor/@vfrey/contracts/dist/domain/types.js +1 -0
  299. package/vendor/@vfrey/contracts/dist/domain/variation.d.ts +57 -0
  300. package/vendor/@vfrey/contracts/dist/domain/variation.js +278 -0
  301. package/vendor/@vfrey/contracts/dist/events.d.ts +20 -0
  302. package/vendor/@vfrey/contracts/dist/events.js +1 -0
  303. package/vendor/@vfrey/contracts/dist/http.d.ts +11 -0
  304. package/vendor/@vfrey/contracts/dist/http.js +37 -0
  305. package/vendor/@vfrey/contracts/dist/index.d.ts +22 -0
  306. package/vendor/@vfrey/contracts/dist/index.js +22 -0
  307. package/vendor/@vfrey/contracts/dist/log.d.ts +2 -0
  308. package/vendor/@vfrey/contracts/dist/log.js +10 -0
  309. package/vendor/@vfrey/contracts/dist/mail.d.ts +55 -0
  310. package/vendor/@vfrey/contracts/dist/mail.js +1 -0
  311. package/vendor/@vfrey/contracts/package.json +18 -0
  312. package/vendor/@vfrey/ingest/dist/index.d.ts +41 -0
  313. package/vendor/@vfrey/ingest/dist/index.js +221 -0
  314. package/vendor/@vfrey/ingest/dist/parse.d.ts +5 -0
  315. package/vendor/@vfrey/ingest/dist/parse.js +165 -0
  316. package/vendor/@vfrey/ingest/package.json +21 -0
  317. package/vendor/framey/LICENSE +190 -0
  318. package/vendor/framey/NOTICE +15 -0
  319. package/vendor/framey/SOURCE.json +24 -0
  320. package/vendor/framey/STUDIO-SOURCE.json +9 -0
  321. package/vendor/framey/bin/framey-localize-fonts.mjs +12 -0
  322. package/vendor/framey/bin/framey.mjs +16 -0
  323. package/vendor/framey/dist/add-VMJD5KBS.js +75 -0
  324. package/vendor/framey/dist/animatedGifPrep-QPKGJ6PM.js +43 -0
  325. package/vendor/framey/dist/api.d.ts +211 -0
  326. package/vendor/framey/dist/api.js +76 -0
  327. package/vendor/framey/dist/appHistory-WW56FZTT.js +31 -0
  328. package/vendor/framey/dist/asset-WQKGOELE.js +26 -0
  329. package/vendor/framey/dist/audio-RSJWVWRA.js +1936 -0
  330. package/vendor/framey/dist/batchRender-3HPICDCT.js +366 -0
  331. package/vendor/framey/dist/beats-HL2BDUZI.js +273 -0
  332. package/vendor/framey/dist/benchmark-RWCWHI5Z.js +230 -0
  333. package/vendor/framey/dist/browser-ECYET3Q2.js +206 -0
  334. package/vendor/framey/dist/bundleWithLocalizedFonts-ALYBQEQT.js +52 -0
  335. package/vendor/framey/dist/captureCompositionFrame-4DA6SEH2.js +94 -0
  336. package/vendor/framey/dist/catalog-5JVDEUWK.js +979 -0
  337. package/vendor/framey/dist/catch-up-NEBCL5NO.js +106 -0
  338. package/vendor/framey/dist/check-F5N544ML.js +111 -0
  339. package/vendor/framey/dist/checkBrowser-LZ66CMJG.js +110 -0
  340. package/vendor/framey/dist/chunk-2K7Z2HVP.js +372 -0
  341. package/vendor/framey/dist/chunk-2UZQHDM7.js +323 -0
  342. package/vendor/framey/dist/chunk-2X4PQEYM.js +34 -0
  343. package/vendor/framey/dist/chunk-3422KMTD.js +168 -0
  344. package/vendor/framey/dist/chunk-3FYD4YEK.js +72 -0
  345. package/vendor/framey/dist/chunk-3GXQPCJC.js +682 -0
  346. package/vendor/framey/dist/chunk-3LM6YPBR.js +179 -0
  347. package/vendor/framey/dist/chunk-442JNXRM.js +20 -0
  348. package/vendor/framey/dist/chunk-4BNN5FGX.js +182 -0
  349. package/vendor/framey/dist/chunk-4P7NX5BM.js +11532 -0
  350. package/vendor/framey/dist/chunk-4UMPIPCQ.js +88 -0
  351. package/vendor/framey/dist/chunk-4YYJOFKS.js +28 -0
  352. package/vendor/framey/dist/chunk-54HJ63Q2.js +29 -0
  353. package/vendor/framey/dist/chunk-5ETJX6WM.js +89 -0
  354. package/vendor/framey/dist/chunk-5SG54JRS.js +68 -0
  355. package/vendor/framey/dist/chunk-634HSJ3J.js +58 -0
  356. package/vendor/framey/dist/chunk-66LREXGS.js +48 -0
  357. package/vendor/framey/dist/chunk-6BEFEWFB.js +25 -0
  358. package/vendor/framey/dist/chunk-6BNTGNGD.js +286 -0
  359. package/vendor/framey/dist/chunk-6DDPOHMK.js +140 -0
  360. package/vendor/framey/dist/chunk-6GV5XSOR.js +214 -0
  361. package/vendor/framey/dist/chunk-6JR2XUEE.js +127 -0
  362. package/vendor/framey/dist/chunk-73QVATIM.js +362 -0
  363. package/vendor/framey/dist/chunk-7FMUTGOH.js +279 -0
  364. package/vendor/framey/dist/chunk-7JQFJ6JJ.js +291 -0
  365. package/vendor/framey/dist/chunk-AHPGAESX.js +113 -0
  366. package/vendor/framey/dist/chunk-AHX34EFP.js +15 -0
  367. package/vendor/framey/dist/chunk-AJ5CSAEZ.js +487 -0
  368. package/vendor/framey/dist/chunk-B7RJV74O.js +5047 -0
  369. package/vendor/framey/dist/chunk-BL4U6U52.js +254 -0
  370. package/vendor/framey/dist/chunk-BSQ7XANM.js +210 -0
  371. package/vendor/framey/dist/chunk-BZ56MTDX.js +6 -0
  372. package/vendor/framey/dist/chunk-C5BO7PMT.js +282 -0
  373. package/vendor/framey/dist/chunk-CFUCHO4T.js +358 -0
  374. package/vendor/framey/dist/chunk-CZGHFATT.js +31 -0
  375. package/vendor/framey/dist/chunk-DLA44CMS.js +5649 -0
  376. package/vendor/framey/dist/chunk-DPVXBVLL.js +31292 -0
  377. package/vendor/framey/dist/chunk-DQBY7FRR.js +397 -0
  378. package/vendor/framey/dist/chunk-EAMLBAHA.js +154 -0
  379. package/vendor/framey/dist/chunk-EOVYQ3IG.js +143 -0
  380. package/vendor/framey/dist/chunk-EVMY7IPL.js +612 -0
  381. package/vendor/framey/dist/chunk-FG4BBFZI.js +122 -0
  382. package/vendor/framey/dist/chunk-FI4I7CME.js +56 -0
  383. package/vendor/framey/dist/chunk-FLREUEHW.js +2081 -0
  384. package/vendor/framey/dist/chunk-FUFP7A7S.js +1126 -0
  385. package/vendor/framey/dist/chunk-FV3PIKGH.js +56 -0
  386. package/vendor/framey/dist/chunk-FXMKHHPO.js +123 -0
  387. package/vendor/framey/dist/chunk-GGZAM5VH.js +1187 -0
  388. package/vendor/framey/dist/chunk-GKZEVJIB.js +39 -0
  389. package/vendor/framey/dist/chunk-GMECXFAN.js +57 -0
  390. package/vendor/framey/dist/chunk-GNEFDLFB.js +621 -0
  391. package/vendor/framey/dist/chunk-GPMLSOEG.js +19274 -0
  392. package/vendor/framey/dist/chunk-GPYVT5EE.js +59 -0
  393. package/vendor/framey/dist/chunk-H6IEMZEV.js +40 -0
  394. package/vendor/framey/dist/chunk-HEFQCIXR.js +170 -0
  395. package/vendor/framey/dist/chunk-HFQ4CWHA.js +118 -0
  396. package/vendor/framey/dist/chunk-HPDTCOKE.js +304 -0
  397. package/vendor/framey/dist/chunk-HTUHQKDB.js +548 -0
  398. package/vendor/framey/dist/chunk-HU2SPFNG.js +103 -0
  399. package/vendor/framey/dist/chunk-HVW7ABXD.js +19 -0
  400. package/vendor/framey/dist/chunk-IG7NDKXO.js +26 -0
  401. package/vendor/framey/dist/chunk-II3J3WXK.js +246 -0
  402. package/vendor/framey/dist/chunk-IR35BCLK.js +13 -0
  403. package/vendor/framey/dist/chunk-ISN5GRYI.js +20 -0
  404. package/vendor/framey/dist/chunk-IUONB55J.js +669 -0
  405. package/vendor/framey/dist/chunk-IVSUQR2B.js +161 -0
  406. package/vendor/framey/dist/chunk-IXU6PQSW.js +259 -0
  407. package/vendor/framey/dist/chunk-IZCW2NKT.js +29 -0
  408. package/vendor/framey/dist/chunk-JGXJU5PF.js +68 -0
  409. package/vendor/framey/dist/chunk-JHOCK3DG.js +27 -0
  410. package/vendor/framey/dist/chunk-JVBRJMOP.js +121 -0
  411. package/vendor/framey/dist/chunk-K4MJX7SR.js +17 -0
  412. package/vendor/framey/dist/chunk-K4WKGXRC.js +18 -0
  413. package/vendor/framey/dist/chunk-KGPLIH7B.js +127 -0
  414. package/vendor/framey/dist/chunk-KLIKCX6Q.js +63 -0
  415. package/vendor/framey/dist/chunk-KXTKKBOC.js +61 -0
  416. package/vendor/framey/dist/chunk-KZI44OPA.js +185 -0
  417. package/vendor/framey/dist/chunk-LEKZNRKI.js +45 -0
  418. package/vendor/framey/dist/chunk-LFGJWOVA.js +61 -0
  419. package/vendor/framey/dist/chunk-LLMSX6V6.js +17 -0
  420. package/vendor/framey/dist/chunk-LTGTN2TH.js +195 -0
  421. package/vendor/framey/dist/chunk-M2WBOQ2Q.js +54 -0
  422. package/vendor/framey/dist/chunk-MI5FTLYK.js +399 -0
  423. package/vendor/framey/dist/chunk-MLQP2QUF.js +1809 -0
  424. package/vendor/framey/dist/chunk-MMQ52NIZ.js +956 -0
  425. package/vendor/framey/dist/chunk-ND46XKK3.js +742 -0
  426. package/vendor/framey/dist/chunk-NYEXNSHM.js +504 -0
  427. package/vendor/framey/dist/chunk-O4YRB27L.js +57 -0
  428. package/vendor/framey/dist/chunk-O7BGSQ5F.js +92 -0
  429. package/vendor/framey/dist/chunk-OFQWTKPW.js +117 -0
  430. package/vendor/framey/dist/chunk-P5ZBLXJ6.js +91 -0
  431. package/vendor/framey/dist/chunk-P6LJ4Y32.js +4662 -0
  432. package/vendor/framey/dist/chunk-PKZ7RK5N.js +281 -0
  433. package/vendor/framey/dist/chunk-PURHAXFL.js +15 -0
  434. package/vendor/framey/dist/chunk-Q5X2B5WT.js +29 -0
  435. package/vendor/framey/dist/chunk-QAMKOG67.js +248 -0
  436. package/vendor/framey/dist/chunk-R6YBK4XX.js +514 -0
  437. package/vendor/framey/dist/chunk-RGLQURIX.js +2997 -0
  438. package/vendor/framey/dist/chunk-RNV3DM4S.js +3573 -0
  439. package/vendor/framey/dist/chunk-ROEW726S.js +4638 -0
  440. package/vendor/framey/dist/chunk-RQVDTPGD.js +6 -0
  441. package/vendor/framey/dist/chunk-RVZHGOGR.js +26 -0
  442. package/vendor/framey/dist/chunk-RXATE6FZ.js +385 -0
  443. package/vendor/framey/dist/chunk-S3S4TGEH.js +424 -0
  444. package/vendor/framey/dist/chunk-SDYDNHEE.js +11202 -0
  445. package/vendor/framey/dist/chunk-SSWBU67I.js +173 -0
  446. package/vendor/framey/dist/chunk-ST35C4K6.js +28 -0
  447. package/vendor/framey/dist/chunk-SZNTYTIV.js +990 -0
  448. package/vendor/framey/dist/chunk-T2EUWCJE.js +29 -0
  449. package/vendor/framey/dist/chunk-T6AGUTZJ.js +444 -0
  450. package/vendor/framey/dist/chunk-THJALHFJ.js +11131 -0
  451. package/vendor/framey/dist/chunk-TIQB63MX.js +18128 -0
  452. package/vendor/framey/dist/chunk-U242RTCT.js +134 -0
  453. package/vendor/framey/dist/chunk-UJZREAV6.js +3901 -0
  454. package/vendor/framey/dist/chunk-UMD3V7CU.js +264 -0
  455. package/vendor/framey/dist/chunk-UOFAE5RF.js +42 -0
  456. package/vendor/framey/dist/chunk-UTEIUGAZ.js +29 -0
  457. package/vendor/framey/dist/chunk-VAS6HQX3.js +138 -0
  458. package/vendor/framey/dist/chunk-VC76R6W2.js +27 -0
  459. package/vendor/framey/dist/chunk-VFZ7W5W7.js +226 -0
  460. package/vendor/framey/dist/chunk-VHNLZAE2.js +348 -0
  461. package/vendor/framey/dist/chunk-VMC4WSH5.js +278 -0
  462. package/vendor/framey/dist/chunk-VORQIH64.js +108 -0
  463. package/vendor/framey/dist/chunk-VTXFRIHO.js +186 -0
  464. package/vendor/framey/dist/chunk-W2LGJSEN.js +182 -0
  465. package/vendor/framey/dist/chunk-WKBM7NDG.js +32 -0
  466. package/vendor/framey/dist/chunk-WMQNIQDJ.js +2057 -0
  467. package/vendor/framey/dist/chunk-WN4XZC5F.js +504 -0
  468. package/vendor/framey/dist/chunk-WQ6ZXHFQ.js +133 -0
  469. package/vendor/framey/dist/chunk-X7HBSTCZ.js +53 -0
  470. package/vendor/framey/dist/chunk-X7MTZ4T2.js +6 -0
  471. package/vendor/framey/dist/chunk-XPTOJZJF.js +308 -0
  472. package/vendor/framey/dist/chunk-XT6MXC7A.js +6 -0
  473. package/vendor/framey/dist/chunk-XT7X6QCP.js +6 -0
  474. package/vendor/framey/dist/chunk-XTMDWNEC.js +2820 -0
  475. package/vendor/framey/dist/chunk-XUHOIDKG.js +6 -0
  476. package/vendor/framey/dist/chunk-XX7LTW5Y.js +138 -0
  477. package/vendor/framey/dist/chunk-Y3YGTZEG.js +382 -0
  478. package/vendor/framey/dist/chunk-Y5SBSGN7.js +346 -0
  479. package/vendor/framey/dist/chunk-YCMVI4MZ.js +625 -0
  480. package/vendor/framey/dist/chunk-YOR4CTCE.js +261 -0
  481. package/vendor/framey/dist/chunk-YPRBGITP.js +2748 -0
  482. package/vendor/framey/dist/chunk-ZKDMAOFU.js +32 -0
  483. package/vendor/framey/dist/chunk-ZW6DURPF.js +1318 -0
  484. package/vendor/framey/dist/clean-ZJOGDKDM.js +336 -0
  485. package/vendor/framey/dist/cli.js +439 -0
  486. package/vendor/framey/dist/cloudrun-HGJ3B6ZV.js +767 -0
  487. package/vendor/framey/dist/commands/contrast-audit.browser.js +643 -0
  488. package/vendor/framey/dist/commands/layout-audit.browser.js +2914 -0
  489. package/vendor/framey/dist/commands/motion-sample.browser.js +74 -0
  490. package/vendor/framey/dist/commands/motion-signature.browser.js +475 -0
  491. package/vendor/framey/dist/compare-W7UY3BAZ.js +463 -0
  492. package/vendor/framey/dist/compiler-TM3W6GYF.js +136 -0
  493. package/vendor/framey/dist/component-QF5VGYMU.js +176 -0
  494. package/vendor/framey/dist/compositions-XT3PMNDF.js +238 -0
  495. package/vendor/framey/dist/contactSheet-7W6GYHBQ.js +24 -0
  496. package/vendor/framey/dist/deploy-6FJPWKF2.js +299 -0
  497. package/vendor/framey/dist/destroy-HE2RIPKZ.js +57 -0
  498. package/vendor/framey/dist/deterministicFonts-RADD3BSX.js +50 -0
  499. package/vendor/framey/dist/dist-4S2FGGVY.js +422 -0
  500. package/vendor/framey/dist/dist-BE4B2EZE.js +32 -0
  501. package/vendor/framey/dist/dist-EWXJGN63.js +129 -0
  502. package/vendor/framey/dist/docs-VKIRFEEX.js +131 -0
  503. package/vendor/framey/dist/doctor-2UNJ2G7U.js +74 -0
  504. package/vendor/framey/dist/dom-37K6YOH4.js +14 -0
  505. package/vendor/framey/dist/dotEnv-7PZQTVIM.js +54 -0
  506. package/vendor/framey/dist/events-ACY3P2PA.js +76 -0
  507. package/vendor/framey/dist/events-IHB3B2MK.js +69 -0
  508. package/vendor/framey/dist/ffmpeg-DR5LGGSK.js +63 -0
  509. package/vendor/framey/dist/figma-BODVUPHB.js +63 -0
  510. package/vendor/framey/dist/fontData.generated-NXAOI4GH.js +13 -0
  511. package/vendor/framey/dist/fontLocalizeCli.js +142 -0
  512. package/vendor/framey/dist/gpuPolicy-XLEXORZY.js +49 -0
  513. package/vendor/framey/dist/grade-compare-GAXFQ74C.js +661 -0
  514. package/vendor/framey/dist/gsapParser-IEUSLYDJ.js +2885 -0
  515. package/vendor/framey/dist/gsapParserAcorn-LZJKCFQI.js +30 -0
  516. package/vendor/framey/dist/help-VCB5X2HS.js +184 -0
  517. package/vendor/framey/dist/history-ENGZEVFT.js +471 -0
  518. package/vendor/framey/dist/hyperframe.manifest.json +22 -0
  519. package/vendor/framey/dist/hyperframe.runtime.iife.js +1132 -0
  520. package/vendor/framey/dist/hyperframes-player.global.js +478 -0
  521. package/vendor/framey/dist/hyperframes-slideshow.global.js +148 -0
  522. package/vendor/framey/dist/info-WPCJHBMU.js +182 -0
  523. package/vendor/framey/dist/init-G4WGLYGD.js +1176 -0
  524. package/vendor/framey/dist/inspect-5IQ6CNEQ.js +106 -0
  525. package/vendor/framey/dist/installer-ML4HWUV7.js +40 -0
  526. package/vendor/framey/dist/keyframes-Q6XJO7VW.js +2755 -0
  527. package/vendor/framey/dist/lambda-A7JC74JF.js +468 -0
  528. package/vendor/framey/dist/layout-YET6XNXA.js +95 -0
  529. package/vendor/framey/dist/lint-I7FZN2VJ.js +162 -0
  530. package/vendor/framey/dist/lintProject-PDB3UN72.js +30 -0
  531. package/vendor/framey/dist/manager-CD6LJ7ZN.js +45 -0
  532. package/vendor/framey/dist/manager-WA4F2GST.js +67 -0
  533. package/vendor/framey/dist/media-treatment-BXYS4WVA.js +1030 -0
  534. package/vendor/framey/dist/media-use-LWH3MANK.js +113 -0
  535. package/vendor/framey/dist/models-K363FYM4.js +195 -0
  536. package/vendor/framey/dist/motionShot-GPAVWXLH.js +640 -0
  537. package/vendor/framey/dist/normalize-FASIPBUM.js +24 -0
  538. package/vendor/framey/dist/normalize-audio-VDWYRHN6.js +268 -0
  539. package/vendor/framey/dist/open-E3TB6P6J.js +128 -0
  540. package/vendor/framey/dist/parakeetRunner-UP34UOI2.js +58 -0
  541. package/vendor/framey/dist/pipeline-VXIUYEBU.js +64 -0
  542. package/vendor/framey/dist/play-BUTDQ4DV.js +353 -0
  543. package/vendor/framey/dist/policies-OLDYGFK5.js +309 -0
  544. package/vendor/framey/dist/preflight-2KZ2GWAZ.js +55 -0
  545. package/vendor/framey/dist/present-GXYSM7NX.js +353 -0
  546. package/vendor/framey/dist/preview-EKZ33JOJ.js +1910 -0
  547. package/vendor/framey/dist/producer-SKU5EV3J.js +13 -0
  548. package/vendor/framey/dist/progress-ZWB4Z4ET.js +76 -0
  549. package/vendor/framey/dist/projectConfig-3MZAYVTS.js +60 -0
  550. package/vendor/framey/dist/publication-DTKWNF74.js +33 -0
  551. package/vendor/framey/dist/remove-background-OY5L7XN2.js +265 -0
  552. package/vendor/framey/dist/render-CDV4GDFX.js +187 -0
  553. package/vendor/framey/dist/render-YE5YAMOD.js +2620 -0
  554. package/vendor/framey/dist/render-batch-ZAMFPCLL.js +274 -0
  555. package/vendor/framey/dist/renderSetupWorker.js +120 -0
  556. package/vendor/framey/dist/resolver-D5BIPSEW.js +42 -0
  557. package/vendor/framey/dist/runtimeVersion.js +18 -0
  558. package/vendor/framey/dist/sam-WFZXI4F7.js +23 -0
  559. package/vendor/framey/dist/shaderTransitionWorker.js +44 -0
  560. package/vendor/framey/dist/sherpa-RQWLV7I3.js +79 -0
  561. package/vendor/framey/dist/sherpaWorker.js +84 -0
  562. package/vendor/framey/dist/sites-AMOVABTK.js +54 -0
  563. package/vendor/framey/dist/skill-ZHVLH7KX.js +15 -0
  564. package/vendor/framey/dist/slideshow-SJGK4RQS.js +24 -0
  565. package/vendor/framey/dist/snapshot-TUXL6LBQ.js +1515 -0
  566. package/vendor/framey/dist/src-JHQGB2S6.js +215 -0
  567. package/vendor/framey/dist/src-Z5PGEMXB.js +532 -0
  568. package/vendor/framey/dist/state-B6H3WHCF.js +28 -0
  569. package/vendor/framey/dist/staticProjectServer-DFVZOUGI.js +63 -0
  570. package/vendor/framey/dist/studio/assets/hyperframes-player-DLaKjw0L.js +478 -0
  571. package/vendor/framey/dist/studio/assets/index-BX3KHhGX.js +71 -0
  572. package/vendor/framey/dist/studio/assets/index-CYbvOVp-.css +1 -0
  573. package/vendor/framey/dist/studio/assets/index-Dp3QEUGL.js +402 -0
  574. package/vendor/framey/dist/studio/assets/index-qrTAXbqc.js +531 -0
  575. package/vendor/framey/dist/studio/favicon.svg +14 -0
  576. package/vendor/framey/dist/studio/icons/timeline/audio.svg +7 -0
  577. package/vendor/framey/dist/studio/icons/timeline/captions.svg +5 -0
  578. package/vendor/framey/dist/studio/icons/timeline/composition.svg +12 -0
  579. package/vendor/framey/dist/studio/icons/timeline/image.svg +18 -0
  580. package/vendor/framey/dist/studio/icons/timeline/music.svg +10 -0
  581. package/vendor/framey/dist/studio/icons/timeline/text.svg +3 -0
  582. package/vendor/framey/dist/studio/index.html +23 -0
  583. package/vendor/framey/dist/studio-api-2NECGRMB.js +179 -0
  584. package/vendor/framey/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
  585. package/vendor/framey/dist/studioServer-N2OPUMOQ.js +1569 -0
  586. package/vendor/framey/dist/synthesize-PKTB5ATG.js +183 -0
  587. package/vendor/framey/dist/system-7F3UEHQT.js +27 -0
  588. package/vendor/framey/dist/telemetry-DQGPEKM6.js +145 -0
  589. package/vendor/framey/dist/telemetry-UN55N6U6.js +77 -0
  590. package/vendor/framey/dist/timeline-LHUUMK63.js +1295 -0
  591. package/vendor/framey/dist/tokens-OLECWDFK.js +92 -0
  592. package/vendor/framey/dist/transcribe-O7HQKMIV.js +331 -0
  593. package/vendor/framey/dist/transcribe-UJESPBT5.js +76 -0
  594. package/vendor/framey/dist/tts-YCCQHZD4.js +234 -0
  595. package/vendor/framey/dist/urlDownloader-H2LXLG4U.js +48 -0
  596. package/vendor/framey/dist/usage-HG4WMM7A.js +2167 -0
  597. package/vendor/framey/dist/validate-F2XMN6EV.js +87 -0
  598. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/GSAP-LICENSE.txt +8 -0
  599. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/CustomEase.min.js +11 -0
  600. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/MotionPathPlugin.min.js +11 -0
  601. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/gsap.min.js +11 -0
  602. package/vendor/framey/dist/warmCheck.js +220 -0
  603. package/vendor/framey/dist/warmCheckClient.js +139 -0
  604. package/vendor/framey/dist/workspaceBuildCheck-XYD2YTFW.js +133 -0
  605. package/vendor/framey-player/LICENSE +190 -0
  606. package/vendor/framey-player/NOTICE +16 -0
  607. package/vendor/framey-player/SOURCE.json +6 -0
  608. package/vendor/framey-player/hyperframes-player.global.js +478 -0
  609. package/vendor/framey.pin +1 -0
  610. package/bin/index.js +0 -3
@@ -0,0 +1,144 @@
1
+ // Measured from the Samantha takes. One shared rate lands the film on 200 words per minute.
2
+ export const playbackRate = 1.1458;
3
+ export const tailPadSeconds = 0.28;
4
+ export const reaDurationInFrames = 2511;
5
+
6
+ export type ReaScene = {
7
+ id: string;
8
+ file: string;
9
+ narration: string;
10
+ wavSeconds: number;
11
+ from: number;
12
+ durationInFrames: number;
13
+ };
14
+
15
+ export const reaScenes: ReaScene[] = [
16
+ {
17
+ "id": "no-source",
18
+ "file": "voice-01.wav",
19
+ "narration": "You love how the search box in Notes works, but you cannot open its source code.",
20
+ "wavSeconds": 4.533,
21
+ "from": 0,
22
+ "durationInFrames": 140
23
+ },
24
+ {
25
+ "id": "meet-rea",
26
+ "file": "voice-02.wav",
27
+ "narration": "Meet R. E. A., the GitHub project that people have starred more than 360,000 times.",
28
+ "wavSeconds": 6.031,
29
+ "from": 140,
30
+ "durationInFrames": 179
31
+ },
32
+ {
33
+ "id": "one-connection",
34
+ "file": "voice-03.wav",
35
+ "narration": "Its line is Reverse Engineer Anything: one connection that lets your coding assistant look through an app.",
36
+ "wavSeconds": 5.559,
37
+ "from": 319,
38
+ "durationInFrames": 167
39
+ },
40
+ {
41
+ "id": "notes-example",
42
+ "file": "voice-04.wav",
43
+ "narration": "Point it at Notes, and it can show you how that search really works.",
44
+ "wavSeconds": 3.912,
45
+ "from": 486,
46
+ "durationInFrames": 124
47
+ },
48
+ {
49
+ "id": "setup-command",
50
+ "file": "voice-05.wav",
51
+ "narration": "To start, type n p x, rea agents, setup.",
52
+ "wavSeconds": 3.995,
53
+ "from": 610,
54
+ "durationInFrames": 126
55
+ },
56
+ {
57
+ "id": "pick-review",
58
+ "file": "voice-06.wav",
59
+ "narration": "Pick your coding assistant, such as Claude Code, Codex, or Cursor, then review the changes.",
60
+ "wavSeconds": 6.361,
61
+ "from": 736,
62
+ "durationInFrames": 188
63
+ },
64
+ {
65
+ "id": "approve-restart",
66
+ "file": "voice-07.wav",
67
+ "narration": "Approve them, restart the assistant, and it is connected.",
68
+ "wavSeconds": 3.504,
69
+ "from": 924,
70
+ "durationInFrames": 113
71
+ },
72
+ {
73
+ "id": "the-ask",
74
+ "file": "voice-08.wav",
75
+ "narration": "Now ask in plain words: understand how search works in Notes, show the proof, and build a similar feature.",
76
+ "wavSeconds": 6.635,
77
+ "from": 1037,
78
+ "durationInFrames": 195
79
+ },
80
+ {
81
+ "id": "stays-local",
82
+ "file": "voice-09.wav",
83
+ "narration": "The looking happens on your computer, and the app is never uploaded.",
84
+ "wavSeconds": 3.763,
85
+ "from": 1232,
86
+ "durationInFrames": 120
87
+ },
88
+ {
89
+ "id": "the-answer",
90
+ "file": "voice-10.wav",
91
+ "narration": "Back comes a plain explanation, the proof behind it, and a note on what could not be proven.",
92
+ "wavSeconds": 5.323,
93
+ "from": 1352,
94
+ "durationInFrames": 161
95
+ },
96
+ {
97
+ "id": "js-lane",
98
+ "file": "voice-11.wav",
99
+ "narration": "If the app is built with JavaScript, you need nothing extra.",
100
+ "wavSeconds": 3.702,
101
+ "from": 1513,
102
+ "durationInFrames": 118
103
+ },
104
+ {
105
+ "id": "compiled-lane",
106
+ "file": "voice-12.wav",
107
+ "narration": "If it is a compiled program, it needs Hopper, Ghidra, or IDA, and setup can offer to install Hopper after you approve.",
108
+ "wavSeconds": 7.626,
109
+ "from": 1631,
110
+ "durationInFrames": 221
111
+ },
112
+ {
113
+ "id": "build-beside-proof",
114
+ "file": "voice-13.wav",
115
+ "narration": "Then a similar search appears in your own project, one you are allowed to ship, beside the proof.",
116
+ "wavSeconds": 5.549,
117
+ "from": 1852,
118
+ "durationInFrames": 167
119
+ },
120
+ {
121
+ "id": "allowed-only",
122
+ "file": "voice-14.wav",
123
+ "narration": "Use it only for research, learning, and software you own or are allowed to examine.",
124
+ "wavSeconds": 4.998,
125
+ "from": 2019,
126
+ "durationInFrames": 152
127
+ },
128
+ {
129
+ "id": "official-only",
130
+ "file": "voice-15.wav",
131
+ "narration": "Get it only from the official GitHub page, morluto slash rea, because lookalike copies are not official.",
132
+ "wavSeconds": 6.414,
133
+ "from": 2171,
134
+ "durationInFrames": 189
135
+ },
136
+ {
137
+ "id": "close",
138
+ "file": "voice-16.wav",
139
+ "narration": "That is R. E. A.: n p x, rea agents, setup, and then ask.",
140
+ "wavSeconds": 4.934,
141
+ "from": 2360,
142
+ "durationInFrames": 151
143
+ }
144
+ ];
@@ -0,0 +1,4 @@
1
+ import { registerRoot } from "remotion";
2
+ import { RemotionRoot } from "./Root.js";
3
+
4
+ registerRoot(RemotionRoot);
@@ -0,0 +1,39 @@
1
+ import { AbsoluteFill, Audio, interpolate, staticFile, useCurrentFrame, useVideoConfig } from "remotion";
2
+ import type { RenderProps } from "@vfrey/contracts";
3
+ import { AiLabel } from "../AiLabel.js";
4
+ import { activeBeat, beatWindows } from "../timing.js";
5
+
6
+ const serif = '"Liberation Serif", Georgia, serif';
7
+ const sans = '"Liberation Sans", Arial, sans-serif';
8
+
9
+ /** Slow magazine split. Serif quote above, body lines below, lower-third caption. */
10
+ export function EditorialSplit(props: RenderProps) {
11
+ const frame = useCurrentFrame();
12
+ const { fps } = useVideoConfig();
13
+ const windows = beatWindows(props.beats, fps);
14
+ const current = activeBeat(windows, frame);
15
+ const local = frame - current.start;
16
+ const rise = interpolate(local, [0, 18], [16, 0], { extrapolateRight: "clamp" });
17
+ const side = props.layoutSeed % 2 === 0 ? "left" : "right";
18
+ return (
19
+ <AbsoluteFill style={{ background: props.palette.background, color: props.palette.foreground, fontFamily: serif }}>
20
+ {props.voiceoverFile ? <Audio src={staticFile(props.voiceoverFile)} /> : null}
21
+ <div style={{ position: "absolute", top: 0, [side]: 0, width: 28, height: "100%", background: props.palette.accent }} />
22
+ <div style={{ position: "absolute", top: 120, left: 88, right: 88 }}>
23
+ <div style={{ fontFamily: sans, letterSpacing: 4, fontSize: 22, textTransform: "uppercase", color: props.palette.muted }}>
24
+ {props.palette.id} / {String(current.index + 1).padStart(2, "0")}
25
+ </div>
26
+ <div style={{ marginTop: 28, fontSize: 78, lineHeight: 0.95, fontWeight: 560 }}>{props.hook}</div>
27
+ </div>
28
+ <div style={{ position: "absolute", left: 88, right: 88, top: 980, bottom: 280, background: props.palette.surface, padding: 36 }}>
29
+ <div style={{ fontFamily: sans, fontSize: 40, lineHeight: 1.25, transform: `translateY(${rise}px)` }}>
30
+ {current.beat.text}
31
+ </div>
32
+ </div>
33
+ <div style={{ position: "absolute", left: 88, right: 88, bottom: 110, borderTop: `2px solid ${props.palette.accent}`, paddingTop: 18, fontFamily: sans, fontSize: 28 }}>
34
+ {current.beat.caption}
35
+ </div>
36
+ <AiLabel />
37
+ </AbsoluteFill>
38
+ );
39
+ }
@@ -0,0 +1,39 @@
1
+ import { AbsoluteFill, Audio, interpolate, staticFile, useCurrentFrame, useVideoConfig } from "remotion";
2
+ import type { RenderProps } from "@vfrey/contracts";
3
+ import { AiLabel } from "../AiLabel.js";
4
+ import { activeBeat, beatWindows } from "../timing.js";
5
+
6
+ const sans = '"Liberation Sans", "Arial Black", Arial, sans-serif';
7
+
8
+ /** Fast, full-bleed type. One claim per cut. Captions are the picture. */
9
+ export function KineticType(props: RenderProps) {
10
+ const frame = useCurrentFrame();
11
+ const { fps } = useVideoConfig();
12
+ const windows = beatWindows(props.beats, fps);
13
+ const current = activeBeat(windows, frame);
14
+ const local = frame - current.start;
15
+ const span = Math.max(1, current.end - current.start);
16
+ const scale = interpolate(local, [0, 8, span], [1.04, 1, 1], { extrapolateRight: "clamp" });
17
+ const bar = interpolate(local, [0, 8], [0, 1], { extrapolateRight: "clamp" });
18
+ const lift = 160 + (props.layoutSeed % 4) * 36;
19
+ const size = current.beat.caption.length > 42 ? 56 : current.beat.caption.length > 18 ? 68 : 84;
20
+ return (
21
+ <AbsoluteFill style={{ background: props.palette.background, color: props.palette.foreground, fontFamily: sans }}>
22
+ {props.voiceoverFile ? <Audio src={staticFile(props.voiceoverFile)} /> : null}
23
+ <div style={{ position: "absolute", top: lift, left: 72, right: 72, height: 18, background: props.palette.surface }}>
24
+ <div style={{ width: `${bar * 100}%`, height: "100%", background: props.palette.accent }} />
25
+ </div>
26
+ <div style={{ position: "absolute", left: 72, right: 72, top: lift + 48, bottom: 220, overflow: "hidden" }}>
27
+ <div style={{ fontSize: size, fontWeight: 800, letterSpacing: -1.5, lineHeight: 0.98, transform: `scale(${scale})`, transformOrigin: "left top", textAlign: "left" }}>
28
+ {current.beat.caption}
29
+ </div>
30
+ </div>
31
+ <div style={{ position: "absolute", left: 72, bottom: 96, display: "flex", gap: 12 }}>
32
+ {windows.map((window) => (
33
+ <div key={window.index} style={{ width: 36, height: 8, background: frame >= window.start ? props.palette.accent : props.palette.muted }} />
34
+ ))}
35
+ </div>
36
+ <AiLabel />
37
+ </AbsoluteFill>
38
+ );
39
+ }
@@ -0,0 +1,50 @@
1
+ import { AbsoluteFill, Audio, interpolate, staticFile, useCurrentFrame, useVideoConfig } from "remotion";
2
+ import type { RenderProps } from "@vfrey/contracts";
3
+ import { AiLabel } from "../AiLabel.js";
4
+ import { activeBeat, beatWindows } from "../timing.js";
5
+
6
+ const mono = '"Liberation Mono", "Courier New", monospace';
7
+
8
+ /** Medium technical board. Index rail, evidence bars, terminal caption chips. */
9
+ export function SignalBoard(props: RenderProps) {
10
+ const frame = useCurrentFrame();
11
+ const { fps } = useVideoConfig();
12
+ const windows = beatWindows(props.beats, fps);
13
+ const current = activeBeat(windows, frame);
14
+ const local = frame - current.start;
15
+ const span = Math.max(1, current.end - current.start);
16
+ const grow = interpolate(local, [0, span * 0.7], [0.08, 0.92], { extrapolateRight: "clamp" });
17
+ const cursor = Math.floor(frame / 15) % 2 === 0 ? "▋" : " ";
18
+ const indexOnRight = props.layoutSeed % 2 === 1;
19
+ return (
20
+ <AbsoluteFill
21
+ style={{
22
+ background: props.palette.background,
23
+ color: props.palette.foreground,
24
+ fontFamily: mono,
25
+ backgroundImage: `linear-gradient(${props.palette.surface} 1px, transparent 1px), linear-gradient(90deg, ${props.palette.surface} 1px, transparent 1px)`,
26
+ backgroundSize: "48px 48px",
27
+ }}
28
+ >
29
+ {props.voiceoverFile ? <Audio src={staticFile(props.voiceoverFile)} /> : null}
30
+ <div style={{ position: "absolute", top: 72, left: 64, right: 64, display: "flex", justifyContent: indexOnRight ? "flex-end" : "flex-start", gap: 22, flexWrap: "wrap" }}>
31
+ {windows.map((window) => (
32
+ <div key={window.index} style={{ color: window.index === current.index ? props.palette.accent : props.palette.muted, fontSize: 26 }}>
33
+ {String(window.index + 1).padStart(2, "0")} {window.beat.role}
34
+ </div>
35
+ ))}
36
+ </div>
37
+ <div style={{ position: "absolute", top: 220, left: 64, right: 64 }}>
38
+ <div style={{ fontSize: 54, lineHeight: 1.15 }}>{current.beat.text}</div>
39
+ <div style={{ marginTop: 48, height: 28, background: props.palette.surface }}>
40
+ <div style={{ width: `${grow * 100}%`, height: "100%", background: props.palette.accent }} />
41
+ </div>
42
+ </div>
43
+ <div style={{ position: "absolute", left: 80, bottom: 140, padding: "16px 20px", background: props.palette.surface, fontSize: 30 }}>
44
+ {current.beat.caption}
45
+ {cursor}
46
+ </div>
47
+ <AiLabel />
48
+ </AbsoluteFill>
49
+ );
50
+ }
@@ -0,0 +1,22 @@
1
+ import type { Beat } from "@vfrey/contracts";
2
+
3
+ export interface BeatWindow {
4
+ beat: Beat;
5
+ start: number;
6
+ end: number;
7
+ index: number;
8
+ }
9
+
10
+ export function beatWindows(beats: Beat[], fps: number): BeatWindow[] {
11
+ let frame = 0;
12
+ return beats.map((beat, index) => {
13
+ const length = Math.max(1, Math.round(beat.seconds * fps));
14
+ const window = { beat, start: frame, end: frame + length, index };
15
+ frame += length;
16
+ return window;
17
+ });
18
+ }
19
+
20
+ export function activeBeat(windows: BeatWindow[], frame: number): BeatWindow {
21
+ return windows.find((window) => frame >= window.start && frame < window.end) ?? windows[windows.length - 1]!;
22
+ }
@@ -0,0 +1,78 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ type Env = Record<string, string | undefined>;
6
+
7
+ export const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
8
+
9
+ /**
10
+ * Where Remotion keeps the Chrome Headless Shell it downloads. This is the rule in @remotion/renderer: the
11
+ * nearest folder at or above the working directory that holds a package.json, then `node_modules/.remotion`.
12
+ */
13
+ export function remotionCacheDir(cwd: string): string {
14
+ let dir: string | undefined = cwd;
15
+ for (;;) {
16
+ if (existsSync(path.join(dir, "package.json"))) return path.join(dir, "node_modules", ".remotion");
17
+ const parent = path.dirname(dir);
18
+ if (parent === dir) return path.resolve(cwd, ".remotion");
19
+ dir = parent;
20
+ }
21
+ }
22
+
23
+ /** The cached Chrome Headless Shell executable, or null when the first render would still download it. */
24
+ export function cachedHeadlessShell(cwd: string): string | null {
25
+ const root = path.join(remotionCacheDir(cwd), "chrome-headless-shell");
26
+ let platforms: string[] = [];
27
+ try {
28
+ platforms = readdirSync(root);
29
+ } catch {
30
+ return null;
31
+ }
32
+ for (const platform of platforms) {
33
+ // The cache also holds a VERSION file next to the platform folders.
34
+ let folders: string[] = [];
35
+ try {
36
+ folders = readdirSync(path.join(root, platform));
37
+ } catch {
38
+ continue;
39
+ }
40
+ for (const folder of folders) {
41
+ if (!folder.startsWith("chrome-headless-shell-")) continue;
42
+ for (const name of ["headless_shell", "chrome-headless-shell", "chrome-headless-shell.exe"]) {
43
+ const file = path.join(root, platform, folder, name);
44
+ if (existsSync(file)) return file;
45
+ }
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+
51
+ /**
52
+ * The Chrome Headless Shell the HTML engines use: one the person named, else the one Remotion cached for the
53
+ * working folder or for this package. Both engines then share one download.
54
+ */
55
+ export function resolveHeadlessShell(env: Env, cwd: string = process.cwd()): string | null {
56
+ for (const name of ["PRODUCER_HEADLESS_SHELL_PATH", "HYPERFRAMES_BROWSER_PATH"]) {
57
+ const named = env[name];
58
+ if (named && existsSync(named)) return named;
59
+ }
60
+ return cachedHeadlessShell(cwd) ?? cachedHeadlessShell(PACKAGE_ROOT);
61
+ }
62
+
63
+ /**
64
+ * True when the first Framey render would still download Chrome Headless Shell. `VFREY_TEST_CHROME_MISSING`
65
+ * is a test hook: it makes the shell count as missing without touching the real cache.
66
+ */
67
+ export function headlessShellMissing(env: Env, cwd: string = process.cwd()): boolean {
68
+ if (env.VFREY_TEST_CHROME_MISSING) return true;
69
+ return resolveHeadlessShell(env, cwd) === null;
70
+ }
71
+
72
+ /** True when `command` is an executable file in one of the PATH folders. */
73
+ export function onPath(command: string, env: Env): boolean {
74
+ for (const dir of (env.PATH ?? "").split(path.delimiter)) {
75
+ if (dir && existsSync(path.join(dir, command))) return true;
76
+ }
77
+ return false;
78
+ }
@@ -0,0 +1,29 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { withJsExtensions } from "./webpack.js";
4
+
5
+ /** Short local render used by the product entry. Same renderer as the worker. */
6
+ export async function renderRemotionMark(outputPath: string, label: string, port = 4219): Promise<void> {
7
+ await mkdir(path.dirname(outputPath), { recursive: true });
8
+ const { bundle } = await import("@remotion/bundler");
9
+ const { renderMedia, selectComposition } = await import("@remotion/renderer");
10
+ const serveUrl = await bundle({
11
+ entryPoint: path.resolve("src/remotion/index.ts"),
12
+ webpackOverride: withJsExtensions,
13
+ });
14
+ const inputProps = { label };
15
+ const composition = await selectComposition({
16
+ serveUrl,
17
+ id: "EngineMark",
18
+ inputProps,
19
+ port,
20
+ });
21
+ await renderMedia({
22
+ composition,
23
+ serveUrl,
24
+ codec: "h264",
25
+ outputLocation: outputPath,
26
+ inputProps,
27
+ port,
28
+ });
29
+ }
@@ -0,0 +1,130 @@
1
+ import type { RenderProps } from "@vfrey/contracts";
2
+
3
+ /** The six colors of the vfrey look. Square corners, monospace accents. */
4
+ export const FRAMEY_PALETTE = {
5
+ black: "#000000",
6
+ white: "#FFFFFF",
7
+ ice: "#E3F2FD",
8
+ sky: "#90CAF9",
9
+ blue: "#2196F3",
10
+ navy: "#0D47A1",
11
+ } as const;
12
+
13
+ export const DISCLOSURE_LABEL = "AI-GENERATED";
14
+
15
+ export const FRAMEY_FRAME = { width: 1080, height: 1920, fps: 30 } as const;
16
+
17
+ function escapeHtml(text: string): string {
18
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
19
+ }
20
+
21
+ function num(value: number): string {
22
+ return String(Math.round(value * 1000) / 1000);
23
+ }
24
+
25
+ /**
26
+ * The Framey (HTML + GSAP) version of the KineticType template: full-bleed type, one claim per cut, a
27
+ * progress bar per beat, beat ticks along the bottom, and the burned-in AI disclosure label.
28
+ * Every visible thing is a function of timeline time, so a render is repeatable.
29
+ */
30
+ export function kineticTypeHtml(props: RenderProps, voiceFile: string | null): string {
31
+ const p = FRAMEY_PALETTE;
32
+ let start = 0;
33
+ const windows = props.beats.map((beat, index) => {
34
+ const seconds = Math.max(1 / FRAMEY_FRAME.fps, beat.seconds);
35
+ const window = { beat, index, start, seconds };
36
+ start += seconds;
37
+ return window;
38
+ });
39
+ const total = Math.max(1, props.durationSec > 0 ? props.durationSec : start);
40
+ const lift = 160 + (props.layoutSeed % 4) * 36;
41
+ const count = windows.length;
42
+
43
+ const slides = windows
44
+ .map((w) => {
45
+ const caption = w.beat.caption;
46
+ const size = caption.length > 42 ? 56 : caption.length > 18 ? 68 : 84;
47
+ const index = String(w.index + 1).padStart(2, "0");
48
+ return ` <div id="beat-${w.index}" class="clip beat" data-start="${num(w.start)}" data-duration="${num(w.seconds)}" data-track-index="1">
49
+ <div class="meta">${index}/${String(count).padStart(2, "0")} // ${escapeHtml(w.beat.role.toUpperCase())}</div>
50
+ <div id="text-${w.index}" class="caption" style="font-size:${size}px">${escapeHtml(caption)}</div>
51
+ </div>`;
52
+ })
53
+ .join("\n");
54
+ const ticks = windows.map((w) => ` <div id="tick-${w.index}" class="tick"></div>`).join("\n");
55
+ const audio = voiceFile
56
+ ? ` <audio id="voice" src="${escapeHtml(voiceFile)}" data-start="0" data-duration="${num(total)}" data-track-index="0" data-volume="1"></audio>\n`
57
+ : "";
58
+ const beatsJson = JSON.stringify(windows.map((w) => ({ i: w.index, start: w.start, seconds: w.seconds })));
59
+
60
+ return `<!doctype html>
61
+ <html lang="en">
62
+ <head>
63
+ <meta charset="UTF-8" />
64
+ <meta name="viewport" content="width=${FRAMEY_FRAME.width}, height=${FRAMEY_FRAME.height}" />
65
+ <script src="assets/gsap.min.js"></script>
66
+ <style>
67
+ :root {
68
+ --black: ${p.black};
69
+ --white: ${p.white};
70
+ --ice: ${p.ice};
71
+ --sky: ${p.sky};
72
+ --blue: ${p.blue};
73
+ --navy: ${p.navy};
74
+ }
75
+ * { margin: 0; padding: 0; box-sizing: border-box; border-radius: 0; }
76
+ html, body { width: ${FRAMEY_FRAME.width}px; height: ${FRAMEY_FRAME.height}px; overflow: hidden; background: var(--black); }
77
+ #root { position: relative; width: ${FRAMEY_FRAME.width}px; height: ${FRAMEY_FRAME.height}px; background: var(--black); color: var(--white); font-family: "Inter", sans-serif; }
78
+ .track { position: absolute; top: ${lift}px; left: 72px; right: 72px; height: 18px; background: var(--navy); }
79
+ .fill { width: 100%; height: 100%; background: var(--blue); transform-origin: left center; }
80
+ .beat { position: absolute; left: 72px; right: 72px; top: ${lift + 48}px; bottom: 220px; overflow: hidden; }
81
+ .meta { font-family: "JetBrains Mono", monospace; font-size: 26px; font-weight: 500; letter-spacing: 2px; color: var(--sky); margin-bottom: 28px; }
82
+ .caption { font-weight: 800; letter-spacing: -1.5px; line-height: 0.98; color: var(--white); transform-origin: left top; }
83
+ .ticks { position: absolute; left: 72px; bottom: 96px; display: flex; gap: 12px; }
84
+ .tick { width: 36px; height: 8px; background: var(--navy); }
85
+ .label { position: absolute; right: 72px; bottom: 80px; padding: 10px 16px; border: 3px solid var(--sky); color: var(--ice); font-family: "JetBrains Mono", monospace; font-size: 24px; font-weight: 500; letter-spacing: 3px; background: var(--black); }
86
+ </style>
87
+ </head>
88
+ <body>
89
+ <div id="root" data-composition-id="main" data-start="0" data-duration="${num(total)}" data-width="${FRAMEY_FRAME.width}" data-height="${FRAMEY_FRAME.height}">
90
+ ${audio} <div class="track"><div id="fill" class="fill"></div></div>
91
+ ${slides}
92
+ <div class="ticks">
93
+ ${ticks}
94
+ </div>
95
+ <div id="disclosure" class="label">${DISCLOSURE_LABEL}</div>
96
+ </div>
97
+ <script>
98
+ const beats = ${beatsJson};
99
+ const tl = gsap.timeline({ paused: true });
100
+ for (const b of beats) {
101
+ tl.fromTo("#text-" + b.i, { scale: 1.04 }, { scale: 1, duration: 8 / 30, ease: "none" }, b.start);
102
+ tl.fromTo("#fill", { scaleX: 0 }, { scaleX: 1, duration: 8 / 30, ease: "none", immediateRender: false }, b.start);
103
+ tl.set("#tick-" + b.i, { backgroundColor: "${p.blue}" }, b.start);
104
+ }
105
+ window.__timelines = window.__timelines || {};
106
+ window.__timelines["main"] = tl;
107
+ tl.seek(0);
108
+ </script>
109
+ </body>
110
+ </html>
111
+ `;
112
+ }
113
+
114
+ /** How far the voice may differ from the planned length before the picture follows the voice. */
115
+ export const VOICE_SLACK_SEC = 0.5;
116
+ /** Picture held after the last word. */
117
+ export const VOICE_TAIL_SEC = 0.3;
118
+
119
+ /**
120
+ * The beats stretched or squeezed to the voice, so a spoken line is never cut and the video does not run silent.
121
+ * A voice within the slack of the plan leaves the plan alone.
122
+ */
123
+ export function retimeToVoice(props: RenderProps, voiceSec: number | null): RenderProps {
124
+ if (!voiceSec || !Number.isFinite(voiceSec) || voiceSec <= 0) return props;
125
+ if (Math.abs(voiceSec - props.durationSec) <= VOICE_SLACK_SEC) return props;
126
+ const total = Math.round((voiceSec + VOICE_TAIL_SEC) * 100) / 100;
127
+ const planned = props.beats.reduce((sum, beat) => sum + beat.seconds, 0) || 1;
128
+ const beats = props.beats.map((beat) => ({ ...beat, seconds: Math.round((beat.seconds * total * 1000) / planned) / 1000 }));
129
+ return { ...props, beats, durationSec: total };
130
+ }