diff --git a/apps/web/content/blog/website-as-a-service.mdx b/apps/web/content/blog/website-as-a-service.mdx index 34d952d..33b9ff7 100644 --- a/apps/web/content/blog/website-as-a-service.mdx +++ b/apps/web/content/blog/website-as-a-service.mdx @@ -1,6 +1,6 @@ --- title: "Website as a Service: Warum das Sorglos-Paket der einzig logische Weg für Unternehmer ist" -thumbnail: "/blog/website-as-a-service-thumb.png" +thumbnail: "/blog/website-as-a-service.png" description: "Vergessen Sie Plugin-Updates, Sicherheitslücken und Stundenabrechnungen. Ein Plädoyer für Websites ohne Overhead und warum Fixpreise den Markt revolutionieren." date: "2026-05-06" tags: ["business", "management", "strategy"] diff --git a/apps/web/content/blog/zero-overhead-agencies.mdx b/apps/web/content/blog/zero-overhead-agencies.mdx index c076020..38ba197 100644 --- a/apps/web/content/blog/zero-overhead-agencies.mdx +++ b/apps/web/content/blog/zero-overhead-agencies.mdx @@ -1,6 +1,6 @@ --- title: "Zero Overhead: Warum klassische Agenturen oft zu langsam (und zu teuer) sind" -thumbnail: "/blog/zero-overhead-agencies-thumb.png" +thumbnail: "/blog/zero-overhead-agencies.png" description: "Projektmanager, Account Manager, Junior Designer – bei klassischen Agenturen zahlen Sie oft den Wasserkopf mit. Wie ein Lean-Ansatz bessere und schnellere Ergebnisse liefert." date: "2026-05-06" tags: ["management", "strategy", "efficiency"] diff --git a/apps/web/public/blog/website-as-a-service-thumb.png b/apps/web/public/blog/website-as-a-service-thumb.png deleted file mode 100644 index 2502da8..0000000 Binary files a/apps/web/public/blog/website-as-a-service-thumb.png and /dev/null differ diff --git a/apps/web/public/blog/website-as-a-service.png b/apps/web/public/blog/website-as-a-service.png new file mode 100644 index 0000000..44b78e4 Binary files /dev/null and b/apps/web/public/blog/website-as-a-service.png differ diff --git a/apps/web/public/blog/zero-overhead-agencies-thumb.png b/apps/web/public/blog/zero-overhead-agencies-thumb.png deleted file mode 100644 index 3bc9f37..0000000 Binary files a/apps/web/public/blog/zero-overhead-agencies-thumb.png and /dev/null differ diff --git a/apps/web/public/blog/zero-overhead-agencies.png b/apps/web/public/blog/zero-overhead-agencies.png new file mode 100644 index 0000000..b8c7d41 Binary files /dev/null and b/apps/web/public/blog/zero-overhead-agencies.png differ diff --git a/apps/web/scripts/generate-thumbnail.ts b/apps/web/scripts/generate-thumbnail.ts index 47985b2..634a8bb 100644 --- a/apps/web/scripts/generate-thumbnail.ts +++ b/apps/web/scripts/generate-thumbnail.ts @@ -1,71 +1,83 @@ -import { ThumbnailGenerator } from '@mintel/thumbnail-generator'; -import * as path from 'node:path'; -import * as fs from 'node:fs/promises'; +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 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); - } + 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"; + 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 to parse the topic from the MDX frontmatter if a file is provided + if (targetFile.endsWith(".mdx")) { try { - await fs.access(outputPath); - console.log(`⏭️ Thumbnail already exists, skipping: ${filename}`); - return; - } catch { - // File does not exist, proceed with generation + 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")}.png`; + } catch (e) { + console.warn( + `⚠️ Could not read ${targetFile} as a file. Using literal argument as topic.`, + ); + topic = targetFile; } + } - const inspirationPath = path.join(baseDir, 'public', 'blog', 'inspiration.png'); - let hasInspiration = false; - try { - await fs.access(inspirationPath); - hasInspiration = true; - } catch { - hasInspiration = false; - } + console.log(`Generating abstract thumbnail for topic: "${topic}"`); - 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.`; + const generator = new ThumbnailGenerator({ replicateApiKey: apiKey }); + const isRoot = process.cwd().endsWith("mintel.me"); + const baseDir = isRoot + ? path.join(process.cwd(), "apps", "web") + : process.cwd(); - await generator.generateImage(topic, outputPath, { - systemPrompt: customPrompt, - imagePrompt: hasInspiration ? inspirationPath : undefined, - }); + 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); + console.error("❌ Thumbnail generation failed:", e); + process.exit(1); });