@growthub/cli 0.8.1 → 0.8.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/assets/worker-kits/growthub-creative-video-pipeline-v1/.env.example +28 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/QUICKSTART.md +118 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/SKILL.md +103 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/.env.example +20 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/README.md +33 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/app/api/pipeline/route.js +27 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/app/globals.css +203 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/app/layout.jsx +14 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/app/page.jsx +131 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/app/settings/keys/page.jsx +154 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/lib/adapters/env.js +14 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/lib/adapters/generative/index.js +31 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/lib/domain/pipeline.js +30 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/next.config.js +10 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/package-lock.json +17 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/package.json +17 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/postcss.config.mjs +3 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/apps/creative-video-pipeline/vercel.json +5 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/brands/NEW-CLIENT.md +21 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/brands/_template/brand-kit.md +123 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/brands/growthub/brand-kit.md +123 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/bundles/growthub-creative-video-pipeline-v1.json +83 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/docs/adapter-contracts.md +73 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/docs/governed-workspace-primitives.md +50 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/docs/pipeline-architecture.md +61 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/docs/starter-kit-overview.md +33 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/docs/vercel-deployment.md +42 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/examples/pipeline-brief-sample.md +56 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/growthub-meta/README.md +9 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/growthub-meta/kit-standard.md +24 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/helpers/README.md +8 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/helpers/check-generative-adapter.sh +41 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/helpers/run-pipeline.sh +30 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/kit.json +148 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/output/README.md +23 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/output-standards.md +63 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/runtime-assumptions.md +61 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/setup/check-deps.sh +63 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/setup/clone-fork.sh +18 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/setup/install-skill.sh +10 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/setup/verify-env.mjs +50 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/skills/README.md +11 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/skills/brief-generation/SKILL.md +42 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/skills/generative-execution/SKILL.md +86 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/skills/video-edit/SKILL.md +41 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/skills.md +302 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/index.html +12 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/package-lock.json +20 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/package.json +20 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/serve.mjs +41 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/src/App.jsx +210 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/src/app.css +194 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/src/main.jsx +10 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/studio/vite.config.js +8 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/templates/edit-plan.md +66 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/templates/generative-plan.md +83 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/templates/pipeline-brief.md +129 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/templates/project.md +68 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/templates/self-eval.md +67 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/validation-checklist.md +52 -0
- package/assets/worker-kits/growthub-creative-video-pipeline-v1/workers/creative-video-pipeline-operator/CLAUDE.md +109 -0
- package/dist/index.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Creative Video Pipeline</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "growthub-creative-video-pipeline-studio",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"lockfileVersion": 3,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"": {
|
|
8
|
+
"name": "growthub-creative-video-pipeline-studio",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"react": "^18.3.1",
|
|
12
|
+
"react-dom": "^18.3.1"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
16
|
+
"vite": "^5.4.2"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "growthub-creative-video-pipeline-studio",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"serve": "node serve.mjs"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"react": "^18.3.1",
|
|
14
|
+
"react-dom": "^18.3.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
18
|
+
"vite": "^5.4.2"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Minimal static server for the built Vite shell.
|
|
3
|
+
// Usage: node serve.mjs [--port 5180]
|
|
4
|
+
import http from "node:http";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const DIST = path.resolve(__dirname, "dist");
|
|
11
|
+
const PORT = Number(process.env.PORT ?? 5180);
|
|
12
|
+
|
|
13
|
+
const mime = {
|
|
14
|
+
".html": "text/html; charset=utf-8",
|
|
15
|
+
".js": "application/javascript; charset=utf-8",
|
|
16
|
+
".css": "text/css; charset=utf-8",
|
|
17
|
+
".svg": "image/svg+xml",
|
|
18
|
+
".json": "application/json; charset=utf-8",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function serve(req, res) {
|
|
22
|
+
const url = decodeURIComponent(req.url?.split("?")[0] ?? "/");
|
|
23
|
+
const file = url === "/" ? "/index.html" : url;
|
|
24
|
+
const full = path.resolve(DIST, "." + file);
|
|
25
|
+
if (!full.startsWith(DIST)) { res.statusCode = 403; res.end("Forbidden"); return; }
|
|
26
|
+
fs.readFile(full, (err, buf) => {
|
|
27
|
+
if (err) {
|
|
28
|
+
fs.readFile(path.resolve(DIST, "index.html"), (err2, fallback) => {
|
|
29
|
+
if (err2) { res.statusCode = 404; res.end("Not found"); return; }
|
|
30
|
+
res.setHeader("Content-Type", mime[".html"]); res.end(fallback);
|
|
31
|
+
});
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
res.setHeader("Content-Type", mime[path.extname(full)] ?? "application/octet-stream");
|
|
35
|
+
res.end(buf);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
http.createServer(serve).listen(PORT, () => {
|
|
40
|
+
console.log(`[creative-video-pipeline-studio] serving ${DIST} on http://localhost:${PORT}`);
|
|
41
|
+
});
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
const stages = [
|
|
4
|
+
{
|
|
5
|
+
id: "brief",
|
|
6
|
+
label: "Brief",
|
|
7
|
+
step: "01",
|
|
8
|
+
description: "Brand kit → scene structure → hooks → pipeline-brief.md",
|
|
9
|
+
outputPath: "output/<client>/<project>/brief/pipeline-brief.md",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "generative",
|
|
13
|
+
label: "Generate",
|
|
14
|
+
step: "02",
|
|
15
|
+
description: "growthub pipeline execute → image/video artifacts",
|
|
16
|
+
outputPath: "output/<client>/<project>/generative/manifest.json",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "edit",
|
|
20
|
+
label: "Edit",
|
|
21
|
+
step: "03",
|
|
22
|
+
description: "video-use fork → ElevenLabs Scribe → EDL → FFmpeg → final.mp4",
|
|
23
|
+
outputPath: "output/<client>/<project>/final/final.mp4",
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const adapterDocs = [
|
|
28
|
+
["growthub-pipeline", "Routes through growthub pipeline execute + CMS video-generation node. Requires GROWTHUB_BRIDGE_ACCESS_TOKEN."],
|
|
29
|
+
["byo-api-key", "Routes through explicit provider SDK. Set VIDEO_MODEL_PROVIDER (veo | fal | runway) + provider key."],
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const providerKeys = [
|
|
33
|
+
["ELEVENLABS_API_KEY", "Required for Stage 3 — ElevenLabs Scribe transcription", true],
|
|
34
|
+
["GROWTHUB_BRIDGE_ACCESS_TOKEN", "growthub-pipeline adapter — from growthub auth login", false],
|
|
35
|
+
["GOOGLE_AI_API_KEY", "BYOK: VIDEO_MODEL_PROVIDER=veo", false],
|
|
36
|
+
["FAL_API_KEY", "BYOK: VIDEO_MODEL_PROVIDER=fal", false],
|
|
37
|
+
["RUNWAY_API_KEY", "BYOK: VIDEO_MODEL_PROVIDER=runway", false],
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export default function App() {
|
|
41
|
+
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<main className="shell">
|
|
45
|
+
<aside className="sidebar">
|
|
46
|
+
<div className="brand">
|
|
47
|
+
<span className="brand-mark">CV</span>
|
|
48
|
+
<span>Creative Video Pipeline</span>
|
|
49
|
+
</div>
|
|
50
|
+
<nav className="nav">
|
|
51
|
+
<a href="#pipeline">Pipeline</a>
|
|
52
|
+
<a href="#brief">Brief</a>
|
|
53
|
+
<a href="#generative">Generative</a>
|
|
54
|
+
<a href="#edit">Edit</a>
|
|
55
|
+
<a href="#settings" onClick={(e) => { e.preventDefault(); setSettingsOpen(!settingsOpen); }}>
|
|
56
|
+
Settings
|
|
57
|
+
</a>
|
|
58
|
+
</nav>
|
|
59
|
+
<div className="sidebar-footer">
|
|
60
|
+
<span className="status-dot" />
|
|
61
|
+
Local Vite shell
|
|
62
|
+
</div>
|
|
63
|
+
</aside>
|
|
64
|
+
|
|
65
|
+
<section className="main">
|
|
66
|
+
<div className="utility-bar">
|
|
67
|
+
<div>
|
|
68
|
+
<strong>Growthub Creative Video Pipeline</strong>
|
|
69
|
+
<span>Brief → Generate → Edit — governed workspace with Vite local shell and Vercel app parity.</span>
|
|
70
|
+
</div>
|
|
71
|
+
<div className="utility-actions">
|
|
72
|
+
<a href="#settings" onClick={(e) => { e.preventDefault(); setSettingsOpen(!settingsOpen); }}>
|
|
73
|
+
API Keys
|
|
74
|
+
</a>
|
|
75
|
+
<span className="pill">kit v1</span>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<header className="page-heading" id="pipeline">
|
|
80
|
+
<span className="eyebrow">Three-stage pipeline</span>
|
|
81
|
+
<h1>Brief to final video.</h1>
|
|
82
|
+
<p>
|
|
83
|
+
Brand-grounded brief, generative images and video via the growthub pipeline or BYOK provider, and
|
|
84
|
+
transcript-anchored editing via the video-use fork — all in one governed workspace.
|
|
85
|
+
</p>
|
|
86
|
+
</header>
|
|
87
|
+
|
|
88
|
+
<section className="pipeline-strip" id="pipeline-stages">
|
|
89
|
+
{stages.map((stage) => (
|
|
90
|
+
<article className="stage-card" key={stage.id} id={stage.id}>
|
|
91
|
+
<span className="stage-step">{stage.step}</span>
|
|
92
|
+
<strong>{stage.label}</strong>
|
|
93
|
+
<p>{stage.description}</p>
|
|
94
|
+
<code>{stage.outputPath}</code>
|
|
95
|
+
</article>
|
|
96
|
+
))}
|
|
97
|
+
</section>
|
|
98
|
+
|
|
99
|
+
<section className="hero-grid">
|
|
100
|
+
<article className="hero-card primary">
|
|
101
|
+
<span>Adapter</span>
|
|
102
|
+
<strong>growthub-pipeline</strong>
|
|
103
|
+
<p>Primary path. Routes through hosted CMS video-generation node (veo-3.1-generate-001). Requires Growthub auth.</p>
|
|
104
|
+
</article>
|
|
105
|
+
<article className="hero-card">
|
|
106
|
+
<span>BYOK</span>
|
|
107
|
+
<strong>byo-api-key</strong>
|
|
108
|
+
<p>Secondary path. Explicit provider keys (Veo / fal / Runway). Normalizes to same artifact contract.</p>
|
|
109
|
+
</article>
|
|
110
|
+
<article className="hero-card">
|
|
111
|
+
<span>Edit</span>
|
|
112
|
+
<strong>video-use fork</strong>
|
|
113
|
+
<p>Stage 3 delegates to VIDEO_USE_HOME. ElevenLabs Scribe + FFmpeg render + self-eval loop.</p>
|
|
114
|
+
</article>
|
|
115
|
+
</section>
|
|
116
|
+
|
|
117
|
+
<section className="adapter-grid">
|
|
118
|
+
{adapterDocs.map(([name, desc]) => (
|
|
119
|
+
<article className="card" key={name}>
|
|
120
|
+
<h3>{name}</h3>
|
|
121
|
+
<p>{desc}</p>
|
|
122
|
+
</article>
|
|
123
|
+
))}
|
|
124
|
+
</section>
|
|
125
|
+
|
|
126
|
+
<section className="ops-strip">
|
|
127
|
+
<article>
|
|
128
|
+
<span>01</span>
|
|
129
|
+
<strong>Brand Kit</strong>
|
|
130
|
+
<p>Scene structure and hooks sourced from brand-kit.md — not memory.</p>
|
|
131
|
+
</article>
|
|
132
|
+
<article>
|
|
133
|
+
<span>02</span>
|
|
134
|
+
<strong>CLI Pipeline</strong>
|
|
135
|
+
<p>growthub pipeline execute routes to CMS video-generation node.</p>
|
|
136
|
+
</article>
|
|
137
|
+
<article>
|
|
138
|
+
<span>03</span>
|
|
139
|
+
<strong>video-use Fork</strong>
|
|
140
|
+
<p>Scribe → word-boundary EDL → FFmpeg render → final.mp4.</p>
|
|
141
|
+
</article>
|
|
142
|
+
<article>
|
|
143
|
+
<span>04</span>
|
|
144
|
+
<strong>Governed</strong>
|
|
145
|
+
<p>Every stage appends to project.md and trace.jsonl.</p>
|
|
146
|
+
</article>
|
|
147
|
+
</section>
|
|
148
|
+
|
|
149
|
+
{settingsOpen && (
|
|
150
|
+
<section className="settings-panel" id="settings">
|
|
151
|
+
<div className="settings-header">
|
|
152
|
+
<h2>API Key Settings</h2>
|
|
153
|
+
<p>
|
|
154
|
+
Configure the generative adapter and provider keys. Both paths normalize to the same
|
|
155
|
+
GenerativeArtifact[] object. Set keys in your fork's <code>.env</code> file.
|
|
156
|
+
</p>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<div className="setup-grid">
|
|
160
|
+
<article className="setup-card">
|
|
161
|
+
<span>Primary</span>
|
|
162
|
+
<strong>Growthub Pipeline</strong>
|
|
163
|
+
<p>Set <code>CREATIVE_VIDEO_PIPELINE_GENERATIVE_ADAPTER=growthub-pipeline</code> and authenticate via <code>growthub auth login</code>.</p>
|
|
164
|
+
<code>GROWTHUB_BRIDGE_ACCESS_TOKEN</code>
|
|
165
|
+
</article>
|
|
166
|
+
<article className="setup-card">
|
|
167
|
+
<span>Secondary</span>
|
|
168
|
+
<strong>BYOK Provider</strong>
|
|
169
|
+
<p>Set <code>CREATIVE_VIDEO_PIPELINE_GENERATIVE_ADAPTER=byo-api-key</code> and <code>VIDEO_MODEL_PROVIDER</code>.</p>
|
|
170
|
+
<code>GOOGLE_AI_API_KEY / FAL_API_KEY / RUNWAY_API_KEY</code>
|
|
171
|
+
</article>
|
|
172
|
+
<article className="setup-card">
|
|
173
|
+
<span>Required</span>
|
|
174
|
+
<strong>ElevenLabs Scribe</strong>
|
|
175
|
+
<p>Required for Stage 3 — word-level transcription for the video-use EDL pipeline.</p>
|
|
176
|
+
<code>ELEVENLABS_API_KEY</code>
|
|
177
|
+
</article>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<div className="key-list">
|
|
181
|
+
{providerKeys.map(([key, desc, required]) => (
|
|
182
|
+
<article className="key-row" key={key}>
|
|
183
|
+
<div>
|
|
184
|
+
<code>{key}</code>
|
|
185
|
+
<span className={`key-badge ${required ? "required" : "optional"}`}>
|
|
186
|
+
{required ? "required" : "conditional"}
|
|
187
|
+
</span>
|
|
188
|
+
</div>
|
|
189
|
+
<p>{desc}</p>
|
|
190
|
+
</article>
|
|
191
|
+
))}
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<p className="settings-note">
|
|
195
|
+
Keys are read from your fork's <code>.env</code> file. See <code>.env.example</code> for all available options.
|
|
196
|
+
Never commit API keys to the repo.
|
|
197
|
+
</p>
|
|
198
|
+
</section>
|
|
199
|
+
)}
|
|
200
|
+
</section>
|
|
201
|
+
|
|
202
|
+
<aside className="quick-actions">
|
|
203
|
+
<button onClick={() => setSettingsOpen(!settingsOpen)}>Configure API keys</button>
|
|
204
|
+
<button>View brief output</button>
|
|
205
|
+
<button>View generative output</button>
|
|
206
|
+
<button>Open final video</button>
|
|
207
|
+
</aside>
|
|
208
|
+
</main>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: dark;
|
|
3
|
+
--bg: #080b12;
|
|
4
|
+
--sidebar: #0d1118;
|
|
5
|
+
--panel: #111827;
|
|
6
|
+
--panel-soft: #0d1420;
|
|
7
|
+
--ink: #f7fafc;
|
|
8
|
+
--muted: #93a3b8;
|
|
9
|
+
--line: #223047;
|
|
10
|
+
--accent: #38bdf8;
|
|
11
|
+
--accent-soft: rgba(56, 189, 248, 0.12);
|
|
12
|
+
--good: #22c55e;
|
|
13
|
+
--warn: #f59e0b;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
* { box-sizing: border-box; }
|
|
17
|
+
html { scroll-behavior: smooth; }
|
|
18
|
+
body {
|
|
19
|
+
margin: 0;
|
|
20
|
+
background: var(--bg);
|
|
21
|
+
color: var(--ink);
|
|
22
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
23
|
+
}
|
|
24
|
+
a { color: inherit; }
|
|
25
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }
|
|
26
|
+
|
|
27
|
+
.shell {
|
|
28
|
+
min-height: 100vh;
|
|
29
|
+
display: grid;
|
|
30
|
+
grid-template-columns: 232px minmax(0, 1fr);
|
|
31
|
+
background: radial-gradient(circle at top right, rgba(56, 189, 248, 0.12), transparent 360px), var(--bg);
|
|
32
|
+
}
|
|
33
|
+
.sidebar {
|
|
34
|
+
position: sticky;
|
|
35
|
+
top: 0;
|
|
36
|
+
height: 100vh;
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
gap: 22px;
|
|
40
|
+
background: rgba(13, 17, 24, 0.96);
|
|
41
|
+
border-right: 1px solid var(--line);
|
|
42
|
+
padding: 22px 16px;
|
|
43
|
+
}
|
|
44
|
+
.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; }
|
|
45
|
+
.brand-mark {
|
|
46
|
+
width: 34px;
|
|
47
|
+
height: 34px;
|
|
48
|
+
display: grid;
|
|
49
|
+
place-items: center;
|
|
50
|
+
border-radius: 8px;
|
|
51
|
+
background: var(--accent);
|
|
52
|
+
color: #06111d;
|
|
53
|
+
font-size: 13px;
|
|
54
|
+
font-weight: 900;
|
|
55
|
+
}
|
|
56
|
+
.nav { display: grid; gap: 5px; }
|
|
57
|
+
.nav a {
|
|
58
|
+
color: #c6d1e1;
|
|
59
|
+
text-decoration: none;
|
|
60
|
+
padding: 9px 10px;
|
|
61
|
+
border-radius: 7px;
|
|
62
|
+
font-size: 14px;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
.nav a:hover { background: #172133; color: white; }
|
|
66
|
+
.sidebar-footer { margin-top: auto; display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; }
|
|
67
|
+
.status-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--good); box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.12); }
|
|
68
|
+
.main { width: min(100%, 1180px); padding: 30px; }
|
|
69
|
+
.utility-bar {
|
|
70
|
+
display: flex;
|
|
71
|
+
justify-content: space-between;
|
|
72
|
+
gap: 16px;
|
|
73
|
+
align-items: center;
|
|
74
|
+
margin-bottom: 20px;
|
|
75
|
+
padding: 12px 14px;
|
|
76
|
+
border: 1px solid var(--line);
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
background: rgba(17, 24, 39, 0.82);
|
|
79
|
+
}
|
|
80
|
+
.utility-bar strong { display: block; font-size: 14px; }
|
|
81
|
+
.utility-bar span, .page-heading p, .card p, .stage-card p, .setup-card p { color: var(--muted); line-height: 1.5; }
|
|
82
|
+
.utility-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
83
|
+
.utility-actions a, .pill {
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
min-height: 28px;
|
|
87
|
+
border: 1px solid var(--line);
|
|
88
|
+
border-radius: 999px;
|
|
89
|
+
padding: 5px 10px;
|
|
90
|
+
background: #0c1320;
|
|
91
|
+
color: #c9d7e8;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
}
|
|
96
|
+
.page-heading { margin-bottom: 22px; }
|
|
97
|
+
.page-heading h1 { margin: 4px 0 8px; font-size: clamp(32px, 5vw, 58px); line-height: 0.98; letter-spacing: 0; }
|
|
98
|
+
.page-heading p { max-width: 780px; margin: 0; }
|
|
99
|
+
.eyebrow { color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.12em; }
|
|
100
|
+
|
|
101
|
+
/* Pipeline strip — three stages */
|
|
102
|
+
.pipeline-strip {
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
105
|
+
gap: 14px;
|
|
106
|
+
margin-bottom: 22px;
|
|
107
|
+
}
|
|
108
|
+
.stage-card {
|
|
109
|
+
border: 1px solid var(--line);
|
|
110
|
+
border-radius: 8px;
|
|
111
|
+
background: rgba(17, 24, 39, 0.9);
|
|
112
|
+
padding: 18px;
|
|
113
|
+
}
|
|
114
|
+
.stage-step { color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; }
|
|
115
|
+
.stage-card strong { display: block; margin: 8px 0 6px; font-size: 18px; }
|
|
116
|
+
.stage-card code { display: block; margin-top: 10px; color: #9ab8d8; font-size: 11px; word-break: break-all; }
|
|
117
|
+
|
|
118
|
+
.hero-grid { display: grid; grid-template-columns: 1.2fr 0.9fr 0.9fr; gap: 14px; margin-bottom: 16px; }
|
|
119
|
+
.hero-card {
|
|
120
|
+
min-height: 160px;
|
|
121
|
+
padding: 18px;
|
|
122
|
+
border: 1px solid var(--line);
|
|
123
|
+
border-radius: 8px;
|
|
124
|
+
background: rgba(17, 24, 39, 0.9);
|
|
125
|
+
}
|
|
126
|
+
.hero-card.primary { background: linear-gradient(135deg, rgba(56, 189, 248, 0.18), rgba(17, 24, 39, 0.95)); }
|
|
127
|
+
.hero-card span { color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; }
|
|
128
|
+
.hero-card strong { display: block; margin-top: 10px; font-size: 28px; line-height: 1; }
|
|
129
|
+
.hero-card p { margin: 10px 0 0; color: var(--muted); line-height: 1.5; font-size: 13px; }
|
|
130
|
+
|
|
131
|
+
.adapter-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
|
|
132
|
+
.card { min-height: 100px; padding: 16px; border: 1px solid var(--line); border-radius: 8px; background: rgba(17, 24, 39, 0.9); }
|
|
133
|
+
.card h3 { margin: 0 0 8px; font-size: 14px; color: var(--accent); }
|
|
134
|
+
|
|
135
|
+
.ops-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 22px; }
|
|
136
|
+
.ops-strip article { padding: 14px; border: 1px solid var(--line); border-radius: 8px; background: rgba(13, 20, 32, 0.88); }
|
|
137
|
+
.ops-strip span { color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; }
|
|
138
|
+
.ops-strip strong { display: block; margin: 7px 0; font-size: 14px; }
|
|
139
|
+
|
|
140
|
+
/* Settings panel */
|
|
141
|
+
.settings-panel {
|
|
142
|
+
border: 1px solid var(--line);
|
|
143
|
+
border-radius: 8px;
|
|
144
|
+
background: rgba(13, 20, 32, 0.95);
|
|
145
|
+
padding: 22px;
|
|
146
|
+
margin-bottom: 22px;
|
|
147
|
+
}
|
|
148
|
+
.settings-header { margin-bottom: 18px; }
|
|
149
|
+
.settings-header h2 { margin: 0 0 8px; font-size: 20px; }
|
|
150
|
+
.settings-header p { color: var(--muted); margin: 0; }
|
|
151
|
+
.setup-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
|
|
152
|
+
.setup-card { padding: 14px; border: 1px solid var(--line); border-radius: 8px; background: rgba(13, 20, 32, 0.88); }
|
|
153
|
+
.setup-card span { color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; }
|
|
154
|
+
.setup-card strong { display: block; margin: 7px 0; font-size: 14px; }
|
|
155
|
+
.setup-card code { color: #d7e8ff; word-break: break-word; font-size: 12px; }
|
|
156
|
+
.key-list { display: grid; gap: 8px; }
|
|
157
|
+
.key-row { padding: 12px 14px; border: 1px solid var(--line); border-radius: 8px; background: #0a101b; }
|
|
158
|
+
.key-row div { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
|
|
159
|
+
.key-row p { margin: 0; color: var(--muted); font-size: 13px; }
|
|
160
|
+
.key-badge {
|
|
161
|
+
border-radius: 999px;
|
|
162
|
+
padding: 2px 7px;
|
|
163
|
+
font-size: 11px;
|
|
164
|
+
font-weight: 700;
|
|
165
|
+
}
|
|
166
|
+
.key-badge.required { background: rgba(56, 189, 248, 0.15); color: var(--accent); border: 1px solid rgba(56, 189, 248, 0.3); }
|
|
167
|
+
.key-badge.optional { background: rgba(147, 163, 184, 0.1); color: var(--muted); border: 1px solid var(--line); }
|
|
168
|
+
.settings-note { margin: 14px 0 0; color: var(--muted); font-size: 13px; }
|
|
169
|
+
|
|
170
|
+
.quick-actions { position: fixed; right: 20px; bottom: 20px; display: grid; gap: 8px; width: 200px; }
|
|
171
|
+
.quick-actions button {
|
|
172
|
+
border: 1px solid var(--line);
|
|
173
|
+
border-radius: 8px;
|
|
174
|
+
padding: 10px 12px;
|
|
175
|
+
background: #0d1420;
|
|
176
|
+
color: var(--ink);
|
|
177
|
+
text-align: left;
|
|
178
|
+
font: inherit;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
}
|
|
181
|
+
.quick-actions button:hover { background: #172133; }
|
|
182
|
+
|
|
183
|
+
@media (max-width: 1020px) {
|
|
184
|
+
.shell { grid-template-columns: 1fr; }
|
|
185
|
+
.sidebar { position: static; height: auto; }
|
|
186
|
+
.pipeline-strip, .hero-grid, .adapter-grid, .ops-strip, .setup-grid { grid-template-columns: 1fr; }
|
|
187
|
+
.quick-actions { position: static; width: auto; margin: 20px 30px; }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@media (max-width: 720px) {
|
|
191
|
+
.main { padding: 20px; }
|
|
192
|
+
.utility-bar { display: block; }
|
|
193
|
+
.utility-actions { margin-top: 10px; }
|
|
194
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Edit Plan — [CLIENT] / [PROJECT]
|
|
2
|
+
> Stage 3 planning artifact. Hand this to the video-use agent alongside `pipeline-brief.md`.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Source clips
|
|
7
|
+
|
|
8
|
+
| # | File | Duration | Scene | From manifest |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| 1 | generative/scene1-hook-a.mp4 | 5s | Hook A | manifest.json #id |
|
|
11
|
+
| 2 | generative/scene2.mp4 | 8s | Problem | manifest.json #id |
|
|
12
|
+
| N | generative/sceneN.mp4 | 5s | CTA | manifest.json #id |
|
|
13
|
+
|
|
14
|
+
VIDEO_USE_HOME staging path: `${VIDEO_USE_HOME}/<project>/`
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Cut strategy
|
|
19
|
+
|
|
20
|
+
- **Target duration:** [N]s
|
|
21
|
+
- **Opening hook:** Scene 1 (Hook [A–E] selected for this cut)
|
|
22
|
+
- **Core through-line:** Problem → Solution → CTA
|
|
23
|
+
- **Pacing bias:** tight (cut every ~3s) / breathing / mixed
|
|
24
|
+
- **Word-boundary cuts:** always — never cut inside a word
|
|
25
|
+
- **30 ms audio fades** at every segment boundary
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Overlay plan
|
|
30
|
+
|
|
31
|
+
| Time | Overlay | Tool | Notes |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| 0:00 | On-screen text: "[hook text]" | Manim / PIL | From brief Scene 1 |
|
|
34
|
+
| 0:05 | Caption track starts | FFmpeg subtitle filter | Subtitles applied last |
|
|
35
|
+
| 0:25 | CTA card: "[cta text]", [phone], [url] | Manim / PIL | From brand kit |
|
|
36
|
+
|
|
37
|
+
Subtitles are applied **last** — after all overlays. `setpts=PTS-STARTPTS+T/TB` for timing.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Music direction
|
|
42
|
+
|
|
43
|
+
- **Style:** [description]
|
|
44
|
+
- **Tempo:** [BPM guidance]
|
|
45
|
+
- **Fade in/out:** [direction]
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Render target
|
|
50
|
+
|
|
51
|
+
| Format | Codec | Resolution | Aspect |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| MP4 | h264 | 1080×1920 | 9:16 |
|
|
54
|
+
| MP4 | h264 | 1080×1080 | 1:1 (if required) |
|
|
55
|
+
|
|
56
|
+
Output: `output/<client>/<project>/final/final.mp4`
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## QA pass criteria
|
|
61
|
+
|
|
62
|
+
- [ ] Duration within ±10% of target
|
|
63
|
+
- [ ] Audio fades present at every segment boundary
|
|
64
|
+
- [ ] Subtitles applied last and aligned to phrase transcript
|
|
65
|
+
- [ ] No API keys or secrets in rendered output
|
|
66
|
+
- [ ] All 12 video-use production rules pass (see video-use qa-checklist.md)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Generative Plan — [CLIENT] / [PROJECT]
|
|
2
|
+
> Stage 2 planning artifact. Fill before running `helpers/run-pipeline.sh` or BYOK execution.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Adapter
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
CREATIVE_VIDEO_PIPELINE_GENERATIVE_ADAPTER=
|
|
10
|
+
VIDEO_MODEL_PROVIDER= (if byo-api-key)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Node bindings
|
|
16
|
+
|
|
17
|
+
| Scene | Type | Model | Prompt (from brief Appendix) | Duration | Aspect |
|
|
18
|
+
|---|---|---|---|---|---|
|
|
19
|
+
| Scene 1 (Hook A) | video | veo-3.1-generate-001 | | 5s | 9:16 |
|
|
20
|
+
| Scene 2 | video | veo-3.1-generate-001 | | 8s | 9:16 |
|
|
21
|
+
| Scene N | image | (image capability) | | — | 9:16 |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Reference images
|
|
26
|
+
|
|
27
|
+
> Bind as typed data URLs: `data:image/jpeg;base64,<base64>` per `@growthub/api-contract` ref spec.
|
|
28
|
+
> Never pass raw URLs as `refs[].dataUrl`.
|
|
29
|
+
|
|
30
|
+
| Name | Source | Purpose |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| brand_reference | brands/<client>/assets/logo.jpg | Brand anchor |
|
|
33
|
+
| scene_reference | brands/<client>/assets/reference.jpg | Visual style |
|
|
34
|
+
|
|
35
|
+
Shell command to convert a local image to a typed data URL:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python3 -c "
|
|
39
|
+
import base64, sys
|
|
40
|
+
with open(sys.argv[1], 'rb') as f:
|
|
41
|
+
b64 = base64.b64encode(f.read()).decode()
|
|
42
|
+
print(f'data:image/{sys.argv[2]};base64,{b64}')
|
|
43
|
+
" brands/<client>/assets/logo.jpg jpeg
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Pipeline payload (growthub-pipeline adapter)
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"pipelineId": "",
|
|
53
|
+
"executionMode": "hosted",
|
|
54
|
+
"nodes": [
|
|
55
|
+
{
|
|
56
|
+
"nodeId": "video-gen-1",
|
|
57
|
+
"slug": "video-generation",
|
|
58
|
+
"bindings": {
|
|
59
|
+
"videoModel": "veo-3.1-generate-001",
|
|
60
|
+
"prompt": "",
|
|
61
|
+
"seconds": 8,
|
|
62
|
+
"aspectRatio": "9:16",
|
|
63
|
+
"creativeCount": 1,
|
|
64
|
+
"refs": [
|
|
65
|
+
{ "name": "brand_reference", "dataUrl": "" }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Expected output
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
output/<client>/<project>/generative/
|
|
79
|
+
├── manifest.json
|
|
80
|
+
├── scene1-hook-a.mp4
|
|
81
|
+
├── scene2.mp4
|
|
82
|
+
└── scene-n-bg.jpg
|
|
83
|
+
```
|