initial commit: rocket.new export of broadcastbeat

This commit is contained in:
Ryan Salazar
2026-05-07 16:39:17 +00:00
commit 70aa1ad46e
302 changed files with 60710 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import { NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
const PRESS_RELEASE_PATTERNS = [
/for immediate release/i,
/is pleased to announce/i,
/announced today/i,
/press release/i,
/contact:\s/i,
];
function isPressRelease(content: string): boolean {
return PRESS_RELEASE_PATTERNS.filter((p) => p.test(content)).length >= 2;
}
function countWords(text: string): number {
return (text || '').split(/\s+/).filter(Boolean).length;
}
/**
* GET /api/content/audit
* Returns a full content audit across all published articles.
*/
export async function GET() {
try {
const supabase = await createClient();
const [{ data: imported }, { data: native }] = await Promise.all([
supabase
.from('wp_imported_posts')
.select('id, title, content, status, featured_image, meta_title, meta_description, created_at')
.order('created_at', { ascending: false }),
supabase
.from('native_articles')
.select('id, title, content, status, featured_image, meta_title, meta_description, created_at')
.order('created_at', { ascending: false }),
]);
const allArticles = [
...(imported || []).map((a) => ({ ...a, source: 'imported' })),
...(native || []).map((a) => ({ ...a, source: 'native' })),
];
const published = allArticles.filter((a) => a.status === 'published');
const total = allArticles.length;
const totalPublished = published.length;
// Thin content: under 300 words
const thinContent = published.filter((a) => countWords(a.content) < 300);
// Missing featured image
const missingFeaturedImage = published.filter(
(a) => !a.featured_image || a.featured_image === ''
);
// Missing SEO meta
const missingSeoTitle = published.filter((a) => !a.meta_title || a.meta_title === '');
const missingSeoDescription = published.filter(
(a) => !a.meta_description || a.meta_description === ''
);
const missingSeoAny = published.filter(
(a) => !a.meta_title || !a.meta_description || a.meta_title === '' || a.meta_description === ''
);
// Press releases (unedited)
const pressReleases = published.filter((a) => isPressRelease(a.content || ''));
// Word count distribution
const wordCounts = published.map((a) => countWords(a.content));
const avgWordCount =
wordCounts.length > 0
? Math.round(wordCounts.reduce((s, c) => s + c, 0) / wordCounts.length)
: 0;
// Launch checklist
const launchChecklist = {
zeroPagesWithMissingFeaturedImages: missingFeaturedImage.length === 0,
zeroPagesWithThinContent: thinContent.length === 0,
zeroPagesMissingSeoMeta: missingSeoAny.length === 0,
zeroUnrewrittenPressReleases: pressReleases.length === 0,
};
return NextResponse.json({
summary: {
totalArticles: total,
totalPublished,
thinContentCount: thinContent.length,
missingFeaturedImageCount: missingFeaturedImage.length,
missingSeoTitleCount: missingSeoTitle.length,
missingSeoDescriptionCount: missingSeoDescription.length,
missingSeoAnyCount: missingSeoAny.length,
pressReleaseCount: pressReleases.length,
averageWordCount: avgWordCount,
},
launchChecklist,
details: {
thinContent: thinContent.map((a) => ({
id: a.id,
title: a.title,
wordCount: countWords(a.content),
source: a.source,
})),
missingFeaturedImage: missingFeaturedImage.map((a) => ({
id: a.id,
title: a.title,
source: a.source,
})),
missingSeoMeta: missingSeoAny.map((a) => ({
id: a.id,
title: a.title,
missingTitle: !a.meta_title,
missingDescription: !a.meta_description,
source: a.source,
})),
pressReleases: pressReleases.map((a) => ({
id: a.id,
title: a.title,
source: a.source,
created_at: a.created_at,
})),
},
});
} catch (err: any) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}