Files
BelgianBitcoinEmbassy/frontend/app/events/page.tsx
T
bbeandCursor 6023991f5c feat: add SEO metadata, llms.txt, and markdown page mirrors
Centralize site metadata and social URLs for JSON-LD, expose llmstxt.org
content and per-page .md routes for LLM crawlers, and refactor blog/FAQ/events
pages with shared components.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 00:59:41 +02:00

104 lines
3.4 KiB
TypeScript

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";
// 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 [];
}
}
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();
return (
<>
<Navbar />
<div className="min-h-screen">
<header className="pt-24 pb-12 px-8">
<div className="max-w-6xl mx-auto">
<p className="uppercase tracking-[0.2em] text-primary mb-2 font-semibold text-xs">
Belgian Bitcoin Embassy
</p>
<h1 className="text-4xl md:text-6xl font-black tracking-tighter mb-4">
All Events
</h1>
<p className="text-on-surface-variant max-w-md leading-relaxed">
Past and upcoming Bitcoin meetups in Belgium.
</p>
</div>
</header>
<div className="max-w-6xl mx-auto px-8 pb-24 space-y-20">
<div>
<div className="flex items-center justify-between mb-8">
<h2 className="text-xl font-black flex items-center gap-3">
Upcoming
{upcoming.length > 0 && (
<span className="text-xs font-bold bg-primary/10 text-primary px-2.5 py-1 rounded-full">
{upcoming.length}
</span>
)}
</h2>
<AddToCalendarButton />
</div>
{upcoming.length === 0 ? (
<div className="border border-zinc-800/60 rounded-xl px-8 py-12 text-center">
<p className="text-on-surface-variant text-sm">
No upcoming events scheduled. Check back soon.
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
{upcoming.map((m) => (
<MeetupCard key={m.id} meetup={m} />
))}
</div>
)}
</div>
{past.length > 0 && (
<div>
<h2 className="text-xl font-black mb-8 text-on-surface-variant/60">
Past Events
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
{past.map((m) => (
<MeetupCard key={m.id} meetup={m} muted />
))}
</div>
</div>
)}
</div>
</div>
<Footer />
</>
);
}