@mevdragon/vidfarm-devcli 0.1.0 → 0.2.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 (63) hide show
  1. package/.env.example +11 -4
  2. package/PLATFORM_SPEC.md +142 -2
  3. package/README.md +165 -16
  4. package/SKILL.developer.md +577 -0
  5. package/dist/infra/cdk/bin/vidfarm-prod.js +59 -0
  6. package/dist/infra/cdk/lib/vidfarm-prod-stack.js +212 -0
  7. package/dist/src/account-pages.js +578 -0
  8. package/dist/src/app.js +887 -66
  9. package/dist/src/cli.js +284 -5
  10. package/dist/src/config.js +24 -4
  11. package/dist/src/db.js +427 -18
  12. package/dist/src/dev-app.js +59 -12
  13. package/dist/src/homepage.js +441 -0
  14. package/dist/src/index.js +12 -7
  15. package/dist/src/lib/crypto.js +14 -0
  16. package/dist/src/lib/template-dna.js +542 -0
  17. package/dist/src/lib/template-style-options.js +49 -0
  18. package/dist/src/registry.js +54 -7
  19. package/dist/src/runtime.js +3 -1
  20. package/dist/src/services/auth.js +69 -5
  21. package/dist/src/services/jobs.js +23 -4
  22. package/dist/src/services/providers.js +74 -12
  23. package/dist/src/services/storage.js +52 -18
  24. package/dist/src/services/template-certification.js +160 -0
  25. package/dist/src/services/template-loader.js +37 -0
  26. package/dist/src/services/template-sources.js +135 -0
  27. package/dist/src/worker.js +19 -7
  28. package/dist/templates/template_0000/src/lib/images.js +242 -0
  29. package/dist/templates/template_0000/src/remotion/Root.js +33 -0
  30. package/dist/templates/template_0000/src/sdk.js +3 -0
  31. package/dist/templates/template_0000/src/style-options.js +51 -0
  32. package/dist/templates/template_0000/src/template-dna.js +9 -0
  33. package/dist/templates/template_0000/src/template.js +1217 -0
  34. package/package.json +9 -1
  35. package/templates/template_0000/README.md +121 -0
  36. package/templates/template_0000/SKILL.md +193 -0
  37. package/templates/template_0000/assets/Abel-Regular.ttf +0 -0
  38. package/templates/template_0000/assets/DMSerifDisplay-Regular.ttf +0 -0
  39. package/templates/template_0000/assets/Montserrat[wght].ttf +0 -0
  40. package/templates/template_0000/assets/SourceCodePro[wght].ttf +0 -0
  41. package/templates/template_0000/assets/TikTokSans-SemiBold.ttf +0 -0
  42. package/templates/template_0000/assets/Yesteryear-Regular.ttf +0 -0
  43. package/templates/template_0000/composition.json +11 -0
  44. package/templates/template_0000/package-lock.json +5137 -0
  45. package/templates/template_0000/package.json +30 -0
  46. package/templates/template_0000/research/preview/.gitkeep +1 -0
  47. package/templates/template_0000/research/source_notes.md +7 -0
  48. package/templates/template_0000/scripts/create-site.mjs +27 -0
  49. package/templates/template_0000/scripts/render-cloud.mjs +72 -0
  50. package/templates/template_0000/src/lib/images.ts +284 -0
  51. package/templates/template_0000/src/remotion/Root.js +33 -0
  52. package/templates/template_0000/src/remotion/Root.tsx +75 -0
  53. package/templates/template_0000/src/remotion/index.tsx +4 -0
  54. package/templates/template_0000/src/sdk.ts +122 -0
  55. package/templates/template_0000/src/style-options.js +51 -0
  56. package/templates/template_0000/src/style-options.ts +60 -0
  57. package/templates/template_0000/src/template-dna.ts +15 -0
  58. package/templates/template_0000/src/template.ts +1747 -0
  59. package/templates/template_0000/template.config.json +26 -0
  60. package/templates/template_0000/tsconfig.json +19 -0
  61. package/dist/templates/template_0000/demo-template.js +0 -196
  62. package/dist/templates/template_0000/remotion/Root.js +0 -66
  63. /package/dist/templates/template_0000/{remotion → src/remotion}/index.js +0 -0
