112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
import { MetadataRoute } from 'next';
|
|
|
|
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://spanglish.com.py';
|
|
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
|
|
|
interface SitemapEvent {
|
|
id: string;
|
|
status: string;
|
|
startDatetime: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
/**
|
|
* Fetch all indexable events: published, completed, and cancelled.
|
|
* Sold-out / past events stay in the index (marked as expired, not removed).
|
|
* Only draft and archived events are excluded.
|
|
*/
|
|
async function getIndexableEvents(): Promise<SitemapEvent[]> {
|
|
try {
|
|
const [publishedRes, completedRes] = await Promise.all([
|
|
fetch(`${apiUrl}/api/events?status=published`, {
|
|
next: { tags: ['events-sitemap'] },
|
|
}),
|
|
fetch(`${apiUrl}/api/events?status=completed`, {
|
|
next: { tags: ['events-sitemap'] },
|
|
}),
|
|
]);
|
|
|
|
const published = publishedRes.ok
|
|
? ((await publishedRes.json()).events as SitemapEvent[]) || []
|
|
: [];
|
|
const completed = completedRes.ok
|
|
? ((await completedRes.json()).events as SitemapEvent[]) || []
|
|
: [];
|
|
|
|
return [...published, ...completed];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
|
const events = await getIndexableEvents();
|
|
const now = new Date();
|
|
|
|
// Static pages
|
|
const staticPages: MetadataRoute.Sitemap = [
|
|
{
|
|
url: siteUrl,
|
|
lastModified: now,
|
|
changeFrequency: 'weekly',
|
|
priority: 1,
|
|
},
|
|
{
|
|
url: `${siteUrl}/events`,
|
|
lastModified: now,
|
|
changeFrequency: 'daily',
|
|
priority: 0.9,
|
|
},
|
|
{
|
|
url: `${siteUrl}/community`,
|
|
lastModified: now,
|
|
changeFrequency: 'monthly',
|
|
priority: 0.7,
|
|
},
|
|
{
|
|
url: `${siteUrl}/contact`,
|
|
lastModified: now,
|
|
changeFrequency: 'monthly',
|
|
priority: 0.6,
|
|
},
|
|
{
|
|
url: `${siteUrl}/faq`,
|
|
lastModified: now,
|
|
changeFrequency: 'monthly',
|
|
priority: 0.6,
|
|
},
|
|
// Legal pages
|
|
{
|
|
url: `${siteUrl}/legal/terms-policy`,
|
|
lastModified: now,
|
|
changeFrequency: 'yearly',
|
|
priority: 0.3,
|
|
},
|
|
{
|
|
url: `${siteUrl}/legal/privacy-policy`,
|
|
lastModified: now,
|
|
changeFrequency: 'yearly',
|
|
priority: 0.3,
|
|
},
|
|
{
|
|
url: `${siteUrl}/legal/refund-cancelation-policy`,
|
|
lastModified: now,
|
|
changeFrequency: 'yearly',
|
|
priority: 0.3,
|
|
},
|
|
];
|
|
|
|
// Dynamic event pages — upcoming events get higher priority
|
|
const eventPages: MetadataRoute.Sitemap = events.map((event) => {
|
|
const isUpcoming = new Date(event.startDatetime) > now;
|
|
return {
|
|
url: `${siteUrl}/events/${event.id}`,
|
|
lastModified: new Date(event.updatedAt),
|
|
changeFrequency: isUpcoming ? ('weekly' as const) : ('monthly' as const),
|
|
priority: isUpcoming ? 0.8 : 0.5,
|
|
};
|
|
});
|
|
|
|
return [...staticPages, ...eventPages];
|
|
}
|