Files
portfolio/app/_ui/HomePageServer.tsx
denshooter 77db462c22
Some checks failed
CI / CD / deploy-dev (push) Has been cancelled
CI / CD / deploy-production (push) Has been cancelled
CI / CD / test-build (push) Has been cancelled
fix: add SSR-safe ScrollFadeIn component for scroll animations
ScrollFadeIn uses IntersectionObserver + CSS transitions instead of
Framer Motion's initial prop. Key difference: no inline style in SSR
HTML, so content is visible by default. Animation only activates
after client hydration (hasMounted check).

Wraps About, Projects, Contact, Footer in HomePageServer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-04 23:41:02 +01:00

142 lines
4.7 KiB
TypeScript

import Header from "../components/Header.server";
import Hero from "../components/Hero";
import ScrollFadeIn from "../components/ScrollFadeIn";
import Script from "next/script";
import {
getAboutTranslations,
getProjectsTranslations,
getContactTranslations,
getFooterTranslations,
} from "@/lib/translations-loader";
import {
AboutClient,
ProjectsClient,
ContactClient,
FooterClient,
} from "../components/ClientWrappers";
interface HomePageServerProps {
locale: string;
}
export default async function HomePageServer({ locale }: HomePageServerProps) {
// Parallel laden aller Translations (hero translations handled by Hero server component)
const [aboutT, projectsT, contactT, footerT] = await Promise.all([
getAboutTranslations(locale),
getProjectsTranslations(locale),
getContactTranslations(locale),
getFooterTranslations(locale),
]);
return (
<div className="min-h-screen">
<Script
id={"structured-data"}
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Person",
name: "Dennis Konkol",
url: "https://dk0.dev",
jobTitle: "Software Engineer",
address: {
"@type": "PostalAddress",
addressLocality: "Osnabrück",
addressCountry: "Germany",
},
sameAs: [
"https://github.com/Denshooter",
"https://linkedin.com/in/dkonkol",
],
}),
}}
/>
<Header locale={locale} />
{/* Spacer to prevent navbar overlap */}
<div className="h-24 md:h-32" aria-hidden="true"></div>
<main className="relative">
<Hero locale={locale} />
{/* Wavy Separator 1 - Hero to About */}
<div className="relative h-24 overflow-hidden">
<svg
className="absolute inset-0 w-full h-full"
viewBox="0 0 1440 120"
preserveAspectRatio="none"
>
<path
d="M0,64 C240,96 480,32 720,64 C960,96 1200,32 1440,64 L1440,120 L0,120 Z"
fill="url(#gradient1)"
/>
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#BAE6FD" stopOpacity="0.4" />
<stop offset="50%" stopColor="#DDD6FE" stopOpacity="0.4" />
<stop offset="100%" stopColor="#FBCFE8" stopOpacity="0.4" />
</linearGradient>
</defs>
</svg>
</div>
<ScrollFadeIn>
<AboutClient locale={locale} translations={aboutT} />
</ScrollFadeIn>
{/* Wavy Separator 2 - About to Projects */}
<div className="relative h-24 overflow-hidden">
<svg
className="absolute inset-0 w-full h-full"
viewBox="0 0 1440 120"
preserveAspectRatio="none"
>
<path
d="M0,64 C360,96 720,32 1080,64 C1200,96 1320,32 1440,64 L1440,0 L0,0 Z"
fill="url(#gradient2)"
/>
<defs>
<linearGradient id="gradient2" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#A7F3D0" stopOpacity="0.3" />
<stop offset="50%" stopColor="#BFDBFE" stopOpacity="0.3" />
<stop offset="100%" stopColor="#DDD6FE" stopOpacity="0.3" />
</linearGradient>
</defs>
</svg>
</div>
<ScrollFadeIn>
<ProjectsClient locale={locale} translations={projectsT} />
</ScrollFadeIn>
{/* Wavy Separator 3 - Projects to Contact */}
<div className="relative h-24 overflow-hidden">
<svg
className="absolute inset-0 w-full h-full"
viewBox="0 0 1440 120"
preserveAspectRatio="none"
>
<path
d="M0,32 C240,64 480,0 720,32 C960,64 1200,0 1440,32 L1440,120 L0,120 Z"
fill="url(#gradient3)"
/>
<defs>
<linearGradient id="gradient3" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#FDE68A" stopOpacity="0.3" />
<stop offset="50%" stopColor="#FCA5A5" stopOpacity="0.3" />
<stop offset="100%" stopColor="#C4B5FD" stopOpacity="0.3" />
</linearGradient>
</defs>
</svg>
</div>
<ScrollFadeIn>
<ContactClient locale={locale} translations={contactT} />
</ScrollFadeIn>
</main>
<ScrollFadeIn>
<FooterClient locale={locale} translations={footerT} />
</ScrollFadeIn>
</div>
);
}