feat: resolve live Nostr references in blog posts and add embeds
Support naddr/nevent/note slugs for unindexed posts, cache naddr lookups, render Nostr embeds in markdown, and add a consistency check for events mirrors. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,39 +2,15 @@ import { Navbar } from "@/components/public/Navbar";
|
||||
import { Footer } from "@/components/public/Footer";
|
||||
import { MeetupCard } from "@/components/public/MeetupCard";
|
||||
import { AddToCalendarButton } from "@/components/public/AddToCalendarDialog";
|
||||
import { getMeetupStartUtc } from "@/lib/meetupEventTime";
|
||||
import { apiUrl } from "@/lib/api-base";
|
||||
import { fetchMeetupsLive, partitionMeetups } from "@/lib/meetupsData";
|
||||
|
||||
// Re-render at most every 5 minutes so the upcoming/past split stays current.
|
||||
export const revalidate = 300;
|
||||
|
||||
async function fetchMeetups(): Promise<any[]> {
|
||||
try {
|
||||
const res = await fetch(apiUrl("/meetups"), { next: { revalidate: 300 } });
|
||||
if (!res.ok) return [];
|
||||
const data = await res.json();
|
||||
return Array.isArray(data) ? data : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
// Render at request time from the live backend so crawlers (no JS) always get
|
||||
// the real list, and the count stays in lock-step with /events.md and /llms.txt.
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function EventsPage() {
|
||||
const meetups = await fetchMeetups();
|
||||
|
||||
const now = new Date();
|
||||
const upcoming = meetups.filter((m) => {
|
||||
const start = getMeetupStartUtc(m.date, m.time || "00:00");
|
||||
if (Number.isNaN(start.getTime())) return false;
|
||||
return start >= now;
|
||||
});
|
||||
const past = meetups
|
||||
.filter((m) => {
|
||||
const start = getMeetupStartUtc(m.date, m.time || "00:00");
|
||||
if (Number.isNaN(start.getTime())) return false;
|
||||
return start < now;
|
||||
})
|
||||
.reverse();
|
||||
const meetups = await fetchMeetupsLive();
|
||||
const { upcoming, past } = partitionMeetups(meetups);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -54,7 +30,11 @@ export default async function EventsPage() {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="max-w-6xl mx-auto px-8 pb-24 space-y-20">
|
||||
<div
|
||||
className="max-w-6xl mx-auto px-8 pb-24 space-y-20"
|
||||
data-upcoming-count={upcoming.length}
|
||||
data-past-count={past.length}
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-8">
|
||||
<h2 className="text-xl font-black flex items-center gap-3">
|
||||
|
||||
Reference in New Issue
Block a user