@norahe/remotion-workflow 0.1.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 (2) hide show
  1. package/package.json +16 -0
  2. package/src/cli.mjs +138 -0
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@norahe/remotion-workflow",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Workflow CLI for using Nora Remotion process in existing or new projects.",
6
+ "bin": {
7
+ "remotion-workflow": "src/cli.mjs"
8
+ },
9
+ "files": [
10
+ "src"
11
+ ],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "license": "MIT"
16
+ }
package/src/cli.mjs ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * [INPUT]: process args, filesystem state, and optional create-video scaffolding.
4
+ * [OUTPUT]: initialized workflow guide files in an existing or newly created project.
5
+ * [POS]: CLI entrypoint for @nora/remotion-workflow package.
6
+ * [PROTOCOL]: update this header when code changes, then check AGENTS.md
7
+ */
8
+
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import process from 'node:process';
12
+ import {spawnSync} from 'node:child_process';
13
+
14
+ const HELP = `
15
+ Usage:
16
+ remotion-workflow init [--project-name my-video]
17
+
18
+ Behavior:
19
+ - If current directory already looks like a Remotion project, initialize workflow files there.
20
+ - Otherwise, scaffold a new Remotion project with create-video and initialize workflow files.
21
+ `;
22
+
23
+ const args = process.argv.slice(2);
24
+ const command = args[0];
25
+
26
+ const getArgValue = (flag) => {
27
+ const index = args.indexOf(flag);
28
+ if (index === -1) return null;
29
+ return args[index + 1] ?? null;
30
+ };
31
+
32
+ const ensureDir = (target) => {
33
+ if (!fs.existsSync(target)) {
34
+ fs.mkdirSync(target, {recursive: true});
35
+ }
36
+ };
37
+
38
+ const writeIfMissing = (filePath, content) => {
39
+ if (fs.existsSync(filePath)) return false;
40
+ fs.writeFileSync(filePath, content, 'utf8');
41
+ return true;
42
+ };
43
+
44
+ const isRemotionProject = (cwd) => {
45
+ const packagePath = path.join(cwd, 'package.json');
46
+ const remotionConfigPathTs = path.join(cwd, 'remotion.config.ts');
47
+ const remotionConfigPathJs = path.join(cwd, 'remotion.config.js');
48
+ if (fs.existsSync(remotionConfigPathTs) || fs.existsSync(remotionConfigPathJs)) return true;
49
+ if (!fs.existsSync(packagePath)) return false;
50
+ try {
51
+ const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
52
+ const deps = {...(pkg.dependencies || {}), ...(pkg.devDependencies || {})};
53
+ return Boolean(deps.remotion || deps['@remotion/cli']);
54
+ } catch {
55
+ return false;
56
+ }
57
+ };
58
+
59
+ const createProjectIfNeeded = (cwd, projectName) => {
60
+ if (isRemotionProject(cwd)) return cwd;
61
+ const safeName = projectName || 'my-video';
62
+ console.log(`[workflow] No Remotion project found in ${cwd}`);
63
+ console.log(`[workflow] Creating a new Remotion project: ${safeName}`);
64
+ const result = spawnSync(
65
+ 'npx',
66
+ ['create-video@latest', safeName],
67
+ {stdio: 'inherit', cwd}
68
+ );
69
+ if (result.status !== 0) {
70
+ console.error('[workflow] Failed to create Remotion project via create-video.');
71
+ process.exit(result.status || 1);
72
+ }
73
+ return path.join(cwd, safeName);
74
+ };
75
+
76
+ const buildGuide = (projectName) => {
77
+ return [
78
+ '# Nora Remotion Workflow',
79
+ '',
80
+ `Project: ${projectName}`,
81
+ '',
82
+ '1) Prompt selection',
83
+ '- Open prompt browser: https://github.com/norahe0304-art/remotion-platform (see prompts app docs)',
84
+ '- Copy either `Copy AI Template` (prompt-based) or `Copy Input Guide` (blank from scratch).',
85
+ '',
86
+ '2) Input location',
87
+ '- Paste template into AI chat (Codex / ChatGPT / Claude).',
88
+ '- Fill placeholders there. Do not fill inside prompt web app.',
89
+ '',
90
+ '3) Implementation loop',
91
+ '- Ask AI to implement directly in this project.',
92
+ '- Review scene timing, VO/BGM mix, and transitions.',
93
+ '- Render final video from this project.',
94
+ '',
95
+ '4) Suggested commands',
96
+ '- npm run start',
97
+ '- npm run build',
98
+ ].join('\n');
99
+ };
100
+
101
+ const ensureWorkflowFiles = (projectDir) => {
102
+ const workflowDir = path.join(projectDir, '.nora-remotion-workflow');
103
+ ensureDir(workflowDir);
104
+
105
+ const guidePath = path.join(workflowDir, 'WORKFLOW.md');
106
+ const initializedPath = path.join(workflowDir, 'INIT.json');
107
+
108
+ const guideWritten = writeIfMissing(guidePath, `${buildGuide(path.basename(projectDir))}\n`);
109
+ const initPayload = {
110
+ initializedAt: new Date().toISOString(),
111
+ projectDir,
112
+ version: '0.1.0',
113
+ mode: 'default-remotion-project',
114
+ };
115
+ fs.writeFileSync(initializedPath, `${JSON.stringify(initPayload, null, 2)}\n`, 'utf8');
116
+
117
+ console.log(`[workflow] Initialized: ${workflowDir}`);
118
+ if (!guideWritten) {
119
+ console.log('[workflow] Existing WORKFLOW.md kept (not overwritten).');
120
+ }
121
+ };
122
+
123
+ if (!command || command === '--help' || command === '-h') {
124
+ console.log(HELP.trim());
125
+ process.exit(0);
126
+ }
127
+
128
+ if (command !== 'init') {
129
+ console.error(`[workflow] Unknown command: ${command}`);
130
+ console.log(HELP.trim());
131
+ process.exit(1);
132
+ }
133
+
134
+ const projectName = getArgValue('--project-name');
135
+ const cwd = process.cwd();
136
+ const projectDir = createProjectIfNeeded(cwd, projectName);
137
+ ensureWorkflowFiles(projectDir);
138
+ console.log(`[workflow] Done. Use project: ${projectDir}`);