Merge pull request 'Fix stale featured event on homepage: revalidate cache when featured event changes' (#11) from dev into main

Reviewed-on: #11
This commit is contained in:
2026-02-16 22:44:19 +00:00
3 changed files with 35 additions and 23 deletions

View File

@@ -0,0 +1,22 @@
// Trigger frontend cache revalidation (fire-and-forget)
// Revalidates both the sitemap and the next-event data (homepage, llms.txt)
export 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 frontend revalidation');
return;
}
fetch(`${frontendUrl}/api/revalidate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret, tag: ['events-sitemap', 'next-event'] }),
})
.then((res) => {
if (!res.ok) console.error('Frontend revalidation failed:', res.status);
else console.log('Frontend revalidation triggered (sitemap + next-event)');
})
.catch((err) => {
console.error('Frontend revalidation error:', err.message);
});
}

View File

@@ -5,6 +5,7 @@ import { db, dbGet, dbAll, events, tickets, payments, eventPaymentOverrides, ema
import { eq, desc, and, gte, sql } from 'drizzle-orm';
import { requireAuth, getAuthUser } from '../lib/auth.js';
import { generateId, getNow, convertBooleansForDb, toDbDate, calculateAvailableSeats } from '../lib/utils.js';
import { revalidateFrontendCache } from '../lib/revalidate.js';
interface UserContext {
id: string;
@@ -15,29 +16,6 @@ interface UserContext {
const eventsRouter = new Hono<{ Variables: { user: UserContext } }>();
// 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 frontend revalidation');
return;
}
fetch(`${frontendUrl}/api/revalidate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret, tag: ['events-sitemap', 'next-event'] }),
})
.then((res) => {
if (!res.ok) console.error('Frontend revalidation failed:', res.status);
else console.log('Frontend revalidation triggered (sitemap + next-event)');
})
.catch((err) => {
console.error('Frontend revalidation error:', err.message);
});
}
// Helper to normalize event data for API response
// PostgreSQL decimal returns strings, booleans are stored as integers
function normalizeEvent(event: any) {

View File

@@ -5,6 +5,7 @@ import { db, dbGet, siteSettings, events } from '../db/index.js';
import { eq, and, gte } from 'drizzle-orm';
import { requireAuth } from '../lib/auth.js';
import { generateId, getNow, toDbBool } from '../lib/utils.js';
import { revalidateFrontendCache } from '../lib/revalidate.js';
interface UserContext {
id: string;
@@ -172,6 +173,11 @@ siteSettingsRouter.put('/', requireAuth(['admin']), zValidator('json', updateSit
(db as any).select().from(siteSettings).where(eq((siteSettings as any).id, existing.id))
);
// Revalidate frontend cache if featured event changed
if (data.featuredEventId !== undefined) {
revalidateFrontendCache();
}
return c.json({ settings: updated, message: 'Settings updated successfully' });
});
@@ -216,6 +222,9 @@ siteSettingsRouter.put('/featured-event', requireAuth(['admin']), zValidator('js
await (db as any).insert(siteSettings).values(newSettings);
// Revalidate frontend cache so homepage shows the updated featured event
revalidateFrontendCache();
return c.json({ featuredEventId: eventId, message: eventId ? 'Event set as featured' : 'Featured event removed' });
}
@@ -229,6 +238,9 @@ siteSettingsRouter.put('/featured-event', requireAuth(['admin']), zValidator('js
})
.where(eq((siteSettings as any).id, existing.id));
// Revalidate frontend cache so homepage shows the updated featured event
revalidateFrontendCache();
return c.json({ featuredEventId: eventId, message: eventId ? 'Event set as featured' : 'Featured event removed' });
});