@mevdragon/vidfarm-devcli 0.2.0 → 0.2.2
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.
- package/.env.example +6 -39
- package/GETTING_STARTED.developers.md +178 -0
- package/README.md +62 -246
- package/SKILL.developer.md +127 -447
- package/dist/src/account-pages.js +57 -5
- package/dist/src/app.js +32 -22
- package/dist/src/config.js +1 -1
- package/dist/src/context.js +1 -1
- package/dist/src/services/storage.js +22 -0
- package/dist/templates/template_0000/src/template.js +1 -1
- package/package.json +4 -4
- package/templates/template_0000/README.md +7 -52
- package/templates/template_0000/SKILL.md +3 -3
- package/templates/template_0000/package.json +3 -5
- package/templates/template_0000/src/lib/images.js +242 -0
- package/templates/template_0000/src/remotion/index.js +3 -0
- package/templates/template_0000/src/sdk.js +3 -0
- package/templates/template_0000/src/template.js +1117 -0
- package/templates/template_0000/src/template.ts +1 -1
- package/templates/template_0000/template.config.json +6 -11
- package/AWS_REMOTION_HANDOFF.md +0 -311
- package/PLATFORM_SPEC.md +0 -1038
- package/dist/infra/cdk/bin/vidfarm-prod.js +0 -59
- package/dist/infra/cdk/lib/vidfarm-prod-stack.js +0 -212
- package/templates/template_0000/package-lock.json +0 -5137
- package/templates/template_0000/scripts/create-site.mjs +0 -27
- package/templates/template_0000/scripts/render-cloud.mjs +0 -72
|
@@ -220,6 +220,40 @@ function shell(input) {
|
|
|
220
220
|
color: var(--muted);
|
|
221
221
|
background: rgba(255,255,255,0.7);
|
|
222
222
|
}
|
|
223
|
+
.status-row {
|
|
224
|
+
display: flex;
|
|
225
|
+
flex-wrap: wrap;
|
|
226
|
+
gap: 10px;
|
|
227
|
+
align-items: center;
|
|
228
|
+
}
|
|
229
|
+
.status-pill {
|
|
230
|
+
display: inline-flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
gap: 8px;
|
|
233
|
+
padding: 8px 12px;
|
|
234
|
+
border: 1px solid var(--line);
|
|
235
|
+
background: rgba(255,255,255,0.78);
|
|
236
|
+
color: var(--ink);
|
|
237
|
+
letter-spacing: 0.08em;
|
|
238
|
+
text-transform: uppercase;
|
|
239
|
+
font-size: 12px;
|
|
240
|
+
}
|
|
241
|
+
.status-pill::before {
|
|
242
|
+
content: "";
|
|
243
|
+
width: 9px;
|
|
244
|
+
height: 9px;
|
|
245
|
+
border-radius: 999px;
|
|
246
|
+
background: #7a6d61;
|
|
247
|
+
}
|
|
248
|
+
.status-pill.is-active::before {
|
|
249
|
+
background: var(--accent);
|
|
250
|
+
box-shadow: 0 0 0 4px rgba(159, 61, 36, 0.12);
|
|
251
|
+
}
|
|
252
|
+
.developer-panel {
|
|
253
|
+
background:
|
|
254
|
+
linear-gradient(135deg, rgba(159, 61, 36, 0.11), rgba(255,255,255,0.68)),
|
|
255
|
+
rgba(255,255,255,0.62);
|
|
256
|
+
}
|
|
223
257
|
.key-list, .attachment-list {
|
|
224
258
|
display: grid;
|
|
225
259
|
gap: 12px;
|
|
@@ -402,6 +436,21 @@ export function renderSettingsPage(input) {
|
|
|
402
436
|
data-copy-content='${escapeAttribute(input.developerSkill)}'
|
|
403
437
|
data-copy-label="Developer SKILL.md"
|
|
404
438
|
>Developer SKILL.md</button>
|
|
439
|
+
` : "";
|
|
440
|
+
const developerPanel = input.isDeveloper ? `
|
|
441
|
+
<section class="settings-panel developer-panel">
|
|
442
|
+
<div class="card-head">
|
|
443
|
+
<div>
|
|
444
|
+
<div class="pill">Developer Access</div>
|
|
445
|
+
<h2>Template developer tools are enabled</h2>
|
|
446
|
+
</div>
|
|
447
|
+
<div class="status-pill is-active">Developer</div>
|
|
448
|
+
</div>
|
|
449
|
+
<p class="helper">This account can submit template sources and use the developer workflow. The <code>Developer SKILL.md</code> prompt is available here for fast copy into your agent tooling.</p>
|
|
450
|
+
<div class="toolbar">
|
|
451
|
+
${developerSkillButton}
|
|
452
|
+
</div>
|
|
453
|
+
</section>
|
|
405
454
|
` : "";
|
|
406
455
|
return shell({
|
|
407
456
|
title: "Settings",
|
|
@@ -423,7 +472,10 @@ export function renderSettingsPage(input) {
|
|
|
423
472
|
<div class="pill">Profile</div>
|
|
424
473
|
<h2>Workspace identity</h2>
|
|
425
474
|
</div>
|
|
426
|
-
<div class="
|
|
475
|
+
<div class="status-row">
|
|
476
|
+
<div class="status-pill ${input.isPaidPlan ? "is-active" : ""}">${input.isPaidPlan ? "Paid plan" : "Inactive plan"}</div>
|
|
477
|
+
<div class="status-pill ${input.isDeveloper ? "is-active" : ""}">${input.isDeveloper ? "Developer" : "Standard"}</div>
|
|
478
|
+
</div>
|
|
427
479
|
</div>
|
|
428
480
|
<form method="post" action="/settings/profile">
|
|
429
481
|
<label for="settings-email">Email</label>
|
|
@@ -440,10 +492,11 @@ export function renderSettingsPage(input) {
|
|
|
440
492
|
</div>
|
|
441
493
|
</form>
|
|
442
494
|
</section>
|
|
495
|
+
${developerPanel}
|
|
443
496
|
<section class="settings-panel">
|
|
444
497
|
<div class="pill">Vidfarm API</div>
|
|
445
|
-
<h2>Your
|
|
446
|
-
<p class="helper">Use this key with the <code>vidfarm-user-id</code> header pair when calling the API directly.</p>
|
|
498
|
+
<h2>Your Vidfarm API key</h2>
|
|
499
|
+
<p class="helper">Use this key with the <code>vidfarm-user-id</code> header pair when calling the Vidfarm API directly.</p>
|
|
447
500
|
<label for="vidfarm-api-key">Current API key</label>
|
|
448
501
|
<div class="secret-wrap">
|
|
449
502
|
<input id="vidfarm-api-key" type="password" value="${escapeHtml(input.vidfarmApiKey)}" readonly />
|
|
@@ -457,7 +510,6 @@ export function renderSettingsPage(input) {
|
|
|
457
510
|
data-copy-content='${escapeAttribute(input.directorSkill)}'
|
|
458
511
|
data-copy-label="Director SKILL.md"
|
|
459
512
|
>Director SKILL.md</button>
|
|
460
|
-
${developerSkillButton}
|
|
461
513
|
</div>
|
|
462
514
|
</section>
|
|
463
515
|
<section class="settings-panel">
|
|
@@ -506,7 +558,7 @@ export function renderSettingsPage(input) {
|
|
|
506
558
|
<section class="settings-panel">
|
|
507
559
|
<div class="pill">Attachments</div>
|
|
508
560
|
<h2>Shared files</h2>
|
|
509
|
-
<p class="helper">Uploads are stored under your <code>user
|
|
561
|
+
<p class="helper">Uploads are stored under your <code>user/<user_id>/*</code> namespace and can be opened via public read URLs.</p>
|
|
510
562
|
<form method="post" action="/settings/attachments" enctype="multipart/form-data">
|
|
511
563
|
<label for="settings-files">Images, video, audio, PDF, Markdown, or text</label>
|
|
512
564
|
<input id="settings-files" type="file" name="files" multiple accept="image/*,video/*,audio/*,.pdf,.md,.txt,text/markdown,text/plain,application/pdf" />
|
package/dist/src/app.js
CHANGED
|
@@ -70,6 +70,17 @@ const listJobsQuerySchema = z.object({
|
|
|
70
70
|
function getLoginMode(value) {
|
|
71
71
|
return value === "password" ? "password" : "otp";
|
|
72
72
|
}
|
|
73
|
+
function readRootSkillFile(...filenames) {
|
|
74
|
+
for (const filename of filenames) {
|
|
75
|
+
try {
|
|
76
|
+
return readFileSync(path.resolve(filename), "utf8");
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
73
84
|
const allowedAttachmentExtensions = new Set([
|
|
74
85
|
".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg",
|
|
75
86
|
".mp4", ".mov", ".webm", ".m4v",
|
|
@@ -361,23 +372,9 @@ app.get("/settings", (c) => {
|
|
|
361
372
|
if (!customer) {
|
|
362
373
|
return redirect(c, "/login");
|
|
363
374
|
}
|
|
364
|
-
const directorSkill = (
|
|
365
|
-
try {
|
|
366
|
-
return readFileSync(path.resolve("SKILL.user.md"), "utf8");
|
|
367
|
-
}
|
|
368
|
-
catch {
|
|
369
|
-
return "";
|
|
370
|
-
}
|
|
371
|
-
})();
|
|
375
|
+
const directorSkill = readRootSkillFile("SKILL.director.md", "SKILL.user.md");
|
|
372
376
|
const developerSkill = customer.isDeveloper
|
|
373
|
-
? (
|
|
374
|
-
try {
|
|
375
|
-
return readFileSync(path.resolve("SKILL.developer.md"), "utf8");
|
|
376
|
-
}
|
|
377
|
-
catch {
|
|
378
|
-
return null;
|
|
379
|
-
}
|
|
380
|
-
})()
|
|
377
|
+
? readRootSkillFile("SKILL.developer.md") || null
|
|
381
378
|
: null;
|
|
382
379
|
return c.html(renderSettingsPage({
|
|
383
380
|
notice: c.req.query("notice") ?? null,
|
|
@@ -476,7 +473,7 @@ app.post("/settings/attachments", async (c) => {
|
|
|
476
473
|
const arrayBuffer = await file.arrayBuffer();
|
|
477
474
|
const buffer = Buffer.from(arrayBuffer);
|
|
478
475
|
const attachmentId = createId("att");
|
|
479
|
-
const storageKey =
|
|
476
|
+
const storageKey = storage.userAttachmentKey(customer.id, attachmentId, fileName);
|
|
480
477
|
const stored = await storage.putBuffer(storageKey, buffer, contentType, { publicRead: true });
|
|
481
478
|
database.createUserAttachment({
|
|
482
479
|
id: attachmentId,
|
|
@@ -610,14 +607,17 @@ function buildAbsoluteUrl(c, pathname) {
|
|
|
610
607
|
}
|
|
611
608
|
function resolveTemplateAboutStorageKey(templateId, entry) {
|
|
612
609
|
const normalizedEntry = entry.replace(/^\/+/, "");
|
|
610
|
+
const templateAboutPrefix = storage.templateAboutKey(templateId, "");
|
|
613
611
|
if (!/^https?:\/\//i.test(entry)) {
|
|
614
|
-
|
|
612
|
+
if (normalizedEntry.startsWith("templates/")) {
|
|
613
|
+
return normalizedEntry;
|
|
614
|
+
}
|
|
615
615
|
if (normalizedEntry.startsWith(templateAboutPrefix)) {
|
|
616
616
|
return normalizedEntry;
|
|
617
617
|
}
|
|
618
618
|
return normalizedEntry.startsWith("about/")
|
|
619
|
-
?
|
|
620
|
-
:
|
|
619
|
+
? joinStoragePath("templates", templateId, normalizedEntry)
|
|
620
|
+
: storage.templateAboutKey(templateId, normalizedEntry);
|
|
621
621
|
}
|
|
622
622
|
try {
|
|
623
623
|
const url = new URL(entry);
|
|
@@ -657,7 +657,7 @@ async function serveTemplateAboutAsset(c, templateId, assetPath) {
|
|
|
657
657
|
if (!normalizedAssetPath) {
|
|
658
658
|
return c.json({ error: "Template about asset path is required" }, 400);
|
|
659
659
|
}
|
|
660
|
-
const key =
|
|
660
|
+
const key = storage.templateAboutKey(template.id, normalizedAssetPath);
|
|
661
661
|
const readUrl = await storage.getReadUrl(key);
|
|
662
662
|
if (config.STORAGE_DRIVER === "s3" && readUrl) {
|
|
663
663
|
return c.redirect(readUrl, 302);
|
|
@@ -742,7 +742,10 @@ function resolveTemplateAboutMediaUrl(c, templateId, entry) {
|
|
|
742
742
|
return entry;
|
|
743
743
|
}
|
|
744
744
|
const normalizedEntry = entry.replace(/^\/+/, "");
|
|
745
|
-
|
|
745
|
+
if (normalizedEntry.startsWith("templates/")) {
|
|
746
|
+
return buildAbsoluteUrl(c, `/template-media?key=${encodeURIComponent(normalizedEntry)}`);
|
|
747
|
+
}
|
|
748
|
+
const templateAboutPrefix = storage.templateAboutKey(templateId, "");
|
|
746
749
|
const aboutPath = normalizedEntry.startsWith(templateAboutPrefix)
|
|
747
750
|
? `about/${normalizedEntry.slice(templateAboutPrefix.length)}`
|
|
748
751
|
: normalizedEntry.startsWith("about/")
|
|
@@ -750,6 +753,13 @@ function resolveTemplateAboutMediaUrl(c, templateId, entry) {
|
|
|
750
753
|
: `about/${normalizedEntry}`;
|
|
751
754
|
return buildAbsoluteUrl(c, `${TEMPLATES_PREFIX}/${templateId}/${aboutPath}`);
|
|
752
755
|
}
|
|
756
|
+
function joinStoragePath(...parts) {
|
|
757
|
+
return parts
|
|
758
|
+
.flatMap((part) => part.split("/"))
|
|
759
|
+
.map((part) => part.trim())
|
|
760
|
+
.filter(Boolean)
|
|
761
|
+
.join("/");
|
|
762
|
+
}
|
|
753
763
|
app.get(TEMPLATES_PREFIX, (c) => c.json({
|
|
754
764
|
templates: templateRegistry.list().map((template) => ({
|
|
755
765
|
...serializeTemplate(c, template),
|
package/dist/src/config.js
CHANGED
|
@@ -26,7 +26,7 @@ const schema = z.object({
|
|
|
26
26
|
AWS_SECRET_ACCESS_KEY: z.string().optional(),
|
|
27
27
|
PUBLIC_BASE_URL: z.string().optional(),
|
|
28
28
|
RESEND_API_KEY: z.string().optional(),
|
|
29
|
-
RESEND_FROM_EMAIL: z.string().default("
|
|
29
|
+
RESEND_FROM_EMAIL: z.string().default("vidfarm@fwd.zoomgtm.com"),
|
|
30
30
|
OPENAI_API_KEY: z.string().optional(),
|
|
31
31
|
OPENROUTER_API_KEY: z.string().optional(),
|
|
32
32
|
GEMINI_API_KEY: z.string().optional(),
|
package/dist/src/context.js
CHANGED
|
@@ -3,7 +3,7 @@ import { database } from "./db.js";
|
|
|
3
3
|
import { createId } from "./lib/ids.js";
|
|
4
4
|
export function createTemplateJobContext(input) {
|
|
5
5
|
const templateConfig = database.getTemplateConfig(input.customer.id, input.template.id);
|
|
6
|
-
const prefix =
|
|
6
|
+
const prefix = input.storage.templateJobPrefix(input.template.id, input.customer.id, input.job.id);
|
|
7
7
|
return {
|
|
8
8
|
env: config.isProduction ? "production" : "development",
|
|
9
9
|
customer: input.customer,
|
|
@@ -14,6 +14,21 @@ export class StorageService {
|
|
|
14
14
|
constructor() {
|
|
15
15
|
mkdirSync(this.localRoot, { recursive: true });
|
|
16
16
|
}
|
|
17
|
+
userAttachmentKey(customerId, attachmentId, fileName) {
|
|
18
|
+
return joinStorageKey("user", customerId, "attachments", attachmentId, fileName);
|
|
19
|
+
}
|
|
20
|
+
developerAttachmentKey(customerId, attachmentId, fileName) {
|
|
21
|
+
return joinStorageKey("developer", customerId, "attachments", attachmentId, fileName);
|
|
22
|
+
}
|
|
23
|
+
templateJobPrefix(templateId, customerId, jobId) {
|
|
24
|
+
return joinStorageKey("templates", templateId, "users", customerId, "jobs", jobId);
|
|
25
|
+
}
|
|
26
|
+
templateJobKey(templateId, customerId, jobId, key) {
|
|
27
|
+
return joinStorageKey(this.templateJobPrefix(templateId, customerId, jobId), key);
|
|
28
|
+
}
|
|
29
|
+
templateAboutKey(templateId, assetPath) {
|
|
30
|
+
return joinStorageKey("templates", templateId, "about", assetPath);
|
|
31
|
+
}
|
|
17
32
|
async putJson(key, value, options) {
|
|
18
33
|
const body = JSON.stringify(value, null, 2);
|
|
19
34
|
return this.putBuffer(key, Buffer.from(body, "utf8"), "application/json", options);
|
|
@@ -86,6 +101,13 @@ export class StorageService {
|
|
|
86
101
|
return this.getPublicUrl(key);
|
|
87
102
|
}
|
|
88
103
|
}
|
|
104
|
+
function joinStorageKey(...parts) {
|
|
105
|
+
return parts
|
|
106
|
+
.flatMap((part) => part.split("/"))
|
|
107
|
+
.map((part) => part.trim())
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.join("/");
|
|
110
|
+
}
|
|
89
111
|
function inferContentType(filePath) {
|
|
90
112
|
switch (path.extname(filePath).toLowerCase()) {
|
|
91
113
|
case ".json":
|
|
@@ -11,7 +11,7 @@ const TEMPLATE_ID = "4c7a7e1a-7f35-4f30-9f86-9c8a63c7f2db";
|
|
|
11
11
|
const TEMPLATE_SLUG_ID = "template_0000";
|
|
12
12
|
const COMPOSITION_ID = "template-0000";
|
|
13
13
|
const TEMPLATE_PREVIEW_MEDIA = [
|
|
14
|
-
"
|
|
14
|
+
"templates/template-0000/about/preview-01.jpg",
|
|
15
15
|
];
|
|
16
16
|
const FRAME = { width: 1080, height: 1920 };
|
|
17
17
|
const TIKTOK_SAFE_AREA = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mevdragon/vidfarm-devcli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Developer CLI for running the Vidfarm local template platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"vidfarm-devcli": "dist/src/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
|
-
"dist",
|
|
11
|
+
"dist/src",
|
|
12
|
+
"dist/templates/template_0000",
|
|
12
13
|
"templates/template_0000",
|
|
13
14
|
"README.md",
|
|
14
15
|
"SKILL.developer.md",
|
|
15
|
-
"
|
|
16
|
-
"AWS_REMOTION_HANDOFF.md",
|
|
16
|
+
"GETTING_STARTED.developers.md",
|
|
17
17
|
".env.example"
|
|
18
18
|
],
|
|
19
19
|
"publishConfig": {
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Standalone GitHub-distributable package for the Vidfarm `template_0000` starter template.
|
|
4
4
|
|
|
5
|
-
This package exists
|
|
5
|
+
This package exists to give third-party developers a concrete example of the Vidfarm template contract.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- preserve the exact checked-in config and build shape the release admin will later promote to shared Remotion AWS and the production Docker image
|
|
7
|
+
Developers should treat this repo as an authoring and review unit.
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
When a template is ready, it is handed off for Vidfarm admin review and approval before it becomes available on the hosted platform.
|
|
11
10
|
|
|
12
11
|
Every new template should keep its source-format research checked in:
|
|
13
12
|
|
|
@@ -15,33 +14,21 @@ Every new template should keep its source-format research checked in:
|
|
|
15
14
|
- `research/preview/` for the screenshots or source video the DNA analyzers inspect
|
|
16
15
|
- `src/template-dna.ts` for the generated viral and visual DNA that feed the published template metadata
|
|
17
16
|
|
|
18
|
-
The production release flow is:
|
|
19
|
-
|
|
20
|
-
1. developer pushes template code to GitHub
|
|
21
|
-
2. admin reviews the repo and selects a commit from `production`
|
|
22
|
-
3. admin publishes the approved Remotion site bundle to shared AWS
|
|
23
|
-
4. admin imports and activates the approved commit in Vidfarm
|
|
24
|
-
5. admin rebuilds and redeploys the production Docker image
|
|
25
|
-
|
|
26
|
-
Template authors do not publish directly to shared Remotion Lambda and do not directly promote templates into production Docker.
|
|
27
|
-
|
|
28
17
|
Production integration settings are checked into `template.config.json`. AI agents and developers should treat that file as the source of truth for:
|
|
29
18
|
|
|
30
19
|
- project identity
|
|
31
20
|
- `template_id` as the self-issued UUIDv4 platform identifier
|
|
32
21
|
- `slug_id` as the human-readable stable slug
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- Remotion region/function/bucket/site/composition settings
|
|
36
|
-
- release control expectations for admin promotion
|
|
22
|
+
- the template module path
|
|
23
|
+
- the local Remotion composition settings used by the starter template
|
|
37
24
|
|
|
38
25
|
## Included
|
|
39
26
|
|
|
40
27
|
- `SKILL.md` for customer AI-agent usage
|
|
41
28
|
- `src/template.ts` for the Vidfarm platform contract
|
|
42
|
-
- `src/remotion/*` for local
|
|
29
|
+
- `src/remotion/*` for local video rendering
|
|
43
30
|
- `src/lib/images.ts` for non-cropping portrait normalization
|
|
44
|
-
- `composition.json` sample props for
|
|
31
|
+
- `composition.json` sample props for local render tests
|
|
45
32
|
|
|
46
33
|
## Template behavior
|
|
47
34
|
|
|
@@ -87,35 +74,3 @@ vidfarm analyze-visual-dna --template-dir .
|
|
|
87
74
|
```
|
|
88
75
|
|
|
89
76
|
If you scaffold a template with `vidfarm generate-template` and provide `--source-preview-dir`, the CLI will run both analyzers automatically unless `--skip-dna-analysis` is set.
|
|
90
|
-
|
|
91
|
-
## Shared Remotion AWS
|
|
92
|
-
|
|
93
|
-
Expected shared infra:
|
|
94
|
-
|
|
95
|
-
- region: stored in `template.config.json`
|
|
96
|
-
- function: stored in `template.config.json`
|
|
97
|
-
- bucket: stored in `template.config.json`
|
|
98
|
-
|
|
99
|
-
The only runtime secrets expected from the execution environment are AWS credentials. The production Remotion topology is intentionally checked into `template.config.json`, not spread across `.env` values.
|
|
100
|
-
|
|
101
|
-
These shared-AWS operations are release-admin tasks. Template developers should not run them against the shared production AWS account.
|
|
102
|
-
|
|
103
|
-
Release admin create-site:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
npm run admin:create-site
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Release admin cloud render smoke test:
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
npm run admin:render:cloud
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Release admin cloud render from a real stage-1 manifest:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
npm run admin:render:cloud -- --manifest /abs/path/to/template-0000.json
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Use the manifest mode when you want the cloud render verification to include the actual composited slide frames with text overlays, not just the static sample props.
|
|
@@ -5,8 +5,8 @@ Use this template when the customer wants a fast vertical slideshow for TikTok-s
|
|
|
5
5
|
Operational rule:
|
|
6
6
|
|
|
7
7
|
- template developers author and test this template locally
|
|
8
|
-
-
|
|
9
|
-
-
|
|
8
|
+
- the hosted platform later runs the approved template behind the standard Vidfarm API wrapper
|
|
9
|
+
- a Vidfarm admin reviews and approves the template before it is made available in production
|
|
10
10
|
|
|
11
11
|
Inputs:
|
|
12
12
|
|
|
@@ -51,7 +51,7 @@ Allowed text background colors:
|
|
|
51
51
|
- `light_gray`
|
|
52
52
|
- `dark_gray`
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Typical routes for this template:
|
|
55
55
|
|
|
56
56
|
- `GET /templates/template_0000`
|
|
57
57
|
- `GET /templates/template_0000/skill`
|
|
@@ -2,19 +2,16 @@
|
|
|
2
2
|
"name": "vidfarm_template_0000",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"description": "Standalone Vidfarm template_0000 project for
|
|
5
|
+
"description": "Standalone Vidfarm template_0000 starter project for local template authoring.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
9
9
|
"build": "tsc -p tsconfig.json",
|
|
10
|
-
"studio": "remotion studio src/remotion/index.tsx"
|
|
11
|
-
"admin:create-site": "node ./scripts/create-site.mjs",
|
|
12
|
-
"admin:render:cloud": "node ./scripts/render-cloud.mjs"
|
|
10
|
+
"studio": "remotion studio src/remotion/index.tsx"
|
|
13
11
|
},
|
|
14
12
|
"dependencies": {
|
|
15
13
|
"@remotion/bundler": "4.0.355",
|
|
16
14
|
"@remotion/cli": "4.0.355",
|
|
17
|
-
"@remotion/lambda": "4.0.355",
|
|
18
15
|
"@remotion/renderer": "4.0.355",
|
|
19
16
|
"react": "^18.3.1",
|
|
20
17
|
"react-dom": "^18.3.1",
|
|
@@ -22,6 +19,7 @@
|
|
|
22
19
|
"sharp": "^0.34.2"
|
|
23
20
|
},
|
|
24
21
|
"devDependencies": {
|
|
22
|
+
"@mevdragon/vidfarm-devcli": "^0.2.2",
|
|
25
23
|
"@types/node": "^24.0.1",
|
|
26
24
|
"@types/react": "^18.3.23",
|
|
27
25
|
"@types/react-dom": "^18.3.7",
|