Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 1m24s
Build & Deploy / 🏗️ Build (push) Failing after 4m3s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 5s
- Refined hero sections for About, Blog, Websites, and Case Studies for a bespoke industrial entry point. - Redesigned Marker component using layered SVG paths for an organic, hand-drawn highlighter effect. - Restored technical precision in ArchitectureVisualizer with refined line thickness. - Streamlined contact page by removing generic headers and prioritizing the configurator/gateway. - Updated technical references to reflect self-hosted Gitea infrastructure. - Cleaned up unused imports and addressed linting warnings across modified pages.
112 lines
4.3 KiB
TypeScript
112 lines
4.3 KiB
TypeScript
import * as React from "react";
|
|
import { notFound } from "next/navigation";
|
|
import { blogPosts } from "../../../src/data/blogPosts";
|
|
import { PageHeader } from "../../../src/components/PageHeader";
|
|
import { Section } from "../../../src/components/Section";
|
|
import { Reveal } from "../../../src/components/Reveal";
|
|
import { BlogPostClient } from "../../../src/components/BlogPostClient";
|
|
import { PostComponents } from "../../../src/components/blog/posts";
|
|
import { Card } from "../../../src/components/Layout";
|
|
|
|
export async function generateStaticParams() {
|
|
return blogPosts.map((post) => ({
|
|
slug: post.slug,
|
|
}));
|
|
}
|
|
|
|
export default async function BlogPostPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ slug: string }>;
|
|
}) {
|
|
const { slug } = await params;
|
|
const post = blogPosts.find((p) => p.slug === slug);
|
|
|
|
if (!post) {
|
|
notFound();
|
|
}
|
|
|
|
const formattedDate = new Date(post.date).toLocaleDateString("de-DE", {
|
|
month: "long",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
});
|
|
|
|
const wordCount = post.description.split(/\s+/).length + 300; // Average post length
|
|
const readingTime = Math.max(1, Math.ceil(wordCount / 200));
|
|
|
|
const PostContent = PostComponents[slug];
|
|
|
|
return (
|
|
<div className="flex flex-col gap-8 md:gap-12 py-8 md:py-24 overflow-hidden">
|
|
<BlogPostClient readingTime={readingTime} title={post.title} />
|
|
|
|
<PageHeader
|
|
variant="blog"
|
|
title={post.title}
|
|
description={post.description}
|
|
backgroundSymbol={slug.charAt(0).toUpperCase()}
|
|
/>
|
|
|
|
<main id="post-content">
|
|
<Section containerVariant="wide" className="pt-0 md:pt-0">
|
|
<div className="max-w-5xl mx-auto px-0 sm:px-4 md:px-0">
|
|
<Reveal delay={0.4} width="100%">
|
|
<Card
|
|
variant="glass"
|
|
techBorder
|
|
className="relative overflow-hidden rounded-none sm:rounded-3xl"
|
|
>
|
|
{/* Decorative background grid inside the card */}
|
|
<div className="absolute inset-0 opacity-[0.03] bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]" />
|
|
|
|
<div className="relative z-10 px-5 py-10 md:px-16 md:py-20">
|
|
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 text-[9px] md:text-[10px] font-bold text-slate-400 mb-10 md:mb-12 uppercase tracking-[0.2em] border-b border-slate-100 pb-6">
|
|
<div className="flex items-center gap-3">
|
|
<span className="w-2 h-2 rounded-full bg-slate-300" />
|
|
<time dateTime={post.date}>{formattedDate}</time>
|
|
</div>
|
|
<div className="flex items-center gap-4 sm:gap-6">
|
|
<div className="flex items-center gap-2">
|
|
<span className="text-slate-200 hidden sm:inline">
|
|
|
|
|
</span>
|
|
<span>{readingTime} min Lesezeit</span>
|
|
</div>
|
|
<span>
|
|
{slug.substring(0, 4).toUpperCase()}-
|
|
{Math.floor(Math.random() * 999)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{post.tags && post.tags.length > 0 && (
|
|
<div className="flex flex-wrap gap-2 mb-10 md:mb-12">
|
|
{post.tags.map((tag, index) => (
|
|
<span
|
|
key={tag}
|
|
className="px-2.5 py-1 bg-slate-50 border border-slate-100 rounded text-[9px] md:text-[10px] font-mono text-slate-500 uppercase tracking-widest"
|
|
>
|
|
#{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{PostContent ? (
|
|
<PostContent />
|
|
) : (
|
|
<div className="p-8 bg-slate-50 border border-slate-200 rounded-lg italic text-slate-500">
|
|
Inhalt wird bald veröffentlicht...
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
</Reveal>
|
|
</div>
|
|
</Section>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|