diff --git a/packages/cli/src/capture/agentPromptGenerator.ts b/packages/cli/src/capture/agentPromptGenerator.ts index 9df7f38dd..fb977d5c1 100644 --- a/packages/cli/src/capture/agentPromptGenerator.ts +++ b/packages/cli/src/capture/agentPromptGenerator.ts @@ -20,7 +20,8 @@ export function generateAgentPrompt( hasScreenshot: boolean, hasLottie?: boolean, hasShaders?: boolean, - catalogedAssets?: CatalogedAsset[], + _catalogedAssets?: CatalogedAsset[], + detectedLibraries?: string[], ): void { const prompt = buildPrompt( url, @@ -29,7 +30,7 @@ export function generateAgentPrompt( hasScreenshot, hasLottie, hasShaders, - catalogedAssets, + detectedLibraries, ); writeFileSync(join(outputDir, "CLAUDE.md"), prompt, "utf-8"); writeFileSync(join(outputDir, ".cursorrules"), prompt, "utf-8"); @@ -38,122 +39,81 @@ export function generateAgentPrompt( function buildPrompt( url: string, tokens: DesignTokens, - animations: AnimationCatalog | undefined, + _animations: AnimationCatalog | undefined, hasScreenshot: boolean, hasLottie?: boolean, hasShaders?: boolean, - catalogedAssets?: CatalogedAsset[], + detectedLibraries?: string[], ): string { - const hostname = new URL(url).hostname.replace(/^www\./, ""); - const title = tokens.title || hostname; - const cues = detectImplementationCues(tokens, animations); + const title = tokens.title || new URL(url).hostname.replace(/^www\./, ""); const colorSummary = tokens.colors.slice(0, 10).join(", "); - const fontSummary = tokens.fonts.join(", ") || "none detected"; - const sectionCount = tokens.sections?.length ?? 0; - const headingCount = tokens.headings?.length ?? 0; - const ctaCount = tokens.ctas?.length ?? 0; + const fontSummary = + tokens.fonts + .map( + (f) => + f.family + + (f.variable && f.weightRange + ? ` (${f.weightRange[0]}-${f.weightRange[1]} variable)` + : f.weights.length > 0 + ? ` (${f.weights.join(",")})` + : ""), + ) + .join(", ") || "none detected"; - const videoUrls = catalogedAssets - ? catalogedAssets - .filter((a) => a.type === "Video" && a.url.startsWith("http")) - .map((a) => a.url) - .filter((u, i, arr) => arr.indexOf(u) === i) // deduplicate - : []; + // Build the data inventory table rows + const tableRows: string[] = []; + if (hasScreenshot) { + tableRows.push( + "| `screenshots/scroll-*.png` | Viewport screenshots of the full page. Start with `scroll-000.png` (hero). |", + ); + } + tableRows.push( + "| `extracted/asset-descriptions.md` | One-line description of every downloaded asset. **Read this first.** |", + ); + tableRows.push( + `| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${tokens.headings?.length ?? 0} headings, ${tokens.ctas?.length ?? 0} CTAs |`, + ); + tableRows.push( + "| `extracted/visible-text.txt` | Page text in DOM order, prefixed with HTML tag (`[h1]`, `[p]`, `[a]`). Use as context — rephrase freely. |", + ); + if (hasLottie) { + tableRows.push( + "| `extracted/lottie-manifest.json` | Lottie animations with previews at `assets/lottie/previews/`. |", + ); + } + if (hasShaders) { + tableRows.push("| `extracted/shaders.json` | WebGL shader source (GLSL). |"); + } + if (detectedLibraries && detectedLibraries.length > 0) { + tableRows.push( + `| \`extracted/detected-libraries.json\` | Libraries: ${detectedLibraries.join(", ")} |`, + ); + } + tableRows.push("| `assets/` | Downloaded images, SVGs, and font files. |"); - return `# ${title} — Captured Website + // Brand summary — just the essentials + const brandLines: string[] = []; + brandLines.push(`- **Colors**: ${colorSummary || "see tokens.json"}`); + brandLines.push(`- **Fonts**: ${fontSummary}`); + if (detectedLibraries && detectedLibraries.length > 0) { + brandLines.push(`- **Built with**: ${detectedLibraries.join(", ")}`); + } + + return `# ${title} Source: ${url} -## How to Create a Video - -Invoke the \`/website-to-hyperframes\` skill. It walks you through the full workflow: read data → create DESIGN.md → plan video → build compositions → lint/validate/preview. - -If you don't have the skill installed, run: \`npx skills add heygen-com/hyperframes\` +To create a video from this capture, use the \`/website-to-hyperframes\` skill. ## What's in This Capture | File | Contents | |------|----------| -${hasScreenshot ? "| `screenshots/scroll-*.png` | Viewport screenshots covering the full page (1920x1080 each, 30% overlap). **View scroll-000.png FIRST** (hero section), then scan through the rest to understand the full page. |" : ""} -| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${headingCount} headings, ${ctaCount} CTAs, ${sectionCount} sections | -| \`extracted/visible-text.txt\` | All visible text content in DOM order — use exact strings, never paraphrase | -| \`extracted/assets-catalog.json\` | Every asset URL (images, fonts, videos, icons) with HTML context | -| \`extracted/animations.json\` | Animation catalog: ${animations?.summary?.webAnimations ?? 0} web animations, ${animations?.summary?.scrollTargets ?? 0} scroll triggers, ${animations?.summary?.canvases ?? 0} canvases | -| \`assets/svgs/\` | Extracted inline SVGs (logos, icons, illustrations) | -| \`assets/\` | Downloaded images and font files — **Read every image file to see what it contains** | -${hasLottie ? "| `extracted/lottie-manifest.json` | Lottie animations found on this site — read this to see what animations are available (name, dimensions, duration). Embed via `lottie.loadAnimation({ path: 'assets/lottie/animation-0.json' })`. Do NOT read the raw JSON files — they are machine data. |" : ""} -${videoUrls.length > 0 ? "| `extracted/video-manifest.json` | Video manifest: every `