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>
This commit is contained in:
bbe
2026-06-29 00:59:41 +02:00
co-authored by Cursor
parent 99380ef6aa
commit 6023991f5c
27 changed files with 1082 additions and 401 deletions
+12 -1
View File
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
import EventDetailClient from "./EventDetailClient";
import { EventJsonLd, BreadcrumbJsonLd } from "@/components/public/JsonLd";
import { apiUrl } from "@/lib/api-base";
import { getMeetupStartUtc, getMeetupEndUtc } from "@/lib/meetupEventTime";
async function fetchEvent(id: string) {
try {
@@ -59,6 +60,15 @@ export default async function EventDetailPage({ params }: Props) {
const event = await fetchEvent(id);
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://belgianbitcoinembassy.org";
let startDate = event?.date;
let endDate: string | undefined;
if (event?.date) {
const start = getMeetupStartUtc(event.date, event.time || "00:00");
if (!Number.isNaN(start.getTime())) startDate = start.toISOString();
const end = getMeetupEndUtc(event.date, event.time || "");
if (end && !Number.isNaN(end.getTime())) endDate = end.toISOString();
}
return (
<>
{event && (
@@ -66,7 +76,8 @@ export default async function EventDetailPage({ params }: Props) {
<EventJsonLd
name={event.title}
description={event.description}
startDate={event.date}
startDate={startDate}
endDate={endDate}
location={event.location}
url={`${siteUrl}/events/${id}`}
imageUrl={event.imageId ? `${siteUrl}/media/${event.imageId}` : undefined}