Files
BelgianBitcoinEmbassy/frontend/app/blog/page.tsx
T
bbeandCursor 2ef68222bf 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>
2026-06-29 03:57:32 +02:00

72 lines
2.0 KiB
TypeScript

import { Navbar } from "@/components/public/Navbar";
import { Footer } from "@/components/public/Footer";
import {
BlogIndex,
type BlogPost,
type BlogCategory,
} from "@/components/public/BlogIndex";
import { BreadcrumbJsonLd } from "@/components/public/JsonLd";
import { apiUrl } from "@/lib/api-base";
const LIMIT = 9;
// Render at request time so the first page of posts is in the HTML for crawlers.
export const dynamic = "force-dynamic";
async function fetchJson<T>(path: string, fallback: T): Promise<T> {
try {
const res = await fetch(apiUrl(path), { cache: "no-store" });
if (!res.ok) return fallback;
return (await res.json()) as T;
} catch {
return fallback;
}
}
export default async function BlogPage() {
const [{ posts, total }, categories] = await Promise.all([
fetchJson<{ posts: BlogPost[]; total: number }>(`/posts?page=1&limit=${LIMIT}`, {
posts: [],
total: 0,
}),
fetchJson<BlogCategory[]>("/categories", []),
]);
return (
<>
<BreadcrumbJsonLd
items={[
{ name: "Home", href: "/" },
{ name: "Blog", href: "/blog" },
]}
/>
<Navbar />
<div className="min-h-screen">
<header className="pt-24 pb-16 px-8">
<div className="max-w-7xl mx-auto">
<p className="uppercase tracking-[0.2em] text-primary mb-4 font-semibold text-sm">
From the Nostr Network
</p>
<h1 className="text-5xl md:text-7xl font-black tracking-tighter mb-4">
Blog
</h1>
<p className="text-xl text-on-surface-variant max-w-xl leading-relaxed">
Curated Bitcoin content from the Nostr network
</p>
</div>
</header>
<BlogIndex
initialPosts={Array.isArray(posts) ? posts : []}
initialTotal={total ?? 0}
categories={Array.isArray(categories) ? categories : []}
limit={LIMIT}
/>
</div>
<Footer />
</>
);
}