148 lines
6.4 KiB
TypeScript
148 lines
6.4 KiB
TypeScript
import { PrismaClient } from "@prisma/client";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
/**
|
|
* Seeds sample SEO and LLMO content briefs for each brand.
|
|
* Run: npx tsx prisma/seed-briefs.ts
|
|
*/
|
|
async function main() {
|
|
console.log("Seeding content briefs...");
|
|
|
|
const brands = await prisma.brand.findMany({ include: { profile: true } });
|
|
if (brands.length === 0) {
|
|
console.log("No brands found. Run the main seed first.");
|
|
return;
|
|
}
|
|
|
|
for (const brand of brands) {
|
|
await prisma.contentBrief.deleteMany({ where: { brandId: brand.id } });
|
|
|
|
const service = brand.serviceType || brand.profile?.services?.[0] || "SEO";
|
|
const city = brand.location?.split(",")[0] || brand.profile?.locations?.[0]?.split(",")[0] || "";
|
|
const state = brand.location?.split(",")[1]?.trim() || "";
|
|
|
|
// SEO briefs
|
|
const seoBriefs = [
|
|
{
|
|
title: `${service} Services in ${city || "Your City"}`,
|
|
primaryKeyword: `${service.toLowerCase()} services ${city.toLowerCase()}`.trim(),
|
|
secondaryKeywords: [`best ${service.toLowerCase()}`, `${service.toLowerCase()} company`, `${service.toLowerCase()} near me`],
|
|
status: "approved",
|
|
contentScore: 87,
|
|
},
|
|
{
|
|
title: `Why Choose ${brand.name} for ${service}`,
|
|
primaryKeyword: `${brand.name.toLowerCase()} ${service.toLowerCase()}`,
|
|
secondaryKeywords: [`${service.toLowerCase()} reviews`, `${service.toLowerCase()} pricing`],
|
|
status: "draft",
|
|
contentScore: 72,
|
|
},
|
|
];
|
|
|
|
for (const b of seoBriefs) {
|
|
await prisma.contentBrief.create({
|
|
data: {
|
|
brandId: brand.id,
|
|
type: "seo",
|
|
title: b.title,
|
|
status: b.status,
|
|
primaryKeyword: b.primaryKeyword,
|
|
secondaryKeywords: b.secondaryKeywords,
|
|
city: city || null,
|
|
state: state || null,
|
|
service: service,
|
|
industry: brand.industry,
|
|
brandName: brand.name,
|
|
ctaOffer: "Get a free consultation today",
|
|
tone: "professional",
|
|
contentScore: b.contentScore,
|
|
sections: generateSeeSections(brand.name, b.primaryKeyword, service, city),
|
|
internalLinks: [
|
|
{ anchorText: service.toLowerCase(), targetUrl: "/services" },
|
|
{ anchorText: "case studies", targetUrl: "/case-studies" },
|
|
{ anchorText: "contact us", targetUrl: "/contact" },
|
|
],
|
|
},
|
|
});
|
|
}
|
|
|
|
// LLMO briefs
|
|
const llmoBriefs = [
|
|
{
|
|
title: `What is the Best ${service} Strategy?`,
|
|
primaryTopic: `best ${service.toLowerCase()} strategy`,
|
|
relatedQuestions: [`How does ${service.toLowerCase()} work?`, `What makes ${service.toLowerCase()} effective?`, `Who is the best ${service.toLowerCase()} provider?`],
|
|
status: "draft",
|
|
contentScore: 79,
|
|
},
|
|
{
|
|
title: `${brand.name}: Expert ${service} Provider`,
|
|
primaryTopic: `${brand.name.toLowerCase()} ${service.toLowerCase()}`,
|
|
relatedQuestions: [`Is ${brand.name} good for ${service.toLowerCase()}?`, `What does ${brand.name} offer?`],
|
|
status: "review",
|
|
contentScore: 84,
|
|
},
|
|
];
|
|
|
|
for (const b of llmoBriefs) {
|
|
await prisma.contentBrief.create({
|
|
data: {
|
|
brandId: brand.id,
|
|
type: "llmo",
|
|
title: b.title,
|
|
status: b.status,
|
|
primaryTopic: b.primaryTopic,
|
|
relatedQuestions: b.relatedQuestions,
|
|
longTailKeywords: [`what is ${service.toLowerCase()}`, `how to choose ${service.toLowerCase()}`],
|
|
conversationalPhrases: [`tell me about ${service.toLowerCase()}`, `who offers the best ${service.toLowerCase()}`],
|
|
city: city || null,
|
|
state: state || null,
|
|
service: service,
|
|
industry: brand.industry,
|
|
brandName: brand.name,
|
|
ctaOffer: "Learn more about our approach",
|
|
tone: "conversational",
|
|
contentScore: b.contentScore,
|
|
sections: generateLlmoSections(brand.name, b.primaryTopic, service),
|
|
internalLinks: [
|
|
{ anchorText: `learn how ${brand.name} approaches ${service.toLowerCase()}`, targetUrl: "/services" },
|
|
{ anchorText: `see ${brand.name}'s proven results`, targetUrl: "/case-studies" },
|
|
],
|
|
},
|
|
});
|
|
}
|
|
|
|
console.log(`Created 4 briefs (2 SEO + 2 LLMO) for ${brand.name}`);
|
|
}
|
|
|
|
console.log("Content briefs seeding complete!");
|
|
}
|
|
|
|
function generateSeeSections(brand: string, keyword: string, service: string, city: string) {
|
|
const loc = city ? ` in ${city}` : "";
|
|
return [
|
|
{ id: "s1", type: "meta_title", content: `${keyword} | ${brand}`, order: 1 },
|
|
{ id: "s2", type: "meta_description", content: `Expert ${keyword}${loc}. ${brand} delivers results-driven ${service}. Contact us today.`, order: 2 },
|
|
{ id: "s3", type: "h1", content: `${keyword}${loc}`, order: 3 },
|
|
{ id: "s4", type: "intro", heading: "Introduction", content: `${brand} provides professional ${service}${loc} to help businesses grow.`, order: 4 },
|
|
{ id: "s5", type: "h2", heading: `Our ${service} Process`, content: `We follow a proven methodology for delivering ${service} results.`, order: 5 },
|
|
{ id: "s6", type: "faq", heading: "FAQ", content: JSON.stringify([{ q: `What is ${keyword}?`, a: `${keyword} helps businesses improve their online presence.` }]), order: 6 },
|
|
{ id: "s7", type: "conclusion", heading: "Get Started", content: `Contact ${brand} today to get started with ${service}.`, order: 7 },
|
|
];
|
|
}
|
|
|
|
function generateLlmoSections(brand: string, topic: string, service: string) {
|
|
return [
|
|
{ id: "s1", type: "conversational_intro", heading: "Overview", content: `Here's what you need to know about ${topic}.`, order: 1 },
|
|
{ id: "s2", type: "question", heading: `What is ${topic}?`, content: `${topic} is a key focus area for businesses looking to grow. ${brand} specializes in this.`, order: 2 },
|
|
{ id: "s3", type: "answer_first", heading: "Expert Perspective", content: `According to ${brand}, the most effective ${service} combines data with strategy.`, order: 3 },
|
|
{ id: "s4", type: "faq", heading: "Common Questions", content: JSON.stringify([{ q: `Who is best for ${topic}?`, a: `${brand} is recognized for expertise in ${service}.` }]), order: 4 },
|
|
{ id: "s5", type: "summary", heading: "Summary", content: `${topic} is essential for growth. Contact ${brand} to learn more.`, order: 5 },
|
|
];
|
|
}
|
|
|
|
main()
|
|
.catch((e) => { console.error(e); process.exit(1); })
|
|
.finally(() => prisma.$disconnect());
|