@@ -0,0 +1,577 @@
1
+ ---
2
+ name: vidfarm-developer
3
+ description: Build and extend Vidfarm video-production templates and platform features in this repository. Use this whenever the user wants to create a new Vidfarm template, add a pipeline stage or operation, wire billing or provider calls, integrate Remotion, extend the developer console, or modify the async jobs/auth/storage/webhook flow for Vidfarm.
4
+ ---
5
+
6
+ # Vidfarm Developer
7
+
8
+ This skill is for working inside the Vidfarm platform in this repository.
9
+
10
+ ## Distribution Notes
11
+
12
+ Current published/distribution targets:
13
+
14
+ - npm package: `@mevdragon/vidfarm-devcli` as a private package
15
+ - GitHub repo: `OfficeXApp/vidfarm-devcli` as a private repo
16
+
17
+ Keep that split in mind when changing package metadata or release instructions. The npm package is intentionally user-scoped right now because private publish succeeded there, while the GitHub repo lives under the OfficeX org.
18
+
19
+ Use it when the task is any of:
20
+
21
+ - add a new internal video template
22
+ - extend an existing template with new operations or workflows
23
+ - wire AI generation through customer-owned provider keys
24
+ - add billing, artifacts, workspace, or webhook behavior
25
+ - integrate Remotion render steps
26
+ - modify the developer console at `/dev`
27
+ - change the Docker/AWS-hosted platform runtime
28
+
29
+ The current runtime is a single Node.js service with:
30
+
31
+ - Hono API
32
+ - SQLite job and lease state
33
+ - in-process worker loop
34
+ - local or S3-backed artifact storage
35
+ - async-first job model
36
+
37
+ The current release model also supports:
38
+
39
+ - GitHub-backed template source records
40
+ - admin-only import from the `production` branch
41
+ - admin-only Remotion site publish to shared AWS
42
+ - admin-only production Docker promotion
43
+ - pinned commit-SHA releases
44
+ - mandatory certification before activation
45
+
46
+ Start from the current implementation, not just the original spec.
47
+
48
+ ## First Read
49
+
50
+ Read these files first before changing behavior:
51
+
52
+ 1. [PLATFORM_SPEC.md](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/PLATFORM_SPEC.md)
53
+ 2. [video-pipeline-architecture-draft.md](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/video-pipeline-architecture-draft.md)
54
+ 3. [AWS_REMOTION_HANDOFF.md](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/AWS_REMOTION_HANDOFF.md) if the task touches Remotion or cloud render setup
55
+ 4. [src/app.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/app.ts)
56
+ 5. [src/db.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/db.ts)
57
+ 6. [src/worker.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/worker.ts)
58
+ 7. [src/template-sdk.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/template-sdk.ts)
59
+ 8. [templates/template_0000/src/template.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/templates/template_0000/src/template.ts)
60
+ 9. [src/dev-app.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/dev-app.ts)
61
+ 10. [src/cli.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/cli.ts) if the task touches local template developer workflow
62
+
63
+ If the task is narrow, only read the relevant slice after this initial pass.
64
+
65
+ ## Platform Shape
66
+
67
+ Treat Vidfarm as one shared control-plane service.
68
+
69
+ - API routes live in `src/app.ts`
70
+ - database schema and persistence helpers live in `src/db.ts`
71
+ - background execution lives in `src/worker.ts`
72
+ - template execution context is built in `src/context.ts`
73
+ - provider leasing and outbound AI routing live in `src/services/providers.ts`
74
+ - storage lives in `src/services/storage.ts`
75
+ - jobs live in `src/services/jobs.ts`
76
+ - webhooks live in `src/services/webhooks.ts`
77
+ - Remotion integration seam lives in `src/services/remotion.ts`
78
+ - templates are registered in `src/registry.ts`
79
+ - template implementation code lives in `templates/*`, not `src/*`
80
+
81
+ Do not split a new template into its own HTTP service unless the user explicitly wants that. The default Vidfarm pattern is internal code modules loaded by the shared platform.
82
+
83
+ ## Core Mental Model
84
+
85
+ Every public template action is async and returns a `job_id`.
86
+
87
+ The normal request flow is:
88
+
89
+ 1. client calls `POST /templates/:templateId/operations/:operationName`
90
+ 2. platform authenticates with `vidfarm-user-id` and `vidfarm-api-key`
91
+ 3. platform validates payload against the template operation schema
92
+ 4. platform creates a queued job in SQLite
93
+ 5. worker picks up the job
94
+ 6. workflow emits logs, artifacts, billing events, and optional webhook deliveries
95
+ 7. client polls `GET /templates/:templateId/jobs/:jobId`
96
+
97
+ Do not implement new synchronous flows unless the user explicitly asks for it. Prefer consistency with the async job model.
98
+
99
+ ## When Adding A New Template
100
+
101
+ Follow this checklist.
102
+
103
+ 1. Create a new folder under `templates/template_<nnnn>/`
104
+ 2. Put the template definition in that folder, not under `src/*`
105
+ 3. Export `defineTemplate({...})`
106
+ 4. Define:
107
+ - `id`
108
+ - `version`
109
+ - `about.description`
110
+ - `about.viral_dna`
111
+ - `about.visual_dna`
112
+ - `about.preview_media`
113
+ - `about.link_to_original`
114
+ - `skillPath`
115
+ - `configSchema`
116
+ - `operations`
117
+ - `jobs`
118
+ 5. Add a template-local `SKILL.md`
119
+ 6. Put original-format notes in `research/source_notes.md` and source screenshots/video in `research/preview/`
120
+ 7. Run `vidfarm analyze-viral-dna --template-dir <template-dir>` and `vidfarm analyze-visual-dna --template-dir <template-dir>`
121
+ 8. Add `smokeTestPayload` for every operation
122
+ 9. Register the template in `src/registry.ts`
123
+ 10. If useful, add default payload/config examples to `src/dev-app.ts`
124
+ 11. Verify end to end with the local developer console and/or curl
125
+
126
+ Use the existing `template_0000` starter template as the baseline example.
127
+
128
+ The starter scaffold now standardizes template DNA authoring:
129
+
130
+ - `research/source_notes.md` is the source-format note file
131
+ - `research/preview/` holds the screenshots or video the analyzers inspect
132
+ - `src/template-dna.ts` is the checked-in generated module that feeds `about.viral_dna`, `about.visual_dna`, and `about.link_to_original`
133
+ - `vidfarm generate-template` stages those files automatically, and if preview media is already present it will run both DNA analyzers during scaffold creation
134
+
135
+ `template_0000` is intentionally opinionated and should be treated as the default starter pattern:
136
+
137
+ - operation 1: `create_slideshow`
138
+ - operation 2: `render_video`
139
+ - stage 1 outputs finished 9:16 slide images with the text already composited
140
+ - stage 2 only sequences those finished slide images into video
141
+ - reserve TikTok UI safe zones at the top, right edge, and bottom
142
+ - avoid subject cut-off during portrait normalization
143
+ - use checked-in TikTok Sans for starter caption typography
144
+ - prefer readable text with shadow/fade over caption boxes
145
+ - if a new template does not need video, it can stop after stage 1
146
+
147
+ Not every template uses Remotion. That is fine. Certification only expects Remotion behavior if the template actually calls `ctx.remotion`.
148
+
149
+ ## Template Contract
150
+
151
+ Each template should expose operations, not ad hoc endpoints.
152
+
153
+ Use this shape:
154
+
155
+ ```ts
156
+ export const myTemplate = defineTemplate({
157
+ id: "123e4567-e89b-42d3-a456-426614174000",
158
+ slugId: "ugc_hooks_v1",
159
+ version: "1.0.0",
160
+ about: {
161
+ title: "UGC Hooks V1",
162
+ description: "Generate hooks, previews, and final render inputs.",
163
+ viral_dna: "Fast creator-style hooks with simple repeatable structure.",
164
+ visual_dna: "Presentation-led mobile layouts with recognizable creator-native framing.",
165
+ preview_media: ["https://cdn.example.com/templates/ugc_hooks_v1/about/preview-01.jpg"],
166
+ link_to_original: "https://www.tiktok.com/@example/video/1234567890"
167
+ },
168
+ configSchema: z.object({
169
+ defaultProvider: z.enum(["openai", "openrouter", "gemini", "perplexity"]).default("openai")
170
+ }),
171
+ operations: {
172
+ scaffold: {
173
+ description: "Generate a script scaffold.",
174
+ inputSchema: z.object({
175
+ topic: z.string()
176
+ }),
177
+ workflow: "scaffoldWorkflow",
178
+ providerHint: "openai",
179
+ webhookSupport: true,
180
+ smokeTestPayload: {
181
+ topic: "creator hooks"
182
+ }
183
+ }
184
+ },
185
+ jobs: {
186
+ async scaffoldWorkflow(ctx, input) {
187
+ return {
188
+ progress: 1,
189
+ output: {}
190
+ };
191
+ }
192
+ }
193
+ });
194
+ ```
195
+
196
+ Keep the separation clear:
197
+
198
+ - `id` is the self-issued UUIDv4 `template_id`
199
+ - `slugId` is the human-readable stable `slug_id`
200
+ - `operations` define the public API surface
201
+ - `jobs` define internal execution workflows
202
+ - `smokeTestPayload` defines the minimum certification input
203
+
204
+ ## GitHub Source Flow
205
+
206
+ For GitHub-backed template distribution, treat the platform as importing approved source code, not live-tracking a repo.
207
+
208
+ Rules:
209
+
210
+ - default source branch is `production`
211
+ - admin manually reviews the repo and decides when to import
212
+ - template authors do not publish directly to shared Remotion AWS
213
+ - template authors do not directly promote templates into production Docker
214
+ - import resolves to a pinned commit SHA
215
+ - certification runs before activation
216
+ - activation flips one certified release live
217
+ - Remotion site publish is part of admin release promotion, not template authoring
218
+ - production Docker rebuild/redeploy happens only after admin approval
219
+
220
+ Do not implement floating branch-head production state. Live template state must always be tied to a specific commit.
221
+
222
+ For the current demo standalone template repo, use:
223
+
224
+ - project/package name: `vidfarm_template_0000`
225
+ - GitHub repo target: `mevdragon/vidfarm_template_0000`
226
+ - checked-in production config file: `template.config.json`
227
+ - `slug_id`: `template_0000`
228
+ - sample `template_id`: `4c7a7e1a-7f35-4f30-9f86-9c8a63c7f2db`
229
+
230
+ When registering a template source with the platform:
231
+
232
+ - `template_id` must be a self-issued UUIDv4
233
+ - `slug_id` must be the human-readable stable identifier
234
+ - registration must fail if another source already uses the same `template_id`
235
+ - the conflict error should tell the developer to generate a different UUIDv4
236
+
237
+ Template repos should prefer checked-in config for production topology over scattered env vars. In particular:
238
+
239
+ - Remotion region/function/bucket/site/composition settings should live in `template.config.json`
240
+ - release control metadata should also live in `template.config.json`
241
+ - AI agents should read `template.config.json` as the source of truth
242
+ - only secrets and credentials should come from the execution environment
243
+
244
+ ## Workflow Rules
245
+
246
+ Inside a template workflow:
247
+
248
+ - log meaningful progress
249
+ - store large outputs as artifacts
250
+ - record billing when you consume external or compute-heavy resources
251
+ - route provider calls through `ctx.providers`
252
+ - use `ctx.remotion` for render submission
253
+ - use `ctx.jobs.enqueueChild(...)` only when a child-job boundary is truly useful
254
+
255
+ Do not bypass framework-owned services with raw provider calls unless the user explicitly wants to break out of the shared routing and billing model.
256
+
257
+ ## Provider Usage
258
+
259
+ For customer-billed AI calls, always go through:
260
+
261
+ ```ts
262
+ await ctx.providers.generateText({
263
+ provider: "openai",
264
+ model: "gpt-4.1-mini",
265
+ prompt: "...",
266
+ temperature: 0.7
267
+ });
268
+ ```
269
+
270
+ Why:
271
+
272
+ - it leases a compatible customer key
273
+ - it respects cooldown and invalidation behavior
274
+ - it records usage events
275
+ - it fits the retry model in the worker
276
+
277
+ Relevant files:
278
+
279
+ - [src/services/providers.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/services/providers.ts)
280
+ - [src/db.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/db.ts)
281
+
282
+ ## Billing Rules
283
+
284
+ Templates should emit billable events through the framework context, not invent a separate ledger.
285
+
286
+ Use:
287
+
288
+ ```ts
289
+ await ctx.billing.record({
290
+ type: "ai_generation",
291
+ costUsd: 0.02,
292
+ metadata: { provider: "openai" }
293
+ });
294
+ ```
295
+
296
+ Current default behavior charges roughly `costUsd * 2` if `chargeUsd` is omitted.
297
+
298
+ If you add a new billable resource type, update both:
299
+
300
+ 1. the domain types in `src/domain.ts`
301
+ 2. any services or reporting code that assumes the existing event kinds
302
+
303
+ ## Storage And Artifacts
304
+
305
+ Use `ctx.storage.putJson(...)` for structured intermediate outputs.
306
+
307
+ The current storage adapter supports:
308
+
309
+ - local disk for development
310
+ - S3-compatible object storage for hosted environments
311
+
312
+ Store large stage outputs as artifacts rather than only embedding them inside `job.result`.
313
+ Template-generated artifacts should be written under the logical prefix:
314
+
315
+ ```txt
316
+ templates/:templateId/users/:userId/jobs/:jobId/...
317
+ ```
318
+
319
+ Relevant files:
320
+
321
+ - [src/services/storage.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/services/storage.ts)
322
+ - [src/context.ts](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/src/context.ts)
323
+
324
+ ## Remotion Pattern
325
+
326
+ Remotion is treated as a downstream adapter, not the platform center.
327
+
328
+ Use:
329
+
330
+ ```ts
331
+ const render = await ctx.remotion.render({
332
+ compositionId: "storyboard-main",
333
+ inputProps: {...}
334
+ });
335
+ ```
336
+
337
+ If the user asks for real Lambda wiring, keep the template contract stable and upgrade `src/services/remotion.ts` rather than hardcoding provider-specific render logic directly into template files.
338
+
339
+ For real AWS-backed Remotion work in this repo:
340
+
341
+ - use [AWS_REMOTION_HANDOFF.md](/Users/localghost/Projects/OfficeX/OfficeX/ZoomGTM/vidfarm/AWS_REMOTION_HANDOFF.md) as source of truth
342
+ - target the shared `us-east-1` Remotion infra described there
343
+ - pin Remotion packages to `4.0.355` unless the task is explicitly shared-infra upgrade work
344
+ - publish a repo-specific site bundle instead of deploying a new render Lambda by default
345
+ - treat shared AWS site publish and cloud render validation as release-admin work, not normal developer authoring work
346
+
347
+ Important credential note:
348
+
349
+ - this repo has separate Remotion AWS credentials available in local production env config as `REMOTION_AWS_ACCESS_KEY_ID` and `REMOTION_AWS_SECRET_ACCESS_KEY`
350
+ - use those for Remotion site publish/render operations
351
+ - do not assume generic `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are the correct identity for Remotion work
352
+
353
+ Preferred env/config values for real Remotion integration:
354
+
355
+ ```env
356
+ REMOTION_REGION=us-east-1
357
+ REMOTION_FUNCTION_NAME=remotion-render-4-0-355-mem2048mb-disk2048mb-180sec
358
+ REMOTION_BUCKET_NAME=remotionlambda-useast1-ujg7c0h43q
359
+ REMOTION_SITE_NAME=your-site-name
360
+ REMOTION_SERVE_URL=https://remotionlambda-useast1-ujg7c0h43q.s3.us-east-1.amazonaws.com/sites/your-site-name/index.html
361
+ REMOTION_COMPOSITION_ID=YourComposition
362
+ ```
363
+
364
+ If implementing real rendering, prefer one of these patterns:
365
+
366
+ 1. publish a site bundle with the shared bucket and site-name pattern from the handoff
367
+ 2. render against the shared function name and the repo-specific `REMOTION_SERVE_URL`
368
+
369
+ Do not deploy a new Lambda function for every template unless the task explicitly requires shared infra changes.
370
+
371
+ Release sequence for Remotion-backed templates:
372
+
373
+ 1. developer merges approved code into the template repo `production` branch
374
+ 2. release admin reviews and pins a commit SHA
375
+ 3. release admin publishes the site bundle to shared AWS
376
+ 4. release admin verifies a cloud render against that site
377
+ 5. release admin activates the pinned template release in the platform
378
+ 6. release admin rebuilds and redeploys the production Docker image
379
+
380
+ ## API Rules
381
+
382
+ If you need new API surface area, prefer these patterns:
383
+
384
+ - customer-facing template actions under `/templates/:templateId/*`
385
+ - developer or customer profile actions under `/me/*`
386
+ - auth under `/auth/*`
387
+ - documentation or debug surfaces only when justified
388
+
389
+ Do not create a separate route per stage if an operation-based route can cover it cleanly. The platform already normalizes work through:
390
+
391
+ `POST /templates/:templateId/operations/:operationName`
392
+
393
+ ## Database Rules
394
+
395
+ When changing persistence:
396
+
397
+ - update schema in `src/db.ts`
398
+ - add mapping helpers there too
399
+ - keep writes idempotent where possible
400
+ - preserve the worker’s retry safety
401
+ - avoid introducing a second state store unless the user explicitly wants it
402
+
403
+ For provider-key coordination, preserve the SQLite lease model unless the task is explicitly about moving to Postgres, Redis, or SQS.
404
+
405
+ ## Developer Console
406
+
407
+ The browser console lives at `/dev`.
408
+
409
+ If you add a new template or operation, consider whether `src/dev-app.ts` should also gain:
410
+
411
+ - default config JSON
412
+ - default payload JSON
413
+ - extra developer affordances for that workflow
414
+
415
+ Keep the console practical. It is for internal developers to test the platform quickly, not for polished end-user UX.
416
+
417
+ ## Local Runbook
418
+
419
+ Typical local run:
420
+
421
+ ```bash
422
+ npm install
423
+ PORT=3100 ENCRYPTION_SECRET=test-secret API_KEY_SALT=test-salt MOCK_PROVIDER_RESPONSES=true npm run dev
424
+ ```
425
+
426
+ Open:
427
+
428
+ ```txt
429
+ http://127.0.0.1:3100/dev
430
+ ```
431
+
432
+ Use mocked provider responses by default during local development unless the task specifically requires real provider traffic.
433
+
434
+ Preferred local template developer workflow:
435
+
436
+ ```bash
437
+ npx @mevdragon/vidfarm-devcli dev --port 3310 --reset
438
+ npx @mevdragon/vidfarm-devcli session
439
+ npx @mevdragon/vidfarm-devcli validate-template --template-id template_0000
440
+ ```
441
+
442
+ That CLI should be the default path for local template testing because it:
443
+
444
+ - boots the real REST API and worker
445
+ - provisions local SQLite automatically
446
+ - seeds a dev auth session
447
+ - seeds provider keys from local env vars when present
448
+ - falls back to mock provider keys plus mocked AI responses when needed
449
+ - renders Remotion locally
450
+
451
+ Reset local state when you need a clean test pass:
452
+
453
+ ```bash
454
+ rm -rf .vidfarm/local
455
+ npx @mevdragon/vidfarm-devcli dev --port 3310 --reset
456
+ ```
457
+
458
+ For slideshow-style templates, remember the artifact distinction:
459
+
460
+ - `slides/*.png` are background images only
461
+ - text overlay appears in `renders/final.mp4`
462
+ - if text seems missing, inspect the final MP4 before assuming generation failed
463
+
464
+ If the task requires real Remotion cloud rendering, confirm these before coding:
465
+
466
+ 1. the repo is using the shared function and bucket from `AWS_REMOTION_HANDOFF.md`
467
+ 2. the Remotion package version matches `4.0.355`
468
+ 3. the runner is using `REMOTION_AWS_ACCESS_KEY_ID` and `REMOTION_AWS_SECRET_ACCESS_KEY`
469
+ 4. the site name is repo-specific and not reusing another repo’s published bundle unintentionally
470
+
471
+ ## Validation Checklist
472
+
473
+ After changes, validate with as many of these as apply:
474
+
475
+ 1. `npm run check`
476
+ 2. `npm run build`
477
+ 3. `npx @mevdragon/vidfarm-devcli validate-template --template-id <templateIdOrSlug>`
478
+ 4. hit `/health`
479
+ 5. use `/dev`
480
+ 6. request OTP and verify login
481
+ 7. add a provider key
482
+ 8. save template config
483
+ 9. launch a job
484
+ 10. poll job status and logs
485
+ 11. inspect produced artifacts
486
+
487
+ If the task touches GitHub-backed template releases, also validate:
488
+
489
+ 1. source branch is `production`
490
+ 2. module path points to the built template export
491
+ 3. `SKILL.md` path is correct
492
+ 4. import creates a release pinned to a commit SHA
493
+ 5. only certified releases are activatable
494
+
495
+ For new template scaffolds, use the CLI instead of copy-pasting the starter repo by hand:
496
+
497
+ ```bash
498
+ npx @mevdragon/vidfarm-devcli generate-template --slug-id hooks_v1 --template-dir templates/template_0007
499
+ ```
500
+
501
+ That command copies `templates/template_0000`, strips `.git` and `node_modules`, rewrites the starter placeholders for the new template, and generates a UUIDv4 `template_id` if you do not pass one explicitly.
502
+
503
+ The generated template repo is still authoring-only. It can contain admin release scripts and config, but only the release admin should run those scripts against shared AWS or production infrastructure.
504
+
505
+ If you changed worker behavior, do not stop at compile success. Run a real job.
506
+
507
+ If you changed Remotion integration, also validate:
508
+
509
+ 1. site publish config
510
+ 2. serve URL shape
511
+ 3. function name
512
+ 4. composition ID
513
+ 5. render submission path
514
+
515
+ If you changed slideshow or text-overlay behavior, also validate:
516
+
517
+ 1. the generated background slide images do not contain baked-in text unless explicitly intended
518
+ 2. the final MP4 shows the overlay text in the expected zone
519
+ 3. long captions wrap correctly and do not clip
520
+ 4. the stored slide assets are the expected aspect ratio, especially for strict 9:16 templates
521
+
522
+ ## Common Tasks
523
+
524
+ ### Add a new operation to an existing template
525
+
526
+ 1. update `operations` in the template file
527
+ 2. add the workflow implementation under `jobs`
528
+ 3. add sample payload defaults in `src/dev-app.ts` if useful
529
+ 4. verify through `/dev`
530
+
531
+ ### Add a new template-wide config field
532
+
533
+ 1. extend `configSchema`
534
+ 2. read it from `ctx.templateConfig`
535
+ 3. test save/load through `/templates/:templateId/config`
536
+
537
+ ### Add a new provider-aware generation step
538
+
539
+ 1. call `ctx.providers.generateText(...)`
540
+ 2. record billing
541
+ 3. log progress and persist the artifact
542
+
543
+ ### Add webhook behavior
544
+
545
+ 1. prefer queueing delivery through the existing webhook service
546
+ 2. do not send ad hoc `fetch()` calls directly from template code
547
+
548
+ ### Register a GitHub-backed template source
549
+
550
+ 1. create or update the template source record
551
+ 2. use branch `production`
552
+ 3. point `template_module_path` at the built module the platform should import
553
+ 4. point `skill_path` at the template-local `SKILL.md`
554
+ 5. import the source to create a pinned release
555
+ 6. activate only after certification passes
556
+
557
+ ## What To Avoid
558
+
559
+ - bypassing auth and job creation by adding custom one-off endpoints
560
+ - storing plaintext customer provider secrets
561
+ - making raw AI calls outside the provider lease system for customer workloads
562
+ - writing template-specific persistence logic outside `src/db.ts` without reason
563
+ - activating a template from a floating branch head instead of a pinned commit
564
+ - omitting `SKILL.md` or `smokeTestPayload`
565
+ - coupling the platform too tightly to one render engine
566
+ - returning giant generated outputs only inline when they should be artifacts
567
+
568
+ ## Output Style For Vidfarm Work
569
+
570
+ When reporting back after Vidfarm changes:
571
+
572
+ - name the main platform area changed
573
+ - mention the template or route affected
574
+ - state how you verified it
575
+ - call out any remaining gap such as `Remotion path still mocked` or `real provider calls not exercised`
576
+
577
+ That keeps Vidfarm work easy to review and safe to iterate on.
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ import { App } from "aws-cdk-lib";
3
+ import { VidfarmProdStack } from "../lib/vidfarm-prod-stack.js";
4
+ function required(name) {
5
+ const value = process.env[name]?.trim();
6
+ if (!value) {
7
+ throw new Error(`Missing required environment variable: ${name}`);
8
+ }
9
+ return value;
10
+ }
11
+ function optional(name) {
12
+ const value = process.env[name]?.trim();
13
+ return value ? value : undefined;
14
+ }
15
+ const account = optional("CDK_DEFAULT_ACCOUNT") ?? optional("AWS_ACCOUNT_ID");
16
+ const region = optional("CDK_DEFAULT_REGION") ?? optional("AWS_REGION") ?? "us-east-1";
17
+ if (!account) {
18
+ throw new Error("Set CDK_DEFAULT_ACCOUNT or AWS_ACCOUNT_ID before running CDK.");
19
+ }
20
+ const env = { account, region };
21
+ const app = new App();
22
+ new VidfarmProdStack(app, "VidfarmProdStack", {
23
+ env,
24
+ zoneName: optional("VIDFARM_ZONE_NAME") ?? "cloud.zoomgtm.com",
25
+ zoneId: required("VIDFARM_ZONE_ID"),
26
+ recordName: optional("VIDFARM_RECORD_NAME") ?? "vidfarm",
27
+ publicBaseUrl: optional("VIDFARM_PUBLIC_BASE_URL") ?? "https://vidfarm.cloud.zoomgtm.com",
28
+ adminEmails: required("VIDFARM_ADMIN_EMAILS"),
29
+ developerEmails: optional("VIDFARM_DEVELOPER_EMAILS") ?? "",
30
+ encryptionSecret: required("VIDFARM_ENCRYPTION_SECRET"),
31
+ apiKeySalt: required("VIDFARM_API_KEY_SALT"),
32
+ webhookSecret: required("VIDFARM_WEBHOOK_SECRET"),
33
+ resendApiKey: optional("VIDFARM_RESEND_API_KEY"),
34
+ resendFromEmail: optional("VIDFARM_RESEND_FROM_EMAIL") ?? "noreply@zoomgtm.com",
35
+ superagencyKey: optional("SUPERAGENCY_KEY"),
36
+ openAiApiKey: optional("VIDFARM_OPENAI_API_KEY"),
37
+ openRouterApiKey: optional("VIDFARM_OPENROUTER_API_KEY"),
38
+ geminiApiKey: optional("VIDFARM_GEMINI_API_KEY"),
39
+ perplexityApiKey: optional("VIDFARM_PERPLEXITY_API_KEY"),
40
+ remotionMode: optional("VIDFARM_REMOTION_MODE") ?? "auto",
41
+ remotionRegion: optional("VIDFARM_REMOTION_REGION") ?? "us-east-1",
42
+ remotionBucketName: optional("VIDFARM_REMOTION_BUCKET_NAME"),
43
+ remotionSiteName: optional("VIDFARM_REMOTION_SITE_NAME"),
44
+ remotionFunctionName: optional("VIDFARM_REMOTION_FUNCTION_NAME"),
45
+ remotionServeUrl: optional("VIDFARM_REMOTION_SERVE_URL"),
46
+ remotionCompositionId: optional("VIDFARM_REMOTION_COMPOSITION_ID") ?? "template-0000",
47
+ remotionAwsAccessKeyId: optional("VIDFARM_REMOTION_AWS_ACCESS_KEY_ID"),
48
+ remotionAwsSecretAccessKey: optional("VIDFARM_REMOTION_AWS_SECRET_ACCESS_KEY"),
49
+ mockProviderResponses: optional("VIDFARM_MOCK_PROVIDER_RESPONSES") ?? "false",
50
+ workerPollMs: Number(optional("VIDFARM_WORKER_POLL_MS") ?? "1500"),
51
+ workerBatchSize: Number(optional("VIDFARM_WORKER_BATCH_SIZE") ?? "2"),
52
+ workerMaxConcurrentJobs: Number(optional("VIDFARM_WORKER_MAX_CONCURRENT_JOBS") ?? "1"),
53
+ defaultJobDelaySeconds: Number(optional("VIDFARM_DEFAULT_JOB_DELAY_SECONDS") ?? "20"),
54
+ maxPendingJobsGlobal: Number(optional("VIDFARM_MAX_PENDING_JOBS_GLOBAL") ?? "0"),
55
+ maxPendingJobsPerCustomer: Number(optional("VIDFARM_MAX_PENDING_JOBS_PER_CUSTOMER") ?? "0"),
56
+ instanceType: optional("VIDFARM_INSTANCE_TYPE") ?? "t3.small",
57
+ dataVolumeSizeGiB: Number(optional("VIDFARM_DATA_VOLUME_SIZE_GIB") ?? "80")
58
+ });
59
+ app.synth();