32 lines
1.9 KiB
TypeScript
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>
|
|
);
|
|
}
|