This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
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());
|
||||
Reference in New Issue
Block a user