From bb94b3eb8b3809f3b692d68006da28ec8316efd7 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sat, 30 May 2026 14:09:29 +0000 Subject: [PATCH] Autoblog banner styles: depict post content, 5 selectable looks Every autoblog hero used one fixed art-direction block, so all posts across all projects looked the same ("person at a screen") and weren't clearly about the post. Now: - Hero prompt leads with the POST's content (title, lede, tags, niche) and explicitly requires the image to depict the topic, not a generic office scene. - 5 selectable banner styles share the cohesive house look but vary the visual treatment: editorial photo, marketing hype, concept illustration, 3D/isometric, bold minimal. - Per-project setting (lx_site.banner_style, default 'editorial'), exposed in the autoblog setup form. - Pulled the photojournalism + "person at work" subject cues out of SHARED_ART_DIRECTION into an inline-concept-only block so they no longer force every hero into the same composition. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../projects/[id]/autoblog/setup/form.tsx | 31 ++++++ .../projects/[id]/autoblog/setup/page.tsx | 2 +- app/actions/linkExchange.ts | 9 ++ lib/lx/articleGen.ts | 104 +++++++++++++++--- .../20260530210000_lx_banner_style.sql | 17 +++ 5 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 supabase/migrations/20260530210000_lx_banner_style.sql diff --git a/app/(app)/projects/[id]/autoblog/setup/form.tsx b/app/(app)/projects/[id]/autoblog/setup/form.tsx index 031c531a..a1af9572 100644 --- a/app/(app)/projects/[id]/autoblog/setup/form.tsx +++ b/app/(app)/projects/[id]/autoblog/setup/form.tsx @@ -38,9 +38,18 @@ type Existing = { internal_links_per_article: number; backlinks_enabled: boolean; external_links_per_article: number; + banner_style: string | null; status: string; }; +const BANNER_STYLE_OPTIONS: Array<{ value: string; label: string; hint: string }> = [ + { value: "editorial", label: "Editorial photo", hint: "Cinematic photojournalistic cover" }, + { value: "hype", label: "Marketing hype", hint: "Bold, energetic launch-poster look" }, + { value: "concept", label: "Concept illustration", hint: "Clean illustrated metaphor of the idea" }, + { value: "tech", label: "3D / isometric", hint: "Sleek 3D render of the topic" }, + { value: "bold_type", label: "Bold minimal", hint: "Striking minimal composition" }, +]; + const DAY_LABELS: Array<{ n: number; label: string }> = [ { n: 1, label: "Mon" }, { n: 2, label: "Tue" }, @@ -115,6 +124,7 @@ export function SetupForm({ const [seoTitle, setSeoTitle] = useState(initial?.seo_title ?? ""); const [seoDescription, setSeoDescription] = useState(initial?.seo_description ?? ""); const [tone, setTone] = useState(initial?.tone ?? ""); + const [bannerStyle, setBannerStyle] = useState(initial?.banner_style ?? "editorial"); const [competitors, setCompetitors] = useState( (initial?.competitors ?? []).join(", "), ); @@ -566,6 +576,7 @@ export function SetupForm({ seoTitle, seoDescription, tone, + bannerStyle, competitors, webhookUrl, webhookSecret, @@ -933,6 +944,26 @@ export function SetupForm({ onChange={(e) => setTone(e.target.value)} /> +
+ + +

+ {BANNER_STYLE_OPTIONS.find((o) => o.value === bannerStyle)?.hint} + {" "}— every banner depicts the post's actual topic in this style. +

+