import { createClient } from '@supabase/supabase-js';
export const dynamic = 'force-dynamic';
export const revalidate = 600; // 10 min — Google rechecks frequently
// Google News sitemap. Only original-editorial articles (ai_rewritten_at IS
// NOT NULL or rewritten-articles surface) from the last 48 hours so we
// stay inside the GN window. Standard sitemap.xml covers older pages.
const PUBLICATION_NAME = 'AV Beat';
const PUBLICATION_LANG = 'en';
const HOST = 'https://avbeat.com';
function esc(s: string): string {
return (s || '').replace(/[&<>"']/g, (c) =>
({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c] as string));
}
export async function GET() {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
const schema = process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || 'bb';
const sb = createClient(url, key, { db: { schema: schema as 'public' }, auth: { persistSession: false } });
const since = new Date(Date.now() - 48 * 3600 * 1000).toISOString();
const [{ data: imported }, { data: rewritten }] = await Promise.all([
sb.from('wp_imported_posts')
.select('wp_slug, title, wp_published_at, ai_rewritten_at, author_name, tags')
.eq('status', 'published')
.not('ai_rewritten_at', 'is', null)
.gte('wp_published_at', since)
.order('wp_published_at', { ascending: false })
.limit(1000),
sb.from('ai_rewritten_articles')
.select('slug, title, published_at, category, source_author')
.eq('status', 'published')
.gte('published_at', since)
.order('published_at', { ascending: false })
.limit(1000),
]);
const entries: string[] = [];
for (const a of imported || []) {
const pubDate = a.wp_published_at || a.ai_rewritten_at;
if (!pubDate) continue;
const tags = Array.isArray(a.tags) ? (a.tags as string[]).slice(0, 5).join(', ') : '';
entries.push(`
${HOST}/news/${esc(a.wp_slug)}
${PUBLICATION_NAME}
${PUBLICATION_LANG}
${pubDate}
${esc(a.title)}${tags ? `\n ${esc(tags)}` : ''}
`);
}
for (const a of rewritten || []) {
if (!a.published_at) continue;
entries.push(`
${HOST}/articles/${esc(a.slug)}
${PUBLICATION_NAME}
${PUBLICATION_LANG}
${a.published_at}
${esc(a.title)}${a.category ? `\n ${esc(a.category)}` : ''}
`);
}
const body = `
${entries.join('\n')}
`;
return new Response(body, {
status: 200,
headers: {
'content-type': 'application/xml; charset=utf-8',
'cache-control': 'public, max-age=300, s-maxage=600',
},
});
}