kennzeichen-seite/frontend/app/blog/[slug]/page.tsx
2026-05-20 20:47:07 +02:00

32 lines
1.9 KiB
TypeScript

export const dynamic = 'force-dynamic';
import { pb, type BlogPost } from "@/lib/pb";
import Link from "next/link";
import { notFound } from "next/navigation";
interface Props { params: { slug: string } }
async function getPost(slug: string) {
try { return await pb.collection("blog_posts").getFirstListItem<BlogPost>(`slug="${slug}"`); }
catch { return null; }
}
export default async function BlogPostPage({ params }: Props) {
const post = await getPost(params.slug);
if (!post) notFound();
const html = post.inhalt
.replace(/^### (.+)$/gm,"<h3>$1</h3>").replace(/^## (.+)$/gm,"<h2>$1</h2>").replace(/^# (.+)$/gm,"<h1>$1</h1>")
.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>").replace(/\*(.+?)\*/g,"<em>$1</em>")
.replace(/`(.+?)`/g,"<code>$1</code>").replace(/\[(.+?)\]\((.+?)\)/g,'<a href="$2">$1</a>')
.replace(/\n\n/g,"</p><p>").replace(/^/,"<p>").replace(/$/,"</p>");
return (
<div className="max-w-2xl mx-auto px-6 py-12">
<Link href="/blog" className="text-sm text-[var(--muted)] hover:text-[var(--ink)] transition-colors mb-8 inline-block"> Blog</Link>
<article>
<time className="text-xs font-mono text-[var(--muted)]">{post.date ? new Date(post.date).toLocaleDateString("de-DE",{day:"numeric",month:"long",year:"numeric"}) : ""}</time>
<h1 style={{ fontFamily:"'Syne',sans-serif", fontWeight:800, fontSize:"2rem", letterSpacing:"-0.03em", lineHeight:1.1 }} className="mt-3 mb-6 text-[var(--ink)]">{post.titel}</h1>
{post.tags?.length > 0 && <div className="flex flex-wrap gap-1.5 mb-8">{post.tags.map(tag => <span key={tag} className="text-xs px-2 py-0.5 bg-[var(--warm)] rounded-sm text-[var(--muted)]">{tag}</span>)}</div>}
<div className="prose prose-sm max-w-none prose-headings:font-['Syne'] prose-a:text-[var(--accent)] prose-code:bg-[var(--warm)] prose-code:px-1 prose-code:rounded" dangerouslySetInnerHTML={{ __html: html }} />
</article>
</div>
);
}