Make next event visible to AI crawlers (SSR, JSON-LD, meta, llms.txt)
- SSR next event on homepage; pass initialEvent from server to avoid client-only content - Add schema.org Event JSON-LD on homepage when next event exists - Dynamic homepage metadata (description, OG, Twitter) with next event date - Add dynamic /llms.txt route for AI-friendly plain-text event info - Revalidation: support next-event tag; backend revalidates sitemap + next-event on event CUD - Allow /llms.txt in robots.txt Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,25 +15,26 @@ interface UserContext {
|
||||
|
||||
const eventsRouter = new Hono<{ Variables: { user: UserContext } }>();
|
||||
|
||||
// Trigger frontend sitemap revalidation (fire-and-forget)
|
||||
function revalidateSitemap() {
|
||||
// Trigger frontend cache revalidation (fire-and-forget)
|
||||
// Revalidates both the sitemap and the next-event data (homepage, llms.txt)
|
||||
function revalidateFrontendCache() {
|
||||
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3002';
|
||||
const secret = process.env.REVALIDATE_SECRET;
|
||||
if (!secret) {
|
||||
console.warn('REVALIDATE_SECRET not set, skipping sitemap revalidation');
|
||||
console.warn('REVALIDATE_SECRET not set, skipping frontend revalidation');
|
||||
return;
|
||||
}
|
||||
fetch(`${frontendUrl}/api/revalidate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ secret, tag: 'events-sitemap' }),
|
||||
body: JSON.stringify({ secret, tag: ['events-sitemap', 'next-event'] }),
|
||||
})
|
||||
.then((res) => {
|
||||
if (!res.ok) console.error('Sitemap revalidation failed:', res.status);
|
||||
else console.log('Sitemap revalidation triggered');
|
||||
if (!res.ok) console.error('Frontend revalidation failed:', res.status);
|
||||
else console.log('Frontend revalidation triggered (sitemap + next-event)');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Sitemap revalidation error:', err.message);
|
||||
console.error('Frontend revalidation error:', err.message);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -360,7 +361,7 @@ eventsRouter.post('/', requireAuth(['admin', 'organizer']), zValidator('json', c
|
||||
await (db as any).insert(events).values(newEvent);
|
||||
|
||||
// Revalidate sitemap when a new event is created
|
||||
revalidateSitemap();
|
||||
revalidateFrontendCache();
|
||||
|
||||
// Return normalized event data
|
||||
return c.json({ event: normalizeEvent(newEvent) }, 201);
|
||||
@@ -399,7 +400,7 @@ eventsRouter.put('/:id', requireAuth(['admin', 'organizer']), zValidator('json',
|
||||
);
|
||||
|
||||
// Revalidate sitemap when an event is updated (status/dates may have changed)
|
||||
revalidateSitemap();
|
||||
revalidateFrontendCache();
|
||||
|
||||
return c.json({ event: normalizeEvent(updated) });
|
||||
});
|
||||
@@ -458,7 +459,7 @@ eventsRouter.delete('/:id', requireAuth(['admin']), async (c) => {
|
||||
await (db as any).delete(events).where(eq((events as any).id, id));
|
||||
|
||||
// Revalidate sitemap when an event is deleted
|
||||
revalidateSitemap();
|
||||
revalidateFrontendCache();
|
||||
|
||||
return c.json({ message: 'Event deleted successfully' });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user