From 8658e550b2c1cbb45acf40c39a1cff00529f62ab Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Wed, 25 Mar 2026 13:28:08 -0700 Subject: [PATCH] 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) --- packages/cli/src/commands/init.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 0024c6be91..cd13ed04fd 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -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(