import { ThumbnailGenerator } from '@mintel/thumbnail-generator'; import * as path from 'node:path'; import * as fs from 'node:fs/promises'; async function run() { const apiKey = process.env.REPLICATE_API_TOKEN || process.env.REPLICATE_API_KEY; if (!apiKey) { console.error("❌ Missing REPLICATE_API_TOKEN in environment."); process.exit(1); } const targetFile = process.argv[2]; if (!targetFile) { console.error("❌ Usage: npx tsx scripts/generate-thumbnail.ts "); process.exit(1); } let topic = targetFile; let filename = "thumbnail.png"; // Try to parse the topic from the MDX frontmatter if a file is provided if (targetFile.endsWith('.mdx')) { try { const content = await fs.readFile(targetFile, 'utf8'); const titleMatch = content.match(/title:\s*"?([^"\n]+)"?/); topic = titleMatch ? titleMatch[1] : path.basename(targetFile, '.mdx'); filename = `${path.basename(targetFile, '.mdx')}-thumb.png`; } catch (e) { console.warn(`⚠️ Could not read ${targetFile} as a file. Using literal argument as topic.`); topic = targetFile; } } console.log(`Generating abstract thumbnail for topic: "${topic}"`); const generator = new ThumbnailGenerator({ replicateApiKey: apiKey }); const isRoot = process.cwd().endsWith('mintel.me'); const baseDir = isRoot ? path.join(process.cwd(), 'apps', 'web') : process.cwd(); const outputPath = path.join(baseDir, 'public', 'blog', filename); // Check if thumbnail already exists to avoid redundant generation try { await fs.access(outputPath); console.log(`⏭️ Thumbnail already exists, skipping: ${filename}`); return; } catch { // File does not exist, proceed with generation } const inspirationPath = path.join(baseDir, 'public', 'blog', 'inspiration.png'); let hasInspiration = false; try { await fs.access(inspirationPath); hasInspiration = true; } catch { hasInspiration = false; } const customPrompt = `Extremely clean, flat, abstract geometric illustration. Use the provided image prompt ONLY as a STRICT style, color, and texture reference. Do not copy the image content, just the aesthetic. Characteristics: Flat vector design, 2D only (no 3D), tech/startup/agency aesthetics, highly professional, abstract data representations, extensive use of whitespace. No text, no chaotic lines, no humans.`; await generator.generateImage(topic, outputPath, { systemPrompt: customPrompt, imagePrompt: hasInspiration ? inspirationPath : undefined, }); } run().catch((e) => { console.error("❌ Thumbnail generation failed:", e); process.exit(1); });