feat(cli): create assets/ and fonts/ directories on init

- scaffoldProject now creates assets/ and fonts/ directories
- Video files are placed in assets/ instead of project root
- Template __VIDEO_SRC__ placeholders resolve to assets/filename

Aligns with the compose-video skill's project structure convention
where user-provided media goes in assets/ and fonts in fonts/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-03-26 17:50:46 +00:00
committed by Vance Ingalls
co-authored by Claude Opus 4.6
parent 96253ca832
commit 8658e550b2
+12 -6
View File
@@ -176,6 +176,8 @@ async function handleVideoFile(
destDir: string,
interactive: boolean,
): Promise<{ meta: VideoMeta; localVideoName: string }> {
const assetsDir = resolve(destDir, "assets");
mkdirSync(assetsDir, { recursive: true });
const probed = probeVideo(videoPath);
let meta: VideoMeta = { ...DEFAULT_META };
let localVideoName = basename(videoPath);
@@ -227,7 +229,7 @@ async function handleVideoFile(
if (shouldTranscode) {
const mp4Name = localVideoName.replace(/\.[^.]+$/, ".mp4");
const mp4Path = resolve(destDir, mp4Name);
const mp4Path = resolve(assetsDir, mp4Name);
const spin = clack.spinner();
spin.start("Transcoding to H.264 MP4...");
const ok = await transcodeToMp4(videoPath, mp4Path);
@@ -236,10 +238,10 @@ async function handleVideoFile(
localVideoName = mp4Name;
} else {
spin.stop(c.warn("Transcode failed — copying original file"));
copyFileSync(videoPath, resolve(destDir, localVideoName));
copyFileSync(videoPath, resolve(assetsDir, localVideoName));
}
} else {
copyFileSync(videoPath, resolve(destDir, localVideoName));
copyFileSync(videoPath, resolve(assetsDir, localVideoName));
}
} else {
if (interactive) {
@@ -249,13 +251,13 @@ async function handleVideoFile(
console.log(c.warn("ffmpeg not installed — cannot transcode. Copying original."));
console.log(c.dim("Install: ") + c.accent("brew install ffmpeg"));
}
copyFileSync(videoPath, resolve(destDir, localVideoName));
copyFileSync(videoPath, resolve(assetsDir, localVideoName));
}
} else {
copyFileSync(videoPath, resolve(destDir, localVideoName));
copyFileSync(videoPath, resolve(assetsDir, localVideoName));
}
return { meta, localVideoName };
return { meta, localVideoName: `assets/${localVideoName}` };
}
// ---------------------------------------------------------------------------
@@ -274,6 +276,10 @@ function scaffoldProject(
cpSync(templateDir, destDir, { recursive: true });
patchVideoSrc(destDir, localVideoName);
// Create asset directories for user-provided content
mkdirSync(resolve(destDir, "assets"), { recursive: true });
mkdirSync(resolve(destDir, "fonts"), { recursive: true });
writeFileSync(
resolve(destDir, "meta.json"),
JSON.stringify(