SEO: robots.txt, sitemap, Organization & Event schema; dashboard fmtTime fix; frontend updates
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,89 +3,109 @@ 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 Event {
|
||||
interface SitemapEvent {
|
||||
id: string;
|
||||
status: string;
|
||||
startDatetime: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
async function getPublishedEvents(): Promise<Event[]> {
|
||||
/**
|
||||
* 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 response = await fetch(`${apiUrl}/api/events?status=published`, {
|
||||
next: { tags: ['events-sitemap'] },
|
||||
});
|
||||
if (!response.ok) return [];
|
||||
const data = await response.json();
|
||||
return data.events || [];
|
||||
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> {
|
||||
// Fetch published events for dynamic event pages
|
||||
const events = await getPublishedEvents();
|
||||
const events = await getIndexableEvents();
|
||||
const now = new Date();
|
||||
|
||||
// Static pages
|
||||
const staticPages: MetadataRoute.Sitemap = [
|
||||
{
|
||||
url: siteUrl,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'weekly',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/events`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'daily',
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/community`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.7,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/contact`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.6,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/faq`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.6,
|
||||
},
|
||||
// Legal pages
|
||||
{
|
||||
url: `${siteUrl}/legal/terms-policy`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.3,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/legal/privacy-policy`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.3,
|
||||
},
|
||||
{
|
||||
url: `${siteUrl}/legal/refund-cancelation-policy`,
|
||||
lastModified: new Date(),
|
||||
lastModified: now,
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.3,
|
||||
},
|
||||
];
|
||||
|
||||
// Dynamic event pages
|
||||
const eventPages: MetadataRoute.Sitemap = events.map((event) => ({
|
||||
url: `${siteUrl}/events/${event.id}`,
|
||||
lastModified: new Date(event.updatedAt),
|
||||
changeFrequency: 'weekly' as const,
|
||||
priority: 0.8,
|
||||
}));
|
||||
// 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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user