Files
Trey t 66c2bbec8b feat: complete marketing command center with pipeline, UI, and asset generation
- Dashboard with campaign management, asset gallery, and publishing queue
- 7-agent pipeline: trend scout, research, scripts, ad creative, video, copy, distribution
- Campaign form with screenshot upload, goal picker, platform selection
- Campaign detail view with Details/Pipeline/Assets/Chat tabs
- Two-set image generation: Gemini AI (NanoBanana MCP) + Canvas Design posters
- Remotion video rendering with phone.png frame and real screenshot alignment
- honeyDue branding: blue #0079FF, orange #FF9400, Inter font, warm off-white
- Asset cards with source badges (Gemini/Canvas/Remotion/Playwright)
- Markdown/JSON render endpoint for viewing pipeline outputs as HTML
- Settings page with Tavily, Gemini, Postiz, Nextdoor integration management
- Claude Chat for campaign feedback loop with streaming SSE
- Postiz publishing modal with scheduling
- Auth with NextAuth credentials + JWT sessions
- SQLite via Prisma with better-sqlite3 adapter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 21:05:26 -05:00

200 lines
10 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PrismaClient } from "../lib/generated/prisma/client";
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
const adapter = new PrismaBetterSqlite3({
url: process.env.DATABASE_URL || "file:./data/marketing.db",
});
const prisma = new PrismaClient({ adapter });
async function main() {
// Campaign 1: Completed with assets
const campaign1 = await prisma.campaign.create({
data: {
name: "Spring Launch Campaign",
status: "review",
platforms: JSON.stringify(["instagram", "tiktok", "nextdoor"]),
config: JSON.stringify({
goal: "app_downloads",
keyMessage: "Your morning routine just got an upgrade. The smartest productivity app of 2026.",
socialProof: "50K+ downloads, 4.8 star rating, Featured in App Store",
variations: 5,
useTrendReport: true,
}),
outputPath: "outputs/spring_launch_campaign_20260323",
prompt: "Create a campaign batch for Spring Launch...",
},
});
// Agent runs for campaign 1
const agents = [
{ name: "trend-scout", duration: 12000, summary: "5 trending hooks found: 'POV: you just found...', 'Why is nobody talking about...'" },
{ name: "marketing-research-agent", duration: 128000, summary: "Market report generated. 3 competitor angles identified, 8 pain points mapped." },
{ name: "script-writer", duration: 95000, summary: "15 scripts written — 5 hooks × 3 platform styles (polished, authentic, local)." },
{ name: "ad-creative-designer", duration: 187000, summary: "8 static ads generated: 4 Instagram (1080x1080), 2 Nextdoor spotlight, 2 Nextdoor display." },
{ name: "video-ad-producer", duration: 312000, summary: "6 video ads rendered: 2 Instagram Reels (polished), 2 TikTok (authentic), 2 Nextdoor (local)." },
{ name: "copywriter-agent", duration: 67000, summary: "Platform-tuned captions written for all 14 creatives. Hashtag sets included." },
{ name: "distribution-agent", duration: 23000, summary: "Publish manifest created. 14 assets ready for review." },
];
for (const agent of agents) {
await prisma.agentRun.create({
data: {
campaignId: campaign1.id,
agentName: agent.name,
status: "completed",
startedAt: new Date(Date.now() - 3600000),
completedAt: new Date(Date.now() - 3600000 + agent.duration),
durationMs: agent.duration,
outputSummary: agent.summary,
},
});
}
// Assets for campaign 1
const assets = [
{ type: "image", platform: "instagram", format: "png", fileName: "instagram_feed_hook_a_1080x1080.png", dimensions: "1080x1080", status: "approved", metadata: { caption: "Your morning just got an upgrade. ✨\n\nThe smartest productivity app of 2026 is here — and it's free.\n\nDownload now — link in bio.\n\n#ProductivityApp #MorningRoutine #AppOfTheDay", hook: "Still doing it the hard way?" } },
{ type: "image", platform: "instagram", format: "png", fileName: "instagram_feed_hook_b_1080x1080.png", dimensions: "1080x1080", status: "approved", metadata: { caption: "POV: you just found the app everyone's been hiding from you. 🚀\n\n50K+ downloads can't be wrong.\n\n#ProductivityTips #TechLife", hook: "POV: you just found this app" } },
{ type: "image", platform: "instagram", format: "png", fileName: "instagram_stories_hook_a_1080x1920.png", dimensions: "1080x1920", status: "draft", metadata: { caption: "Swipe up to download free 🔥", hook: "Your workflow is about to change" } },
{ type: "image", platform: "nextdoor", format: "png", fileName: "nextdoor_spotlight_1200x1200.png", dimensions: "1200x1200", status: "approved", metadata: { caption: "Your neighbors are already using this app to simplify their mornings. Join them — it's free.", hook: "Your neighbors love this app" } },
{ type: "image", platform: "nextdoor", format: "png", fileName: "nextdoor_display_1200x628.png", dimensions: "1200x628", status: "draft", metadata: { caption: "The productivity app trusted by your community. Learn more.", hook: "Trusted locally" } },
{ type: "video", platform: "instagram", format: "mp4", fileName: "instagram_reel_polished_1080x1920.mp4", dimensions: "1080x1920", status: "approved", metadata: { caption: "3 seconds to change your morning ⚡\n\nDownload free — link in bio.\n\n#Reels #ProductivityHack", hook: "Still doing it the hard way?", duration: "15s" } },
{ type: "video", platform: "tiktok", format: "mp4", fileName: "tiktok_ad_authentic_1080x1920.mp4", dimensions: "1080x1920", status: "approved", metadata: { caption: "okay i HAVE to share this app with you guys 😭 #fyp #productivity #appoftiktok", hook: "I need to talk about this app", duration: "9s" } },
{ type: "video", platform: "tiktok", format: "mp4", fileName: "tiktok_ad_hook_b_1080x1920.mp4", dimensions: "1080x1920", status: "draft", metadata: { caption: "why is nobody talking about this?? #fyp #lifehack", hook: "Why is nobody talking about this?", duration: "12s" } },
{ type: "video", platform: "nextdoor", format: "mp4", fileName: "nextdoor_video_local_1080x1080.mp4", dimensions: "1080x1080", status: "draft", metadata: { caption: "See why your neighbors love this app. Simple, free, and made for busy mornings.", hook: "Your neighbors love this app", duration: "15s" } },
{ type: "copy", platform: "instagram", format: "json", fileName: "instagram_captions.json", status: "approved", metadata: { caption: "5 caption variations for Instagram" } },
{ type: "copy", platform: "tiktok", format: "json", fileName: "tiktok_captions.json", status: "approved", metadata: { caption: "5 caption variations for TikTok" } },
{ type: "copy", platform: "nextdoor", format: "json", fileName: "nextdoor_posts.json", status: "approved", metadata: { caption: "3 post variations for Nextdoor" } },
{ type: "research", platform: null, format: "html", fileName: "interactive_report.html", status: "approved", metadata: { caption: "Market research dashboard with competitor analysis" } },
{ type: "script", platform: null, format: "md", fileName: "ad_scripts_all_platforms.md", status: "approved", metadata: { caption: "15 ad scripts — 5 hooks × 3 platform styles" } },
];
for (const asset of assets) {
await prisma.asset.create({
data: {
campaignId: campaign1.id,
type: asset.type,
platform: asset.platform,
format: asset.format,
filePath: `outputs/spring_launch_campaign_20260323/${asset.type === "image" ? "ads" : asset.type === "video" ? "video" : asset.type === "copy" ? "copy" : ""}/${asset.fileName}`,
fileName: asset.fileName,
dimensions: asset.dimensions || null,
status: asset.status,
metadata: JSON.stringify(asset.metadata),
},
});
}
// Campaign 2: Running
const campaign2 = await prisma.campaign.create({
data: {
name: "Summer Feature Drop",
status: "running",
platforms: JSON.stringify(["instagram", "tiktok"]),
config: JSON.stringify({
goal: "engagement",
keyMessage: "The feature you've been asking for is finally here.",
variations: 3,
}),
},
});
// Partial agent runs for campaign 2
const partialAgents = [
{ name: "trend-scout", status: "completed", duration: 9000, summary: "4 trending hooks found" },
{ name: "marketing-research-agent", status: "completed", duration: 110000, summary: "Research complete. 5 angles identified." },
{ name: "script-writer", status: "running", duration: null, summary: null },
];
for (const agent of partialAgents) {
await prisma.agentRun.create({
data: {
campaignId: campaign2.id,
agentName: agent.name,
status: agent.status,
startedAt: new Date(),
completedAt: agent.status === "completed" ? new Date() : null,
durationMs: agent.duration,
outputSummary: agent.summary,
},
});
}
// Campaign 3: Draft
await prisma.campaign.create({
data: {
name: "Back to School Promo",
status: "draft",
platforms: JSON.stringify(["instagram", "nextdoor"]),
config: JSON.stringify({
goal: "app_downloads",
keyMessage: "Get organized before school starts. The app students and parents love.",
}),
},
});
// Campaign 4: Published
const campaign4 = await prisma.campaign.create({
data: {
name: "Valentine's Day Push",
status: "published",
platforms: JSON.stringify(["instagram", "tiktok"]),
config: JSON.stringify({
goal: "brand_awareness",
keyMessage: "Share the love — share the app.",
}),
},
});
// A few published assets for campaign 4
for (const asset of [
{ fileName: "ig_valentines_1080x1080.png", platform: "instagram", type: "image", dimensions: "1080x1080" },
{ fileName: "tiktok_valentines_1080x1920.mp4", platform: "tiktok", type: "video", dimensions: "1080x1920" },
]) {
await prisma.asset.create({
data: {
campaignId: campaign4.id,
type: asset.type,
platform: asset.platform,
format: asset.fileName.split(".").pop()!,
filePath: `outputs/valentines_push_20260214/ads/${asset.fileName}`,
fileName: asset.fileName,
dimensions: asset.dimensions,
status: "published",
postizPostId: `postiz_${Math.random().toString(36).slice(2, 10)}`,
metadata: JSON.stringify({ caption: "Share the love 💕 Download free — link in bio." }),
},
});
}
// Trend report
await prisma.trendReport.create({
data: {
name: "Weekly Trends — March 17-23, 2026",
filePath: "outputs/trend_reports/weekly_20260323.html",
summary: "Top hooks: 'POV: you just found...', 'Why is nobody talking about...'. Competitor analysis: 3 apps gaining traction with UGC-style Reels. Recommended themes: morning routine, before/after transformations.",
},
});
await prisma.trendReport.create({
data: {
name: "Weekly Trends — March 10-16, 2026",
filePath: "outputs/trend_reports/weekly_20260316.html",
summary: "Trending format: split-screen comparisons. Rising hashtag: #AppTok. Competitor spotlight: rival app launched TikTok campaign with 2M views.",
},
});
console.log("Demo data seeded:");
console.log(" 4 campaigns (review, running, draft, published)");
console.log(" 14 assets on Spring Launch");
console.log(" 2 published assets on Valentine's");
console.log(" 7 completed agent runs + 3 partial");
console.log(" 2 trend reports");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());