Initial project commit for Coolify staging
CI / Quality gate (push) Has been cancelled

This commit is contained in:
Andres Resiri
2026-08-03 10:45:41 -04:00
commit 70daeb214a
1199 changed files with 243503 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
console.log("Seeding AI visibility + competitors...");
const brands = await prisma.brand.findMany();
if (brands.length === 0) { console.log("No brands. Run main seed first."); return; }
for (const brand of brands) {
// Clear existing
await prisma.aiVisibilitySnapshot.deleteMany({ where: { brandId: brand.id } });
await prisma.competitorSnapshot.deleteMany({ where: { brandId: brand.id } });
await prisma.competitor.deleteMany({ where: { brandId: brand.id } });
// ── AI Visibility: 30 days of snapshots ──
const platforms = ["chatgpt", "claude", "perplexity", "gemini", "google_aio"];
const topics = [
"best project management tools",
"SEO audit checklist",
"technical SEO guide",
"AI visibility optimization",
"website speed optimization",
];
const pages = ["/features", "/blog/seo-guide", "/technical-audit", "/pricing", "/about"];
for (let d = 30; d >= 0; d--) {
const date = new Date();
date.setDate(date.getDate() - d);
date.setHours(12, 0, 0, 0);
for (let p = 0; p < platforms.length; p++) {
const baseMentions = [5, 4, 3, 2, 1][p];
const growth = 1 + ((30 - d) / 30) * 0.2;
const noise = () => 0.7 + Math.random() * 0.6;
for (let t = 0; t < 2; t++) {
const topicIdx = (p + t) % topics.length;
const mentions = Math.round(baseMentions * growth * noise());
const citations = Math.round(mentions * (0.3 + Math.random() * 0.4));
await prisma.aiVisibilitySnapshot.create({
data: {
brandId: brand.id,
date,
platform: platforms[p],
topic: topics[topicIdx],
mentions,
citations,
visibilityScore: Math.min(100, Math.round(mentions * 8 + citations * 12)),
sourceUrl: pages[topicIdx],
change: d < 28 ? Math.round((Math.random() - 0.3) * 3) : 0,
},
});
}
}
}
console.log(` AI visibility: 30 days × 5 platforms × 2 topics for ${brand.name}`);
// ── Competitors ──
const comps = [
{ name: "RankBoost.io", domain: "rankboost.io", type: "national", strongestPage: "/features/seo-audit", whyWinning: "Published 4 new long-form guides targeting core keywords. Strong internal linking structure.", watchlist: true },
{ name: "ContentKing", domain: "contentking.com", type: "national", strongestPage: "/technical-seo-guide", whyWinning: "12,000-word technical SEO guide displacing competitors in AI citations.", watchlist: true },
{ name: "LocalSEO Pro", domain: "localseepro.com", type: "local", strongestPage: "/local-seo-services", whyWinning: "Dominates local pack for city-specific queries. Strong GBP optimization.", watchlist: false },
{ name: "AgencyFirst", domain: "agencyfirst.io", type: "emerging", strongestPage: "/blog/ai-seo", whyWinning: "New player publishing AI-focused SEO content rapidly.", watchlist: false },
];
for (const c of comps) {
const competitor = await prisma.competitor.create({
data: {
brandId: brand.id,
name: c.name,
domain: c.domain,
type: c.type,
strongestPage: c.strongestPage,
whyWinning: c.whyWinning,
watchlist: c.watchlist,
},
});
// Add weekly snapshots for 12 weeks
for (let w = 12; w >= 0; w--) {
const date = new Date();
date.setDate(date.getDate() - w * 7);
date.setHours(12, 0, 0, 0);
const threat = c.watchlist ? (w < 4 ? "high" : "medium") : "low";
const baseAi = c.name === "RankBoost.io" ? 8 : c.name === "ContentKing" ? 6 : 3;
await prisma.competitorSnapshot.create({
data: {
competitorId: competitor.id,
brandId: brand.id,
date,
movement: w < 3 ? `#${5 - w} → #${3 - w > 0 ? 3 - w : 1}` : "Stable",
rankChange: w < 4 ? Math.round(Math.random() * 3) : 0,
aiMentions: Math.round(baseAi * (1 + (12 - w) / 12 * 0.3) + (Math.random() - 0.5) * 2),
aiMentionChange: w < 6 ? Math.round((Math.random() - 0.3) * 3) : 0,
trafficEstimate: Math.round((5000 + Math.random() * 10000) * (1 + (12 - w) / 12 * 0.15)),
topKeyword: c.name === "RankBoost.io" ? "project management SEO tool" : c.name === "ContentKing" ? "technical SEO audit" : "local SEO services",
threat,
},
});
}
}
console.log(` Competitors: ${comps.length} with 13 weekly snapshots each for ${brand.name}`);
}
console.log("AI visibility + competitors seeding complete!");
}
main()
.catch((e) => { console.error(e); process.exit(1); })
.finally(() => prisma.$disconnect());