feat: unify code-like components with shared CodeWindow, fix blog re-render loop, and stabilize layouts
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Failing after 1m2s
Build & Deploy / 🏗️ Build (push) Failing after 3m44s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Failing after 1m2s
Build & Deploy / 🏗️ Build (push) Failing after 3m44s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { PageHeader } from "../../src/components/PageHeader";
|
||||
import { Section } from "../../src/components/Section";
|
||||
@@ -6,7 +8,6 @@ import {
|
||||
ExperienceIllustration,
|
||||
ResponsibilityIllustration,
|
||||
ResultIllustration,
|
||||
ConceptSystem,
|
||||
ContactIllustration,
|
||||
HeroLines,
|
||||
ParticleNetwork,
|
||||
@@ -21,26 +22,23 @@ import {
|
||||
Label,
|
||||
MonoLabel,
|
||||
} from "../../src/components/Typography";
|
||||
import { BackgroundGrid, Card, Container } from "../../src/components/Layout";
|
||||
import { Card, Container } from "../../src/components/Layout";
|
||||
import { Button } from "../../src/components/Button";
|
||||
import { IconList, IconListItem } from "../../src/components/IconList";
|
||||
import {
|
||||
GradientMesh,
|
||||
CodeSnippet,
|
||||
AbstractCircuit,
|
||||
} from "../../src/components/Effects";
|
||||
import { Marker } from "../../src/components/Marker";
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="flex flex-col bg-white overflow-hidden relative">
|
||||
{/* Background Elements */}
|
||||
<ParticleNetwork className="opacity-20" />
|
||||
<BackgroundGrid />
|
||||
<AbstractCircuit />
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative pt-32 pb-24 overflow-hidden border-b border-slate-50">
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-full opacity-10 pointer-events-none">
|
||||
<HeroLines className="w-full h-full" />
|
||||
</div>
|
||||
<div className="absolute right-0 top-0 w-96 h-96 opacity-5 pointer-events-none">
|
||||
<GridLines />
|
||||
</div>
|
||||
|
||||
<Container variant="narrow" className="relative z-10">
|
||||
<div className="flex flex-col items-center text-center space-y-12">
|
||||
<Reveal>
|
||||
@@ -75,10 +73,11 @@ export default function AboutPage() {
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
Über <span className="text-slate-200">mich.</span>
|
||||
Über <span className="text-slate-400">mich.</span>
|
||||
</>
|
||||
}
|
||||
description="Warum ich tue, was ich tue – und wie Sie davon profitieren."
|
||||
description="15 Jahre Erfahrung. Ein Ziel: Websites, die ihre Versprechen halten."
|
||||
backLink={{ href: "/", label: "Zurück" }}
|
||||
className="pt-0 md:pt-0"
|
||||
/>
|
||||
</div>
|
||||
@@ -89,7 +88,7 @@ export default function AboutPage() {
|
||||
<div className="absolute bottom-0 left-1/2 -translate-x-1/2 w-px h-16 bg-gradient-to-b from-transparent to-slate-200" />
|
||||
</section>
|
||||
|
||||
{/* Section 01: Experience */}
|
||||
{/* Section 01: Story */}
|
||||
<Section
|
||||
number="01"
|
||||
title="Erfahrung"
|
||||
@@ -99,10 +98,8 @@ export default function AboutPage() {
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
15 Jahre Web-Entwicklung. <br />
|
||||
<span className="text-slate-200">
|
||||
Vom Designer zum Architekten.
|
||||
</span>
|
||||
Vom Designer <br />
|
||||
<span className="text-slate-400">zum Architekten.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
@@ -110,17 +107,20 @@ export default function AboutPage() {
|
||||
<Reveal delay={0.1}>
|
||||
<div className="space-y-8">
|
||||
<LeadText className="text-xl md:text-2xl text-slate-400">
|
||||
Ich habe Agenturen, Konzerne und Startups von innen gesehen.
|
||||
Dabei habe ich gelernt, what really counts:{" "}
|
||||
Agenturen, Konzerne, Startups – ich habe die Branche von allen
|
||||
Seiten kennengelernt. Was hängen geblieben ist:{" "}
|
||||
<span className="text-slate-900">
|
||||
Ergebnisse, nicht Prozesse.
|
||||
<Marker delay={0.2} color="rgba(148,163,184,0.15)">
|
||||
Ergebnisse zählen.
|
||||
</Marker>{" "}
|
||||
Nicht der Weg dorthin.
|
||||
</span>
|
||||
</LeadText>
|
||||
<IconList className="space-y-4">
|
||||
{[
|
||||
"Komplexe Systeme vereinfacht",
|
||||
"Performance-Probleme gelöst",
|
||||
"Nachhaltige Software-Architekturen gebaut",
|
||||
"Frontend, Backend, Infrastruktur – Fullstack",
|
||||
"Komplexe Systeme auf das Wesentliche reduziert",
|
||||
"Performance-Probleme systematisch gelöst",
|
||||
].map((item, i) => (
|
||||
<IconListItem key={i} bullet>
|
||||
<BodyText className="text-lg">{item}</BodyText>
|
||||
@@ -137,8 +137,7 @@ export default function AboutPage() {
|
||||
className="group"
|
||||
>
|
||||
<H4 className="text-2xl mb-6">
|
||||
Mein Fokus heute: Direkte Zusammenarbeit ohne
|
||||
Reibungsverluste.
|
||||
Heute: Direkte Zusammenarbeit ohne Reibungsverluste.
|
||||
</H4>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{["Effizient", "Pragmatisch", "Verlässlich"].map((tag, i) => (
|
||||
@@ -156,64 +155,77 @@ export default function AboutPage() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 02: Responsibility */}
|
||||
{/* Section 02: Arbeitsweise – HOW I work */}
|
||||
<Section
|
||||
number="02"
|
||||
title="Verantwortung"
|
||||
title="Arbeitsweise"
|
||||
variant="gray"
|
||||
borderTop
|
||||
illustration={<ResponsibilityIllustration className="w-24 h-24" />}
|
||||
effects={<GradientMesh variant="subtle" className="opacity-60" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Ich stehe für meine <br />
|
||||
<span className="text-slate-200">Arbeit gerade.</span>
|
||||
So läuft ein Projekt <br />
|
||||
<span className="text-slate-400">bei mir ab.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-center">
|
||||
<div className="md:col-span-8 space-y-8">
|
||||
<Reveal delay={0.1}>
|
||||
<LeadText className="text-xl md:text-2xl text-slate-400">
|
||||
In der klassischen Agenturwelt verschwindet Verantwortung oft
|
||||
hinter Hierarchien. Bei mir gibt es nur{" "}
|
||||
<span className="text-slate-900">einen Ansprechpartner:</span>{" "}
|
||||
Mich.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<Card
|
||||
variant="white"
|
||||
padding="normal"
|
||||
className="flex flex-row items-start gap-6 group"
|
||||
>
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-xl flex items-center justify-center shrink-0 font-bold text-xl group-hover:rotate-12 transition-transform duration-500">
|
||||
!
|
||||
{/* Timeline Steps */}
|
||||
<div className="space-y-1 relative">
|
||||
{/* Connecting line */}
|
||||
<div className="absolute left-[15px] top-8 bottom-8 w-px bg-slate-200 hidden md:block" />
|
||||
|
||||
{[
|
||||
{
|
||||
step: "01",
|
||||
title: "Briefing",
|
||||
desc: "Sie beschreiben Ihr Vorhaben. Ich höre zu und stelle die richtigen Fragen.",
|
||||
},
|
||||
{
|
||||
step: "02",
|
||||
title: "Angebot",
|
||||
desc: "Ein Fixpreis-Angebot mit klarem Leistungsumfang. Keine Überraschungen.",
|
||||
},
|
||||
{
|
||||
step: "03",
|
||||
title: "Umsetzung",
|
||||
desc: "Schnelle Iterationen. Sie sehen regelmäßig den Fortschritt und geben Feedback.",
|
||||
},
|
||||
{
|
||||
step: "04",
|
||||
title: "Launch",
|
||||
desc: "Go-Live mit automatisiertem Deployment. Dokumentiert und übergabereif.",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<Reveal key={i} delay={0.1 + i * 0.1}>
|
||||
<div className="flex gap-6 py-6 group">
|
||||
<div className="relative z-10 shrink-0">
|
||||
<div className="w-8 h-8 rounded-full bg-white border border-slate-200 flex items-center justify-center group-hover:border-slate-400 group-hover:shadow-md transition-all duration-500">
|
||||
<span className="text-[9px] font-mono font-bold text-slate-400 group-hover:text-slate-900 transition-colors">
|
||||
{item.step}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<BodyText className="text-slate-900 font-medium text-lg md:text-xl leading-relaxed">
|
||||
Ich übernehme die volle Verantwortung für die technische
|
||||
Umsetzung und Qualität Ihres Projekts. Ohne Ausreden.
|
||||
</BodyText>
|
||||
</Card>
|
||||
<div className="space-y-2 pt-1">
|
||||
<H4 className="text-xl">{item.title}</H4>
|
||||
<BodyText className="text-slate-500">{item.desc}</BodyText>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 03: Systems */}
|
||||
<Section
|
||||
number="03"
|
||||
title="Philosophie"
|
||||
borderTop
|
||||
illustration={<ConceptSystem className="w-24 h-24" />}
|
||||
>
|
||||
{/* Section 03: Philosophie – what drives me */}
|
||||
<Section number="03" title="Philosophie" borderTop>
|
||||
<div className="space-y-16">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Nachhaltigkeit durch <br />
|
||||
<span className="text-slate-200">sauberen Code.</span>
|
||||
Ich stehe für <br />
|
||||
<span className="text-slate-400">meine Arbeit gerade.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
@@ -221,24 +233,24 @@ export default function AboutPage() {
|
||||
<div className="space-y-8">
|
||||
<Reveal delay={0.1}>
|
||||
<LeadText className="text-xl text-slate-400">
|
||||
Ich baue keine Wegwerf-Produkte. Meine Systeme sind so
|
||||
konzipiert, dass sie mit Ihrem Unternehmen{" "}
|
||||
<span className="text-slate-900">wachsen können.</span>
|
||||
Keine Hierarchien, keine Ausreden. Wenn etwas nicht passt,
|
||||
liegt die Verantwortung bei mir – und ich{" "}
|
||||
<span className="text-slate-900">
|
||||
<Marker color="rgba(255,235,59,0.5)">löse es.</Marker>
|
||||
</span>
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{[
|
||||
"Skalierbar",
|
||||
"Wartbar",
|
||||
"Performant",
|
||||
"Sicher",
|
||||
"Unabhängig",
|
||||
"Zukunftssicher",
|
||||
"Vollständige Transparenz",
|
||||
"Ein Ansprechpartner",
|
||||
"Messbare Qualität",
|
||||
"Langfristige Partnerschaft",
|
||||
].map((item, i) => (
|
||||
<Reveal key={i} delay={0.2 + i * 0.05}>
|
||||
<div className="flex items-center gap-3 group">
|
||||
<div className="w-5 h-5 rounded-full bg-slate-50 flex items-center justify-center group-hover:bg-slate-900 transition-colors duration-500">
|
||||
<Check className="w-2.5 h-2.5 text-slate-400 group-hover:text-white" />
|
||||
<div className="w-6 h-6 rounded-full bg-white border border-slate-200 flex items-center justify-center shrink-0 group-hover:bg-slate-900 group-hover:border-slate-900 group-hover:shadow-lg group-hover:shadow-blue-500/10 transition-all duration-300">
|
||||
<Check className="w-3 h-3 text-slate-400 group-hover:text-white transition-colors duration-300" />
|
||||
</div>
|
||||
<Label className="text-slate-900">{item}</Label>
|
||||
</div>
|
||||
@@ -246,126 +258,47 @@ export default function AboutPage() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Decorative terminal */}
|
||||
<Reveal delay={0.3}>
|
||||
<Card
|
||||
variant="dark"
|
||||
padding="normal"
|
||||
className="relative rounded-2xl overflow-hidden group"
|
||||
>
|
||||
<div className="absolute top-0 right-0 w-48 h-48 bg-white/5 -translate-y-24 translate-x-24 rounded-full blur-3xl group-hover:bg-white/10 transition-colors duration-1000" />
|
||||
<H4 className="text-white text-2xl mb-6 relative z-10">
|
||||
Kein Vendor Lock-in.
|
||||
</H4>
|
||||
<LeadText className="text-slate-400 text-lg relative z-10 leading-relaxed">
|
||||
Sie behalten die volle Kontrolle über Ihren Code und Ihre
|
||||
Daten. Keine Abhängigkeit von proprietären Systemen.
|
||||
</LeadText>
|
||||
</Card>
|
||||
<CodeSnippet variant="terminal" className="opacity-70" />
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 04: Result */}
|
||||
{/* Section 04: CTA */}
|
||||
<Section
|
||||
number="04"
|
||||
title="Ergebnis"
|
||||
borderTop
|
||||
illustration={<ResultIllustration className="w-24 h-24" />}
|
||||
>
|
||||
<div className="space-y-16">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Was Sie von mir <br />
|
||||
<span className="text-slate-200">erwarten können.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-16">
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-6">
|
||||
<Label>Kein:</Label>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{[
|
||||
"Agentur-Zirkus",
|
||||
"Meeting-Marathon",
|
||||
"Ticket-Wahnsinn",
|
||||
"CMS-Frust",
|
||||
].map((item, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-4 py-2 border border-slate-100 rounded-full bg-slate-50/50"
|
||||
>
|
||||
<BodyText className="text-slate-400 line-through text-base mb-0">
|
||||
{item}
|
||||
</BodyText>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-6">
|
||||
<Label className="text-slate-900">Sondern (fix):</Label>
|
||||
<IconList className="space-y-8">
|
||||
{[
|
||||
{
|
||||
label: "Direkte Kommunikation",
|
||||
desc: "Kurze Wege, schnelle Entscheidungen.",
|
||||
},
|
||||
{
|
||||
label: "Echte Expertise",
|
||||
desc: "Fundiertes Wissen aus 15 Jahren Praxis.",
|
||||
},
|
||||
{
|
||||
label: "Messbare Qualität",
|
||||
desc: "Code, der hält, was er verspricht.",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<IconListItem key={i} check>
|
||||
<div className="space-y-1">
|
||||
<H4 className="text-xl leading-none">{item.label}</H4>
|
||||
<BodyText className="text-base text-slate-400">
|
||||
{item.desc}
|
||||
</BodyText>
|
||||
</div>
|
||||
</IconListItem>
|
||||
))}
|
||||
</IconList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 05: Today */}
|
||||
<Section
|
||||
number="05"
|
||||
title="Kontakt"
|
||||
variant="gray"
|
||||
borderTop
|
||||
illustration={<ContactIllustration className="w-24 h-24" />}
|
||||
effects={<GradientMesh variant="metallic" className="opacity-60" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Bereit für eine <br />
|
||||
<span className="text-slate-200">Zusammenarbeit?</span>
|
||||
<span className="text-slate-400">Zusammenarbeit?</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<Card
|
||||
variant="white"
|
||||
variant="glass"
|
||||
hover={false}
|
||||
padding="large"
|
||||
techBorder
|
||||
className="rounded-3xl shadow-xl relative overflow-hidden group"
|
||||
>
|
||||
<div className="absolute top-0 right-0 w-96 h-96 bg-slate-50 -translate-y-1/2 translate-x-1/2 rounded-full blur-[80px] group-hover:bg-slate-100 transition-colors duration-1000" />
|
||||
|
||||
<div className="relative z-10 space-y-8">
|
||||
<LeadText className="text-2xl md:text-4xl leading-tight max-w-2xl text-slate-400">
|
||||
Lassen Sie uns gemeinsam etwas bauen, das{" "}
|
||||
<span className="text-slate-900">wirklich funktioniert.</span>
|
||||
<span className="text-slate-900">
|
||||
<Marker delay={0.3} color="rgba(148,163,184,0.15)">
|
||||
wirklich funktioniert.
|
||||
</Marker>
|
||||
</span>
|
||||
</LeadText>
|
||||
|
||||
<div className="pt-4">
|
||||
|
||||
@@ -1,77 +1,113 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { MediumCard } from '../../src/components/MediumCard';
|
||||
import { SearchBar } from '../../src/components/SearchBar';
|
||||
import { Tag } from '../../src/components/Tag';
|
||||
import { blogPosts } from '../../src/data/blogPosts';
|
||||
import { PageHeader } from '../../src/components/PageHeader';
|
||||
import { Reveal } from '../../src/components/Reveal';
|
||||
import * as React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { MediumCard } from "../../src/components/MediumCard";
|
||||
import { SearchBar } from "../../src/components/SearchBar";
|
||||
import { Tag } from "../../src/components/Tag";
|
||||
import { blogPosts } from "../../src/data/blogPosts";
|
||||
import { PageHeader } from "../../src/components/PageHeader";
|
||||
import { Reveal } from "../../src/components/Reveal";
|
||||
import { Section } from "../../src/components/Section";
|
||||
import { AbstractCircuit, GradientMesh } from "../../src/components/Effects";
|
||||
import { Label } from "../../src/components/Typography";
|
||||
|
||||
export default function BlogPage() {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [filteredPosts, setFilteredPosts] = useState(blogPosts);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
|
||||
// Sort posts by date
|
||||
const allPosts = [...blogPosts].sort((a, b) =>
|
||||
new Date(b.date).getTime() - new Date(a.date).getTime()
|
||||
// Memoize allPosts to prevent infinite re-render loop
|
||||
const allPosts = React.useMemo(
|
||||
() =>
|
||||
[...blogPosts].sort(
|
||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime(),
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
// Get unique tags
|
||||
const allTags = Array.from(new Set(allPosts.flatMap(post => post.tags || [])));
|
||||
const [filteredPosts, setFilteredPosts] = useState(allPosts);
|
||||
|
||||
// Memoize allTags
|
||||
const allTags = React.useMemo(
|
||||
() => Array.from(new Set(allPosts.flatMap((post) => post.tags || []))),
|
||||
[allPosts],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
if (query.startsWith('#')) {
|
||||
if (query.startsWith("#")) {
|
||||
const tag = query.slice(1);
|
||||
setFilteredPosts(allPosts.filter(post =>
|
||||
post.tags?.some(t => t.toLowerCase() === tag.toLowerCase())
|
||||
));
|
||||
setFilteredPosts(
|
||||
allPosts.filter((post) =>
|
||||
post.tags?.some((t) => t.toLowerCase() === tag.toLowerCase()),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
setFilteredPosts(allPosts.filter(post => {
|
||||
const title = post.title.toLowerCase();
|
||||
const description = post.description.toLowerCase();
|
||||
const tags = (post.tags || []).join(' ').toLowerCase();
|
||||
return title.includes(query) || description.includes(query) || tags.includes(query);
|
||||
}));
|
||||
setFilteredPosts(
|
||||
allPosts.filter((post) => {
|
||||
const title = post.title.toLowerCase();
|
||||
const description = post.description.toLowerCase();
|
||||
const tags = (post.tags || []).join(" ").toLowerCase();
|
||||
return (
|
||||
title.includes(query) ||
|
||||
description.includes(query) ||
|
||||
tags.includes(query)
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [searchQuery]);
|
||||
}, [searchQuery, allPosts]);
|
||||
|
||||
const filterByTag = (tag: string) => {
|
||||
setSearchQuery(`#${tag}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-24 py-12 md:py-24 overflow-hidden">
|
||||
<PageHeader
|
||||
title={<>Blog <br /><span className="text-slate-200">& Notes.</span></>}
|
||||
description="A public notebook of things I figured out, mistakes I made, and tools I tested."
|
||||
<div className="flex flex-col bg-white overflow-hidden relative min-h-screen">
|
||||
<AbstractCircuit />
|
||||
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
Blog <br />
|
||||
<span className="text-slate-400">& Notes.</span>
|
||||
</>
|
||||
}
|
||||
description="Ein technisches Notizbuch über Lösungen, Fehler und Werkzeuge."
|
||||
backLink={{ href: "/", label: "Zurück" }}
|
||||
backgroundSymbol="B"
|
||||
/>
|
||||
|
||||
<section className="narrow-container">
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-16">
|
||||
<Section
|
||||
number="01"
|
||||
title="Journal"
|
||||
borderTop
|
||||
effects={<GradientMesh variant="metallic" className="opacity-50" />}
|
||||
>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16">
|
||||
{/* Sidebar / Filter area */}
|
||||
<div className="md:col-span-4">
|
||||
<div className="lg:col-span-4 lg:order-2">
|
||||
<div className="sticky top-32 space-y-16">
|
||||
<Reveal>
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Suchen</h3>
|
||||
<div className="space-y-6">
|
||||
<Label className="text-slate-400 uppercase tracking-[0.3em]">
|
||||
Suchen
|
||||
</Label>
|
||||
<SearchBar value={searchQuery} onChange={setSearchQuery} />
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{allTags.length > 0 && (
|
||||
<Reveal delay={0.2}>
|
||||
<div className="space-y-6">
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Themen</h3>
|
||||
<div className="space-y-8">
|
||||
<Label className="text-slate-400 uppercase tracking-[0.3em]">
|
||||
Themen
|
||||
</Label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{allTags.map((tag, index) => (
|
||||
<button
|
||||
key={tag}
|
||||
onClick={() => filterByTag(tag)}
|
||||
className="text-left"
|
||||
className="text-left group"
|
||||
>
|
||||
<Tag tag={tag} index={index} />
|
||||
</button>
|
||||
@@ -84,11 +120,13 @@ export default function BlogPage() {
|
||||
</div>
|
||||
|
||||
{/* Posts area */}
|
||||
<div className="md:col-span-8">
|
||||
<div id="posts-container" className="flex flex-col gap-8">
|
||||
<div className="lg:col-span-8 lg:order-1">
|
||||
<div id="posts-container" className="flex flex-col gap-12">
|
||||
{filteredPosts.length === 0 ? (
|
||||
<div className="empty-state">
|
||||
<p>No posts found matching your criteria.</p>
|
||||
<div className="py-24 text-center border border-dashed border-slate-200 rounded-3xl">
|
||||
<p className="text-slate-400 font-mono text-sm uppercase tracking-widest">
|
||||
Keine Beiträge gefunden.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
filteredPosts.map((post, i) => (
|
||||
@@ -100,7 +138,7 @@ export default function BlogPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ import {
|
||||
BodyText,
|
||||
} from "../../../src/components/Typography";
|
||||
import { BackgroundGrid, Container } from "../../../src/components/Layout";
|
||||
import { MotionButton } from "../../../src/components/Button";
|
||||
import Link from "next/link";
|
||||
import { Button } from "../../../src/components/Button";
|
||||
import { IframeSection } from "../../../src/components/IframeSection";
|
||||
import {
|
||||
Activity,
|
||||
ArrowRight,
|
||||
ArrowLeft,
|
||||
ShieldCheck,
|
||||
Cpu,
|
||||
Server,
|
||||
@@ -26,6 +28,7 @@ import {
|
||||
} from "lucide-react";
|
||||
|
||||
import { Marker } from "../../../src/components/Marker";
|
||||
import { GlitchText } from "../../../src/components/GlitchText";
|
||||
|
||||
export default function KLZCablesCaseStudy() {
|
||||
const { scrollYProgress } = useScroll();
|
||||
@@ -50,6 +53,15 @@ export default function KLZCablesCaseStudy() {
|
||||
/>
|
||||
|
||||
<Container variant="narrow" className="relative z-10">
|
||||
<Reveal>
|
||||
<Link
|
||||
href="/case-studies"
|
||||
className="inline-flex items-center gap-2 text-slate-400 hover:text-slate-900 mb-12 transition-colors font-bold text-[10px] uppercase tracking-[0.4em] group"
|
||||
>
|
||||
<ArrowLeft className="w-3 h-3 group-hover:-translate-x-1 transition-transform" />{" "}
|
||||
Zurück
|
||||
</Link>
|
||||
</Reveal>
|
||||
<div className="space-y-12">
|
||||
<Reveal direction="down" blur>
|
||||
<div className="inline-flex items-center gap-6">
|
||||
@@ -71,13 +83,14 @@ export default function KLZCablesCaseStudy() {
|
||||
</Reveal>
|
||||
|
||||
<div className="space-y-12">
|
||||
<Reveal delay={0.1} direction="up" scale={0.98} blur>
|
||||
<H1 className="text-6xl md:text-8xl tracking-tighter leading-[0.9] font-bold text-slate-900">
|
||||
KLZ Cables
|
||||
<br />
|
||||
<span className="text-slate-100">Case Study.</span>
|
||||
</H1>
|
||||
</Reveal>
|
||||
<GlitchText
|
||||
as="h1"
|
||||
className="text-6xl md:text-8xl tracking-tighter leading-[0.9] font-bold text-slate-900"
|
||||
>
|
||||
KLZ Cables
|
||||
</GlitchText>
|
||||
<br />
|
||||
<span className="text-slate-100">Case Study.</span>
|
||||
|
||||
<Reveal delay={0.2} direction="right" blur>
|
||||
<div className="max-w-3xl border-l-[3px] border-slate-900 pl-8 md:pl-12">
|
||||
@@ -126,14 +139,19 @@ export default function KLZCablesCaseStudy() {
|
||||
borderBottom
|
||||
containerVariant="normal"
|
||||
>
|
||||
{/* Binary overlay background */}
|
||||
<div className="absolute top-0 right-0 p-8 opacity-[0.03] select-none pointer-events-none font-mono text-[10px] hidden md:block">
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<div key={i}>01001101 01001001 01001110 01010100</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-16 lg:gap-24 items-start">
|
||||
<div className="md:col-span-12 mb-12">
|
||||
<Reveal direction="left" blur>
|
||||
<H2 className="text-5xl md:text-8xl tracking-tighter mb-12">
|
||||
Architektur- <br />
|
||||
Refactor.
|
||||
</H2>
|
||||
</Reveal>
|
||||
<H2 className="text-5xl md:text-8xl tracking-tighter mb-12">
|
||||
<GlitchText>Architektur-</GlitchText> <br />
|
||||
Refactor.
|
||||
</H2>
|
||||
</div>
|
||||
<div className="md:col-span-7 space-y-12">
|
||||
<Reveal delay={0.1} direction="up" blur>
|
||||
@@ -217,9 +235,16 @@ export default function KLZCablesCaseStudy() {
|
||||
Infrastructure Validation
|
||||
</Label>
|
||||
<H3 className="text-5xl md:text-8xl tracking-tighter">
|
||||
Global Hub.
|
||||
<GlitchText>Global Hub.</GlitchText>
|
||||
</H3>
|
||||
</div>
|
||||
|
||||
{/* Binary overlay left */}
|
||||
<div className="absolute left-0 bottom-0 p-8 opacity-[0.03] select-none pointer-events-none font-mono text-[10px] hidden md:block group-hover:opacity-10 transition-opacity duration-1000">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<div key={i}>HANDSHAKE_0x00{i}A // SYNC_ACTIVE</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2} width="100%" direction="up" scale={0.98} blur>
|
||||
@@ -298,12 +323,10 @@ export default function KLZCablesCaseStudy() {
|
||||
>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 items-center">
|
||||
<div className="lg:col-span-12 mb-12 text-center lg:text-left relative z-10">
|
||||
<Reveal direction="down" blur>
|
||||
<H3 className="text-4xl md:text-6xl max-w-4xl tracking-tighter">
|
||||
Fokus auf <br />
|
||||
<Marker delay={0.2}>Spezifikationen.</Marker>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<H3 className="text-4xl md:text-6xl max-w-4xl tracking-tighter">
|
||||
Fokus auf <br />
|
||||
<Marker delay={0.2}>Spezifikationen.</Marker>
|
||||
</H3>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-8 relative group">
|
||||
@@ -443,43 +466,80 @@ export default function KLZCablesCaseStudy() {
|
||||
className="!pb-32"
|
||||
>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 lg:gap-24 items-center">
|
||||
<div className="lg:col-span-5 space-y-12">
|
||||
<Reveal direction="left" blur>
|
||||
<div className="space-y-6">
|
||||
<Label className="text-slate-400">Interaction Layer</Label>
|
||||
<H3 className="text-5xl md:text-7xl tracking-tighter text-slate-900">
|
||||
Direkter Draht.
|
||||
</H3>
|
||||
<BodyText className="text-xl text-slate-500 font-serif italic leading-relaxed">
|
||||
Das Kontakt-System wurde auf maximale Reduktion getrimmt. Ein
|
||||
deterministischer Kanal zwischen technischem Bedarf und
|
||||
individueller Beratung – ohne Umwege, ohne Rauschen.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.2} direction="left" blur>
|
||||
<div className="grid grid-cols-2 gap-8 border-t border-slate-100 pt-10">
|
||||
<div className="space-y-2">
|
||||
<MonoLabel className="text-slate-400 text-[9px]">
|
||||
RESPONSE_TIME
|
||||
</MonoLabel>
|
||||
<div className="text-xl font-bold text-slate-900 font-mono">
|
||||
< 120ms
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<MonoLabel className="text-slate-400 text-[9px]">
|
||||
PROTOCOL
|
||||
</MonoLabel>
|
||||
<div className="text-xl font-bold text-slate-900 font-mono">
|
||||
mTLS
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<MonoLabel className="text-slate-400 text-[9px]">
|
||||
AVAILABILITY
|
||||
</MonoLabel>
|
||||
<div className="text-xl font-bold text-[rgba(129,199,132,1)] font-mono">
|
||||
99.9%
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<MonoLabel className="text-slate-400 text-[9px]">
|
||||
ENCRYPTION
|
||||
</MonoLabel>
|
||||
<div className="text-xl font-bold text-slate-900 font-mono">
|
||||
AES-256
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-7">
|
||||
<Reveal direction="left" scale={0.98} blur>
|
||||
<Reveal direction="right" scale={0.98} blur>
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.01 }}
|
||||
transition={{ type: "spring", stiffness: 200, damping: 20 }}
|
||||
className="relative h-[800px] w-full"
|
||||
whileHover={{ scale: 1.002 }}
|
||||
transition={{ type: "spring", stiffness: 100, damping: 30 }}
|
||||
className="relative rounded-[2.5rem] overflow-hidden shadow-2xl shadow-slate-200/50 ring-1 ring-slate-100"
|
||||
>
|
||||
<IframeSection
|
||||
src="/showcase/klz-cables.com/contact.html"
|
||||
height="100%"
|
||||
height="750px"
|
||||
desktopWidth={1200}
|
||||
mobileWidth={390}
|
||||
allowScroll
|
||||
browserFrame
|
||||
className="h-full w-full no-scrollbar"
|
||||
className="w-full no-scrollbar"
|
||||
/>
|
||||
</motion.div>
|
||||
</Reveal>
|
||||
</div>
|
||||
<div className="lg:col-span-5 space-y-10">
|
||||
<Reveal direction="right" blur>
|
||||
<div className="space-y-6">
|
||||
<Label className="text-slate-400">Conversion Layer</Label>
|
||||
<H3 className="text-4xl md:text-6xl tracking-tighter">
|
||||
Direkter Draht.
|
||||
</H3>
|
||||
<BodyText className="text-xl text-slate-500 font-serif italic">
|
||||
Das Kontakt-System wurde auf maximale Reduktion getrimmt.
|
||||
Keine unnötigen Hürden, sondern ein direkter
|
||||
Kommunikations-Kanal zwischen technischem Bedarf und
|
||||
individueller Beratung.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* --- FINAL CTA: ARCHITECTURE & VALUE --- */}
|
||||
<section className="py-40 md:py-64 bg-white relative overflow-hidden border-t border-slate-100">
|
||||
<BackgroundGrid />
|
||||
@@ -540,15 +600,15 @@ export default function KLZCablesCaseStudy() {
|
||||
</div>
|
||||
</Reveal>
|
||||
<Reveal delay={0.5} direction="up" blur className="pt-6">
|
||||
<MotionButton
|
||||
<Button
|
||||
href="/contact"
|
||||
variant="outline"
|
||||
showArrow={false}
|
||||
className="w-full py-8 text-lg group border-2 border-slate-900 rounded-full bg-white hover:bg-slate-900 hover:text-white transition-all duration-700"
|
||||
>
|
||||
Architektur-Audit anfragen
|
||||
Jetzt anfragen
|
||||
<ArrowRight className="inline-block ml-4 w-6 h-6 group-hover:translate-x-4 transition-transform duration-700" />
|
||||
</MotionButton>
|
||||
</Button>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,104 +1,175 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { PageHeader } from "../../src/components/PageHeader";
|
||||
import { Section } from "../../src/components/Section";
|
||||
import { Reveal } from "../../src/components/Reveal";
|
||||
import { H3, LeadText, Label } from "../../src/components/Typography";
|
||||
import { BackgroundGrid, Card } from "../../src/components/Layout";
|
||||
import { MotionButton } from "../../src/components/Button";
|
||||
import Image from "next/image";
|
||||
import { H3, LeadText, BodyText, Label } from "../../src/components/Typography";
|
||||
import { Card } from "../../src/components/Layout";
|
||||
import { Button } from "../../src/components/Button";
|
||||
import { GradientMesh, AbstractCircuit } from "../../src/components/Effects";
|
||||
import { ArrowRight } from "lucide-react";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
export default function CaseStudiesPage() {
|
||||
return (
|
||||
<div className="flex flex-col bg-white overflow-hidden relative min-h-screen">
|
||||
<BackgroundGrid />
|
||||
<div className="flex flex-col bg-white overflow-hidden relative">
|
||||
<AbstractCircuit />
|
||||
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
Case Studies: <br />
|
||||
<span className="text-slate-200">Qualität in jedem Detail.</span>
|
||||
Case <span className="text-slate-400">Studies.</span>
|
||||
</>
|
||||
}
|
||||
description="Ein Blick hinter die Kulissen ausgewählter Projekte. Von der ersten Idee bis zum fertigen Hochleistungssystem."
|
||||
description="Ergebnisse statt Versprechen. Was ich gebaut habe und was es bewirkt."
|
||||
backLink={{ href: "/", label: "Zurück" }}
|
||||
backgroundSymbol="C"
|
||||
/>
|
||||
|
||||
<Section number="01" title="Projekte" borderTop>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
|
||||
<Reveal>
|
||||
<Card variant="white" className="group overflow-hidden">
|
||||
<div className="aspect-video relative overflow-hidden rounded-xl mb-8 bg-slate-100 border border-slate-100">
|
||||
{/* We'll use a placeholder or a screenshot if available.
|
||||
Since we have the cloned site, we could technically iframe a preview here too,
|
||||
but a static image or a styled div is more standard for a card. */}
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-[#0117bf] transition-transform duration-700 group-hover:scale-105 p-12">
|
||||
<Image
|
||||
src="/showcase/klz-cables.com/assets/klz-cables.com/wp-content/uploads/2024/11/white_logo_transparent_background.svg"
|
||||
alt="KLZ Cables Logo"
|
||||
width={200}
|
||||
height={200}
|
||||
className="w-full h-auto max-w-[240px]"
|
||||
/>
|
||||
{/* Featured Case Study */}
|
||||
<Section
|
||||
number="01"
|
||||
title="Showcase"
|
||||
borderTop
|
||||
effects={<GradientMesh variant="metallic" className="opacity-70" />}
|
||||
>
|
||||
<Reveal>
|
||||
<a href="/case-studies/klz-cables" className="block group">
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="none"
|
||||
techBorder
|
||||
className="overflow-hidden relative group min-h-[500px] flex flex-col md:flex-row"
|
||||
>
|
||||
{/* Brand Gradient Background */}
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_30%_30%,rgba(14,165,233,0.08)_0%,transparent_50%),radial-gradient(circle_at_70%_70%,rgba(99,102,241,0.05)_0%,transparent_50%)]" />
|
||||
|
||||
{/* Left Column: Content */}
|
||||
<div className="flex-1 p-8 md:p-12 relative z-10 flex flex-col justify-between">
|
||||
<div className="space-y-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src="/showcase/klz-cables.com/assets/klz-cables.com/wp-content/uploads/2024/11/white_logo_transparent_background.svg"
|
||||
alt="KLZ Logo"
|
||||
className="h-8 invert opacity-80 group-hover:opacity-100 transition-opacity duration-500"
|
||||
/>
|
||||
<div className="h-px w-12 bg-slate-100" />
|
||||
<Label className="text-slate-400">Case Study 2025</Label>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<H3 className="text-4xl md:text-6xl tracking-tighter">
|
||||
KLZ <span className="text-slate-300">Cables</span>
|
||||
</H3>
|
||||
<LeadText className="text-slate-500 text-lg md:text-xl max-w-xl leading-relaxed">
|
||||
Engineering eines industriellen B2B-Systems mit
|
||||
<span className="text-slate-900 font-medium">
|
||||
{" "}
|
||||
automatisierter Asset-Pipeline
|
||||
</span>{" "}
|
||||
und hochperformantem Headless-Stack.
|
||||
</LeadText>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2 pt-2">
|
||||
{["Next.js", "Varnish", "Asset Pipeline", "B2B DB"].map(
|
||||
(tag, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-2.5 py-1 border border-slate-100 bg-white/50 rounded-md text-[9px] font-mono text-slate-400 uppercase tracking-widest group-hover:border-slate-300 transition-colors duration-500"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pt-12">
|
||||
<div className="inline-flex items-center gap-3 text-sm font-bold text-slate-400 group-hover:text-slate-900 transition-all duration-500">
|
||||
<span>EXPLORE PROJECT</span>
|
||||
<ArrowRight className="w-4 h-4 group-hover:translate-x-2 transition-transform duration-500" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<Label>Infrastructure & Energy</Label>
|
||||
<H3 className="group-hover:text-slate-900 transition-colors">
|
||||
KLZ Cables – Digitaler Netzbau
|
||||
</H3>
|
||||
<LeadText className="text-base line-clamp-3">
|
||||
Wie wir eine komplexe WordPress-Struktur in ein performantes,
|
||||
sauberes und langlebiges Web-System verwandelt haben. Fokus
|
||||
auf Performance, SEO und Benutzerführung.
|
||||
</LeadText>
|
||||
{/* Right Column: Visual/Technical Decor */}
|
||||
<div className="w-full md:w-1/3 bg-slate-50 relative overflow-hidden border-t md:border-t-0 md:border-l border-slate-100">
|
||||
<div className="absolute inset-0 opacity-[0.03] select-none pointer-events-none font-mono text-[8px] p-4 flex flex-col gap-1 overflow-hidden">
|
||||
{Array.from({ length: 40 }).map((_, i) => (
|
||||
<div key={i} className="whitespace-nowrap">
|
||||
{Array.from({ length: 10 })
|
||||
.map((_, j) => (
|
||||
<span
|
||||
key={j}
|
||||
className={
|
||||
Math.random() > 0.5
|
||||
? "text-slate-900"
|
||||
: "text-slate-400"
|
||||
}
|
||||
>
|
||||
{Math.floor(Math.random() * 2)}
|
||||
</span>
|
||||
))
|
||||
.join(" ")}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<MotionButton href="/case-studies/klz-cables">
|
||||
Case Study lesen
|
||||
</MotionButton>
|
||||
{/* Abstract "Cable" lines */}
|
||||
<div className="absolute inset-0 flex items-center justify-center p-12">
|
||||
<div className="w-full h-full relative">
|
||||
{[1, 2, 3].map((v) => (
|
||||
<motion.div
|
||||
key={v}
|
||||
initial={{ scaleY: 0 }}
|
||||
whileInView={{ scaleY: 1 }}
|
||||
transition={{ duration: 2, delay: 0.5 + v * 0.2 }}
|
||||
className="absolute inset-y-0 border-r border-slate-200 origin-top"
|
||||
style={{ right: `${v * 25}%` }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-8 right-8 text-[10px] font-mono text-slate-300 rotate-90 origin-right uppercase tracking-[0.3em]">
|
||||
Industrial Grade
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.2}>
|
||||
<div className="h-full flex flex-col justify-center border-2 border-dashed border-slate-100 rounded-3xl p-12 text-center space-y-4">
|
||||
<Label>Demnächst</Label>
|
||||
<H3 className="text-slate-200">
|
||||
Weitere Projekte sind in Arbeit.
|
||||
</H3>
|
||||
<LeadText className="text-base italic">
|
||||
Ich dokumentiere gerade weitere spannende Projekte aus den
|
||||
Bereichen SaaS, E-Commerce und Systemarchitektur.
|
||||
</LeadText>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</a>
|
||||
</Reveal>
|
||||
</Section>
|
||||
|
||||
<Section number="02" title="Philosophie" borderTop variant="gray">
|
||||
<div className="max-w-3xl space-y-8">
|
||||
<Reveal>
|
||||
<H3 className="text-4xl leading-tight">
|
||||
Warum ich Case Studies zeige? <br />
|
||||
<span className="text-slate-200">
|
||||
Weil Code mehr als Text ist.
|
||||
</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl">
|
||||
In diesen Case Studies geht es nicht nur um bunte Bilder. Es geht
|
||||
um die technischen Entscheidungen, die ein Projekt erfolgreich
|
||||
machen. Schnelle Ladezeiten, SEO-Exzellenz und wartbarer Code sind
|
||||
keine Zufälle, sondern das Ergebnis von präziser Planung.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
</div>
|
||||
{/* Coming Soon */}
|
||||
<Section number="02" title="Kommt bald" borderTop>
|
||||
<Reveal>
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="large"
|
||||
techBorder
|
||||
className="text-center relative overflow-hidden group"
|
||||
>
|
||||
<div className="relative z-10 space-y-6 py-8">
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
<div className="w-2 h-2 rounded-full bg-slate-300 animate-pulse" />
|
||||
<Label className="text-slate-400">In Arbeit</Label>
|
||||
</div>
|
||||
<H3 className="text-3xl text-slate-400">
|
||||
Weitere Case Studies in Kürze.
|
||||
</H3>
|
||||
<BodyText className="text-slate-400 max-w-md mx-auto">
|
||||
Ich dokumentiere laufende Projekte – schauen Sie bald wieder
|
||||
vorbei oder kontaktieren Sie mich direkt.
|
||||
</BodyText>
|
||||
<div className="pt-4">
|
||||
<Button href="/contact" variant="outline">
|
||||
Kontakt aufnehmen
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,42 +1,95 @@
|
||||
import * as React from "react";
|
||||
import { Reveal } from "../../src/components/Reveal";
|
||||
import { PageHeader } from "../../src/components/PageHeader";
|
||||
import { Reveal } from "../../src/components/Reveal";
|
||||
import { Section } from "../../src/components/Section";
|
||||
import { H3, LeadText, Label } from "../../src/components/Typography";
|
||||
import { Card } from "../../src/components/Layout";
|
||||
import { ContactForm } from "../../src/components/ContactForm";
|
||||
import { GradientMesh, AbstractCircuit } from "../../src/components/Effects";
|
||||
|
||||
export default function ContactPage() {
|
||||
return (
|
||||
<div className="flex flex-col gap-12 py-12 md:py-24">
|
||||
<div className="flex flex-col bg-white min-h-screen overflow-hidden relative">
|
||||
<AbstractCircuit />
|
||||
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
Projekt <br />
|
||||
<span className="text-slate-200">konfigurieren.</span>
|
||||
Kontakt<span className="text-slate-200">.</span>
|
||||
</>
|
||||
}
|
||||
description="Nutzen Sie den Konfigurator für eine erste Einschätzung oder schreiben Sie mir direkt eine Email."
|
||||
description="Beschreiben Sie kurz Ihr Vorhaben. Ich melde mich zeitnah bei Ihnen."
|
||||
backLink={{ href: "/", label: "Zurück" }}
|
||||
backgroundSymbol="?"
|
||||
backgroundSymbol="@"
|
||||
/>
|
||||
|
||||
<Section title="Konfigurator" containerVariant="wide" className="!py-12">
|
||||
<ContactForm />
|
||||
</Section>
|
||||
<Section
|
||||
borderTop
|
||||
effects={
|
||||
<>
|
||||
<GradientMesh variant="metallic" className="opacity-70" />
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-24">
|
||||
{/* Form */}
|
||||
<div className="md:col-span-7">
|
||||
<Reveal>
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="large"
|
||||
className="relative overflow-hidden"
|
||||
>
|
||||
<ContactForm />
|
||||
</Card>
|
||||
</Reveal>
|
||||
</div>
|
||||
|
||||
<Section title="Direkt" className="!py-12">
|
||||
<div className="grid grid-cols-1 gap-24">
|
||||
<Reveal delay={0.4}>
|
||||
<div className="space-y-8">
|
||||
<a href="mailto:marc@mintel.me" className="group block space-y-2">
|
||||
<span className="text-xs font-bold uppercase tracking-widest text-slate-300 group-hover:text-slate-900 transition-colors">
|
||||
Email
|
||||
</span>
|
||||
<p className="text-3xl md:text-6xl font-bold text-slate-900 border-b border-slate-100 group-hover:border-slate-900 transition-all duration-500 pb-6 tracking-tighter">
|
||||
marc@mintel.me
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</Reveal>
|
||||
{/* Sidebar */}
|
||||
<div className="md:col-span-5 space-y-8">
|
||||
<Reveal delay={0.2}>
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="normal"
|
||||
techBorder
|
||||
className="group"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<Label className="text-slate-900">Verfügbarkeit</Label>
|
||||
</div>
|
||||
<LeadText className="text-lg text-slate-400">
|
||||
Aktuell nehme ich Projekte für{" "}
|
||||
<span className="text-slate-900 font-bold">Q2 2026</span>{" "}
|
||||
an.
|
||||
</LeadText>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.3}>
|
||||
<Card variant="glass" padding="normal" className="group">
|
||||
<div className="space-y-4">
|
||||
<Label className="text-slate-900">Direkt per E-Mail</Label>
|
||||
<a
|
||||
href="mailto:marc@mintel.me"
|
||||
className="block text-xl md:text-2xl font-bold text-slate-900 hover:text-slate-400 transition-colors duration-500 border-b border-slate-100 hover:border-slate-400 pb-1"
|
||||
>
|
||||
marc@mintel.me
|
||||
</a>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.4}>
|
||||
<div className="p-6 space-y-3 rounded-2xl border border-slate-50 bg-slate-50/30">
|
||||
<Label className="text-slate-400">Antwortzeit</Label>
|
||||
<H3 className="text-2xl text-slate-300">
|
||||
<span className="text-slate-900">< 24h</span> an Werktagen.
|
||||
</H3>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
@apply mb-1;
|
||||
}
|
||||
|
||||
code:not([class*='language-']) {
|
||||
code:not([class*="language-"]) {
|
||||
@apply bg-slate-50 px-1.5 py-0.5 rounded-md font-mono text-[0.9em] text-slate-800 border border-slate-100;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@
|
||||
|
||||
/* Components - Tailwind utility classes */
|
||||
@layer components {
|
||||
|
||||
/* Legacy hooks required by tests */
|
||||
.file-example {
|
||||
@apply w-full;
|
||||
@@ -180,7 +179,8 @@
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
@apply inline-flex items-center justify-center px-6 py-3 border border-slate-200 bg-white text-slate-600 font-sans font-bold text-sm uppercase tracking-widest rounded-full transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] hover:border-slate-400 hover:text-slate-900 hover:bg-slate-50 hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 active:translate-y-0 active:shadow-sm;
|
||||
@apply inline-flex items-center justify-center px-6 py-3 border border-slate-200 bg-white text-slate-600 font-sans font-bold text-sm uppercase tracking-widest rounded-full transition-all duration-500 hover:border-slate-400 hover:text-slate-900 hover:bg-slate-50 hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 active:translate-y-0 active:shadow-sm;
|
||||
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@@ -266,7 +266,9 @@
|
||||
color: #1e293b;
|
||||
border-color: #cbd5e1;
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
box-shadow:
|
||||
0 20px 25px -5px rgb(0 0 0 / 0.1),
|
||||
0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@@ -284,7 +286,6 @@
|
||||
|
||||
/* Print styles */
|
||||
@media print {
|
||||
|
||||
.floating-back-to-top,
|
||||
.reading-progress-bar {
|
||||
display: none !important;
|
||||
@@ -343,27 +344,43 @@
|
||||
}
|
||||
|
||||
.highlighter-yellow {
|
||||
background: linear-gradient(135deg, rgba(255, 235, 59, 0.95) 0%, rgba(255, 213, 79, 0.95) 100%);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(255, 235, 59, 0.95) 0%,
|
||||
rgba(255, 213, 79, 0.95) 100%
|
||||
);
|
||||
color: #3f2f00;
|
||||
}
|
||||
|
||||
.highlighter-pink {
|
||||
background: linear-gradient(135deg, rgba(255, 167, 209, 0.95) 0%, rgba(255, 122, 175, 0.95) 100%);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(255, 167, 209, 0.95) 0%,
|
||||
rgba(255, 122, 175, 0.95) 100%
|
||||
);
|
||||
color: #3f0018;
|
||||
}
|
||||
|
||||
.highlighter-green {
|
||||
background: linear-gradient(135deg, rgba(129, 199, 132, 0.95) 0%, rgba(102, 187, 106, 0.95) 100%);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(129, 199, 132, 0.95) 0%,
|
||||
rgba(102, 187, 106, 0.95) 100%
|
||||
);
|
||||
color: #002f0a;
|
||||
}
|
||||
|
||||
.highlighter-blue {
|
||||
background: linear-gradient(135deg, rgba(226, 232, 240, 0.95) 0%, rgba(203, 213, 225, 0.95) 100%);
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(226, 232, 240, 0.95) 0%,
|
||||
rgba(203, 213, 225, 0.95) 100%
|
||||
);
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.highlighter-tag:hover::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -2px;
|
||||
background: inherit;
|
||||
@@ -385,7 +402,7 @@
|
||||
|
||||
/* Marker Title Styles */
|
||||
.marker-title::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -0.15em;
|
||||
right: -0.15em;
|
||||
@@ -394,22 +411,23 @@
|
||||
border-radius: 0.18em;
|
||||
z-index: -1;
|
||||
|
||||
background:
|
||||
linear-gradient(180deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0) 20%,
|
||||
rgba(253, 230, 138, 0.70) 20%,
|
||||
rgba(253, 230, 138, 0.70) 100%);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0) 20%,
|
||||
rgba(253, 230, 138, 0.7) 20%,
|
||||
rgba(253, 230, 138, 0.7) 100%
|
||||
);
|
||||
|
||||
transform-origin: left center;
|
||||
transform:
|
||||
rotate(calc((var(--marker-seed, 0) - 3) * 0.45deg)) skewX(calc((var(--marker-seed, 0) - 3) * -0.25deg));
|
||||
transform: rotate(calc((var(--marker-seed, 0) - 3) * 0.45deg))
|
||||
skewX(calc((var(--marker-seed, 0) - 3) * -0.25deg));
|
||||
|
||||
filter: saturate(1.05);
|
||||
}
|
||||
|
||||
.marker-title::after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -0.18em;
|
||||
right: -0.05em;
|
||||
@@ -418,27 +436,28 @@
|
||||
border-radius: 0.18em;
|
||||
z-index: -1;
|
||||
|
||||
background:
|
||||
linear-gradient(90deg,
|
||||
rgba(253, 230, 138, 0.00) 0%,
|
||||
rgba(253, 230, 138, 0.60) 8%,
|
||||
rgba(253, 230, 138, 0.55) 60%,
|
||||
rgba(253, 230, 138, 0.35) 100%);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(253, 230, 138, 0) 0%,
|
||||
rgba(253, 230, 138, 0.6) 8%,
|
||||
rgba(253, 230, 138, 0.55) 60%,
|
||||
rgba(253, 230, 138, 0.35) 100%
|
||||
);
|
||||
|
||||
opacity: 0.75;
|
||||
mix-blend-mode: multiply;
|
||||
transform:
|
||||
rotate(calc((var(--marker-seed, 0) - 3) * 0.45deg)) translateY(0.02em);
|
||||
transform: rotate(calc((var(--marker-seed, 0) - 3) * 0.45deg))
|
||||
translateY(0.02em);
|
||||
|
||||
mask-image:
|
||||
linear-gradient(180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 100%);
|
||||
mask-image: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 100%
|
||||
);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
|
||||
.post-link:hover .marker-title::before,
|
||||
.post-link:hover .marker-title::after {
|
||||
filter: saturate(1.08) contrast(1.02);
|
||||
@@ -480,7 +499,7 @@
|
||||
.mermaid-container .edgeLabel,
|
||||
.mermaid-container .node text,
|
||||
.mermaid-container tspan {
|
||||
font-family: 'Inter', sans-serif !important;
|
||||
font-family: "Inter", sans-serif !important;
|
||||
fill: #334155 !important;
|
||||
color: #334155 !important;
|
||||
stroke: none !important;
|
||||
@@ -532,7 +551,9 @@
|
||||
}
|
||||
|
||||
.embed-wrapper:hover {
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgb(0 0 0 / 0.1),
|
||||
0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
border-color: #cbd5e1;
|
||||
}
|
||||
|
||||
@@ -602,20 +623,22 @@
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.copy-btn[data-copied='true'] {
|
||||
.copy-btn[data-copied="true"] {
|
||||
color: #065f46;
|
||||
background: rgba(16, 185, 129, 0.10);
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border-color: rgba(16, 185, 129, 0.35);
|
||||
}
|
||||
|
||||
/* Prism.js syntax highlighting - light, low-noise */
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'],
|
||||
pre:has(code[class*='language-']) {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"],
|
||||
pre:has(code[class*="language-"]) {
|
||||
color: #0f172a;
|
||||
background: transparent;
|
||||
text-shadow: none;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
||||
font-family:
|
||||
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.65;
|
||||
direction: ltr;
|
||||
@@ -689,4 +712,269 @@ pre:has(code[class*='language-']) {
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #db2777;
|
||||
}
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════
|
||||
TECH AESTHETIC – Animation Keyframes
|
||||
═══════════════════════════════════════════════ */
|
||||
|
||||
/* Gradient Mesh Blob Animations */
|
||||
@keyframes gradient-blob-1 {
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: translate(30px, -20px) scale(1.05);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(-15px, 25px) scale(0.95);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate(20px, 15px) scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient-blob-2 {
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
33% {
|
||||
transform: translate(-25px, 15px) scale(1.03);
|
||||
}
|
||||
|
||||
66% {
|
||||
transform: translate(20px, -20px) scale(0.97);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient-blob-3 {
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
20% {
|
||||
transform: translate(15px, 10px) scale(1.06);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translate(-10px, 20px) scale(0.98);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translate(25px, -15px) scale(1.02);
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: translate(-20px, -10px) scale(0.96);
|
||||
}
|
||||
}
|
||||
|
||||
/* Binary Stream Scroll */
|
||||
@keyframes binary-scroll {
|
||||
0% {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Circuit Pulse (used for node glow effects) */
|
||||
@keyframes circuit-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
box-shadow: 0 0 0 0 rgba(148, 163, 184, 0);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
box-shadow: 0 0 12px 2px rgba(148, 163, 184, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data Packet Flow */
|
||||
@keyframes data-packet-flow {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100vw);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tech Border Glow */
|
||||
@keyframes border-trace {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 200% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Section Fade-In Glow */
|
||||
@keyframes section-glow {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.08;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tailwind-compatible animation classes */
|
||||
.animate-gradient-blob-1 {
|
||||
animation: gradient-blob-1 20s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-gradient-blob-2 {
|
||||
animation: gradient-blob-2 25s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-gradient-blob-3 {
|
||||
animation: gradient-blob-3 30s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-circuit-pulse {
|
||||
animation: circuit-pulse 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-border-trace {
|
||||
animation: border-trace 4s linear infinite;
|
||||
}
|
||||
|
||||
/* Glassmorphism Utilities */
|
||||
.glass {
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border: 1px solid rgba(226, 232, 240, 0.5);
|
||||
}
|
||||
|
||||
.glass-subtle {
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border: 1px solid rgba(241, 245, 249, 0.8);
|
||||
}
|
||||
|
||||
.glass-dark {
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
background: rgba(15, 23, 42, 0.8);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* Tech Border – animated gradient trace */
|
||||
.tech-border {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tech-border::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent 0%,
|
||||
rgba(148, 163, 184, 0.3) 25%,
|
||||
rgba(191, 206, 228, 0.2) 50%,
|
||||
rgba(148, 163, 184, 0.3) 75%,
|
||||
transparent 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: border-trace 4s linear infinite;
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Noise texture overlay */
|
||||
.noise-overlay::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0.02;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════
|
||||
ABSTRACT CIRCUIT – Trace Pulse Animations
|
||||
═══════════════════════════════════════════════ */
|
||||
|
||||
@keyframes tracePulse1 {
|
||||
0% {
|
||||
stroke-dashoffset: 1280;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tracePulse2 {
|
||||
0% {
|
||||
stroke-dashoffset: 650;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tracePulse3 {
|
||||
0% {
|
||||
stroke-dashoffset: 1280;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tracePulse4 {
|
||||
0% {
|
||||
stroke-dashoffset: 440;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes junctionGlow {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ComparisonRow,
|
||||
ConceptAutomation,
|
||||
ConceptCode,
|
||||
ConceptCommunication,
|
||||
ConceptPrice,
|
||||
ConceptPrototyping,
|
||||
ConceptSystem,
|
||||
ConceptWebsite,
|
||||
DifferenceIllustration,
|
||||
HeroArchitecture,
|
||||
HeroMainIllustration,
|
||||
} from "../src/components/Landing";
|
||||
import { Reveal } from "../src/components/Reveal";
|
||||
import { Marker } from "../src/components/Marker";
|
||||
import { Section } from "../src/components/Section";
|
||||
import {
|
||||
H1,
|
||||
@@ -22,172 +18,114 @@ import {
|
||||
MonoLabel,
|
||||
Label,
|
||||
} from "../src/components/Typography";
|
||||
import { BackgroundGrid, Card, Container } from "../src/components/Layout";
|
||||
import { Card, Container } from "../src/components/Layout";
|
||||
import { Button } from "../src/components/Button";
|
||||
import { GradientMesh, CodeSnippet } from "../src/components/Effects";
|
||||
import { IconList, IconListItem } from "../src/components/IconList";
|
||||
import { HeroSection } from "../src/components/HeroSection";
|
||||
import { GlitchText } from "../src/components/GlitchText";
|
||||
import { Marker } from "../src/components/Marker";
|
||||
|
||||
export default function LandingPage() {
|
||||
return (
|
||||
<div className="flex flex-col bg-white overflow-hidden relative">
|
||||
<BackgroundGrid />
|
||||
{/* Dark Hero */}
|
||||
<HeroSection />
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative min-h-[80vh] flex items-center pt-24 md:pt-0">
|
||||
<Container variant="narrow" className="relative">
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 md:gap-24 items-center">
|
||||
{/* Left Column */}
|
||||
<div className="md:col-span-6 relative z-10">
|
||||
<Reveal>
|
||||
<div className="space-y-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-8 h-px bg-slate-900"></div>
|
||||
<MonoLabel className="text-slate-900">
|
||||
Digital Architect
|
||||
</MonoLabel>
|
||||
</div>
|
||||
<H1 className="text-6xl md:text-8xl">
|
||||
Websites <br />
|
||||
<span className="text-slate-200">ohne Overhead.</span>
|
||||
</H1>
|
||||
<div className="pt-4">
|
||||
<Button href="#contact" variant="outline">
|
||||
Projekt anfragen
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
{/* Rest of page on white */}
|
||||
|
||||
{/* Right Column */}
|
||||
<div className="md:col-span-6 relative h-[400px] md:h-[600px] flex items-center justify-center">
|
||||
<div className="absolute inset-0 -z-10 opacity-[0.03] pointer-events-none flex items-center justify-center scale-150">
|
||||
<HeroArchitecture className="w-full h-full" />
|
||||
</div>
|
||||
|
||||
<Reveal
|
||||
delay={0.2}
|
||||
className="w-full h-full flex items-center justify-center"
|
||||
>
|
||||
<div className="relative w-full h-full flex items-center justify-center pointer-events-none">
|
||||
<HeroMainIllustration className="w-full h-full scale-110 md:scale-125 origin-center" />
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
{/* Section 02: The Promise */}
|
||||
<Section number="02" title="Das Versprechen" borderTop>
|
||||
{/* Section 02: The Promise – Streamlined */}
|
||||
<Section
|
||||
number="02"
|
||||
title="Das Versprechen"
|
||||
borderTop
|
||||
effects={<GradientMesh variant="metallic" className="opacity-70" />}
|
||||
>
|
||||
<div className="space-y-16 relative">
|
||||
<Reveal>
|
||||
<H3 className="max-w-3xl">
|
||||
Schluss mit aufgeblähten Prozessen. <br />
|
||||
<span className="text-slate-200">
|
||||
Ich reduziere auf das Wesentliche.
|
||||
Kein Agentur-Zirkus. <br />
|
||||
<span className="text-slate-400">
|
||||
Nur{" "}
|
||||
<Marker delay={0.3} color="rgba(148,163,184,0.15)">
|
||||
Ergebnisse.
|
||||
</Marker>
|
||||
</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-16 relative z-10">
|
||||
<Reveal delay={0.1}>
|
||||
<div className="space-y-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<Label className="text-slate-900">Was ich biete</Label>
|
||||
</div>
|
||||
<IconList className="space-y-6">
|
||||
{[
|
||||
{
|
||||
text: "Direkte Kommunikation ohne Umwege",
|
||||
icon: <ConceptCommunication className="w-12 h-12" />,
|
||||
},
|
||||
{
|
||||
text: "Schnelle Prototypen statt langer Konzepte",
|
||||
icon: <ConceptPrototyping className="w-12 h-12" />,
|
||||
},
|
||||
{
|
||||
text: "Sauberer Code, der auch morgen noch läuft",
|
||||
icon: <ConceptCode className="w-12 h-12" />,
|
||||
},
|
||||
{
|
||||
text: "Fixpreise für volle Budgetsicherheit",
|
||||
icon: <ConceptPrice className="w-12 h-12" />,
|
||||
},
|
||||
].map((item, i) => (
|
||||
<IconListItem
|
||||
key={i}
|
||||
icon={item.icon}
|
||||
iconContainerClassName="mt-0"
|
||||
>
|
||||
<LeadText className="text-xl">{item.text}</LeadText>
|
||||
</IconListItem>
|
||||
))}
|
||||
</IconList>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.2}>
|
||||
<div className="space-y-8 opacity-40 hover:opacity-100 transition-opacity duration-700">
|
||||
<div className="flex items-center gap-4">
|
||||
<Label>Was ich nicht mache</Label>
|
||||
</div>
|
||||
<IconList className="space-y-4">
|
||||
{[
|
||||
"Endlose Workshops ohne Ergebnis",
|
||||
"PowerPoint-Schlachten",
|
||||
"Outsourcing an Billig-Anbieter",
|
||||
"Wartungsverträge mit versteckten Kosten",
|
||||
].map((item, i) => (
|
||||
<IconListItem
|
||||
key={i}
|
||||
bullet
|
||||
className="line-through decoration-slate-200"
|
||||
iconClassName="opacity-20"
|
||||
>
|
||||
<LeadText className="text-slate-400 text-lg">
|
||||
{item}
|
||||
</LeadText>
|
||||
</IconListItem>
|
||||
))}
|
||||
</IconList>
|
||||
</div>
|
||||
</Reveal>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10">
|
||||
{[
|
||||
{
|
||||
icon: <ConceptCommunication className="w-8 h-8" />,
|
||||
title: "Direkte Kommunikation",
|
||||
text: "Sie sprechen mit dem Entwickler. Keine Stille Post, keine Umwege.",
|
||||
},
|
||||
{
|
||||
icon: <ConceptPrototyping className="w-8 h-8" />,
|
||||
title: "Schnelle Umsetzung",
|
||||
text: "Sichtbare Fortschritte in Tagen. Prototypen statt Konzeptpapiere.",
|
||||
},
|
||||
{
|
||||
icon: <ConceptCode className="w-8 h-8" />,
|
||||
title: "Sauberer Code",
|
||||
text: "Maßgeschneiderte Architektur. Kein Baukasten, kein Plugin-Chaos.",
|
||||
},
|
||||
{
|
||||
icon: <ConceptPrice className="w-8 h-8" />,
|
||||
title: "Klare Fixpreise",
|
||||
text: "Volle Budgetsicherheit. Keine versteckten Kosten.",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<Reveal key={i} delay={0.1 + i * 0.1}>
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="normal"
|
||||
techBorder
|
||||
className="group"
|
||||
>
|
||||
<div className="space-y-4 relative z-10">
|
||||
<div className="w-12 h-12 rounded-xl bg-slate-50 border border-slate-100 flex items-center justify-center group-hover:scale-110 transition-transform duration-500">
|
||||
{item.icon}
|
||||
</div>
|
||||
<Label className="text-slate-900">{item.title}</Label>
|
||||
<BodyText className="text-slate-500">{item.text}</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 03: The Difference */}
|
||||
{/* Section 03: The Difference – Visual Comparison */}
|
||||
<Section number="03" title="Der Unterschied" variant="white" borderTop>
|
||||
<div className="space-y-16 relative">
|
||||
<div className="flex flex-col md:flex-row gap-12 items-center">
|
||||
<Reveal className="flex-1">
|
||||
<LeadText className="text-2xl md:text-3xl leading-tight max-w-2xl relative z-10 text-slate-400">
|
||||
Ich arbeite nicht gegen die Zeit, sondern{" "}
|
||||
<span className="text-slate-900">für das Ergebnis.</span> Mein
|
||||
Fokus liegt auf der Umsetzung, nicht auf der Verwaltung von
|
||||
Prozessen.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2} className="w-full md:w-72 shrink-0">
|
||||
<div className="p-6 bg-slate-50 rounded-2xl border border-slate-100">
|
||||
<DifferenceIllustration className="w-full h-auto grayscale opacity-50" />
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
<Reveal>
|
||||
<H3 className="max-w-3xl">
|
||||
Ich arbeite für das Ergebnis, <br />
|
||||
<span className="text-slate-400">
|
||||
nicht gegen die{" "}
|
||||
<Marker delay={0.4} color="rgba(148,163,184,0.1)">
|
||||
Uhr.
|
||||
</Marker>
|
||||
</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 gap-8 relative z-20">
|
||||
<ComparisonRow
|
||||
negativeLabel="Klassisch"
|
||||
negativeText="Lange Planungsphasen und abstrakte Konzepte."
|
||||
negativeText="Wochen in Planung, bevor eine einzige Zeile Code geschrieben wird."
|
||||
positiveLabel="Mein Weg"
|
||||
positiveText="Schnelle Prototypen. Sie sehen Fortschritt in Tagen."
|
||||
positiveText="Schnelle Prototypen. Ergebnisse in Tagen, nicht Monaten."
|
||||
delay={0.1}
|
||||
/>
|
||||
<ComparisonRow
|
||||
negativeLabel="Klassisch"
|
||||
negativeText="Komplexe Preisstrukturen und versteckte Kosten."
|
||||
negativeText="Unvorhersehbare Kosten durch Stundenabrechnungen."
|
||||
positiveLabel="Mein Weg"
|
||||
positiveText="Klare Fixpreise. Volle Kostentransparenz."
|
||||
positiveText="Fixpreise. Sie wissen von Anfang an, was es kostet."
|
||||
reverse
|
||||
delay={0.2}
|
||||
/>
|
||||
@@ -196,43 +134,40 @@ export default function LandingPage() {
|
||||
</Section>
|
||||
|
||||
{/* Section 04: Target Group */}
|
||||
<Section number="04" title="Zielgruppe" borderTop>
|
||||
<Section number="04" title="Für wen" borderTop>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 relative z-10">
|
||||
<Reveal>
|
||||
<Card variant="dark" padding="normal" className="group">
|
||||
<Card variant="glass" padding="normal" techBorder className="group">
|
||||
<div className="space-y-6 relative overflow-hidden">
|
||||
<div className="w-16 h-16 bg-white/5 rounded-xl flex items-center justify-center border border-white/10">
|
||||
<div className="w-16 h-16 bg-slate-50 border border-slate-100 rounded-xl flex items-center justify-center">
|
||||
<ConceptPrice className="w-8 h-8" />
|
||||
</div>
|
||||
<H3 className="text-white text-3xl">
|
||||
<H3 className="text-3xl">
|
||||
Unternehmer & <br />
|
||||
Geschäftsführer
|
||||
</H3>
|
||||
<LeadText className="text-slate-400 text-lg">
|
||||
"Ich brauche eine Lösung, die funktioniert. Ich habe keine
|
||||
Zeit für technische Details."
|
||||
Sie wollen eine Website, die funktioniert – ohne sich mit
|
||||
Technik beschäftigen zu müssen.
|
||||
</LeadText>
|
||||
</div>
|
||||
<div className="pt-8 border-t border-white/5 mt-8">
|
||||
<Label className="group-hover:text-white transition-colors">
|
||||
<div className="pt-8 border-t border-slate-50 mt-8">
|
||||
<Label className="group-hover:text-slate-900 transition-colors">
|
||||
Perfekt für Sie
|
||||
</Label>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<Card variant="white" padding="normal" className="group">
|
||||
<Card variant="glass" padding="normal" techBorder className="group">
|
||||
<div className="space-y-6 relative overflow-hidden">
|
||||
<div className="w-16 h-16 bg-slate-50 border border-slate-100 rounded-xl flex items-center justify-center">
|
||||
<ConceptWebsite className="w-8 h-8" />
|
||||
</div>
|
||||
<H3 className="text-3xl">
|
||||
Marketing & <br />
|
||||
Vertrieb
|
||||
</H3>
|
||||
<LeadText className="text-slate-400 text-lg">
|
||||
"Wir brauchen Landingpages und Tools, um unsere Ziele zu
|
||||
erreichen. Schnell und zuverlässig."
|
||||
Sie brauchen Landingpages und Tools, die Ergebnisse liefern.
|
||||
Schnell und zuverlässig.
|
||||
</LeadText>
|
||||
</div>
|
||||
<div className="pt-8 border-t border-slate-50 mt-8">
|
||||
@@ -245,65 +180,93 @@ export default function LandingPage() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Section 05: Services */}
|
||||
{/* Section 05: Leistungen — Interactive Service Rows */}
|
||||
<Section number="05" title="Leistungen" variant="gray" borderTop>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative z-20">
|
||||
<Reveal delay={0.1}>
|
||||
<Card variant="white" padding="small" className="group">
|
||||
<div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
|
||||
<ConceptWebsite className="w-8 h-8" />
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<H3 className="text-2xl">Websites</H3>
|
||||
<BodyText>
|
||||
High-Performance Websites. Maßgeschneiderte Architektur statt
|
||||
Baukasten.
|
||||
</BodyText>
|
||||
<div className="pt-4">
|
||||
<a
|
||||
href="/websites"
|
||||
className="text-[10px] font-bold uppercase tracking-[0.4em] text-slate-900 border-b border-slate-100 pb-1 hover:border-slate-900 transition-all"
|
||||
>
|
||||
Details
|
||||
</a>
|
||||
<div className="space-y-0 relative z-20">
|
||||
{[
|
||||
{
|
||||
num: "01",
|
||||
binary: "00000001",
|
||||
title: "Websites",
|
||||
text: "High-Performance Websites mit maßgeschneiderter Architektur. Von der Konzeption bis zum Go-Live — individuell, schnell, messbar.",
|
||||
tags: ["Next.js", "React", "TypeScript", "Performance"],
|
||||
href: "/websites",
|
||||
},
|
||||
{
|
||||
num: "02",
|
||||
binary: "00000010",
|
||||
title: "Systeme",
|
||||
text: "Web-Applikationen und interne Tools, wenn Standard-Software nicht reicht. Dashboards, Portale, Automatisierungen.",
|
||||
tags: ["Full-Stack", "APIs", "Datenbanken", "Auth"],
|
||||
href: "/contact",
|
||||
},
|
||||
{
|
||||
num: "03",
|
||||
binary: "00000011",
|
||||
title: "Automatisierung",
|
||||
text: "Verbindung von Tools, automatische Prozesse, Daten-Synchronisation. Weniger manuelle Arbeit, mehr Effizienz.",
|
||||
tags: ["CI/CD", "Workflows", "Integrationen", "Monitoring"],
|
||||
href: "/contact",
|
||||
},
|
||||
].map((service, i) => (
|
||||
<Reveal key={i} delay={0.1 + i * 0.15}>
|
||||
<div className="group py-12 md:py-16 border-b border-slate-100 last:border-b-0 cursor-pointer transition-all duration-500">
|
||||
<div className="flex flex-col md:flex-row md:items-start gap-8 md:gap-16">
|
||||
{/* Number + Binary */}
|
||||
<div className="md:w-32 shrink-0">
|
||||
<span className="text-5xl md:text-6xl font-black text-slate-100 group-hover:text-slate-200 transition-colors duration-500 tracking-tighter block leading-none">
|
||||
{service.num}
|
||||
</span>
|
||||
<span
|
||||
className="text-[8px] font-mono text-slate-200 tracking-[0.3em] mt-2 block select-none group-hover:text-blue-300 transition-colors duration-700"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{service.binary}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 space-y-6">
|
||||
<H3 className="text-3xl md:text-4xl group-hover:translate-x-2 transition-transform duration-500">
|
||||
<GlitchText
|
||||
trigger="inView"
|
||||
delay={0.2 + i * 0.15}
|
||||
duration={0.6}
|
||||
>
|
||||
{service.title}
|
||||
</GlitchText>
|
||||
</H3>
|
||||
<BodyText className="text-slate-400 max-w-xl group-hover:text-slate-500 transition-colors duration-500">
|
||||
{service.text}
|
||||
</BodyText>
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{service.tags.map((tag, j) => (
|
||||
<span
|
||||
key={j}
|
||||
className="px-3 py-1 text-[9px] font-mono uppercase tracking-widest text-slate-400 border border-slate-100 rounded-full bg-white/50 group-hover:border-slate-200 group-hover:text-slate-500 transition-all duration-500"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Arrow */}
|
||||
<div className="md:self-center shrink-0">
|
||||
<Button
|
||||
href={service.href}
|
||||
variant="ghost"
|
||||
size="normal"
|
||||
showArrow
|
||||
>
|
||||
Details
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.3}>
|
||||
<Card
|
||||
variant="white"
|
||||
padding="small"
|
||||
className="group mt-8 md:mt-0"
|
||||
>
|
||||
<div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
|
||||
<ConceptSystem className="w-8 h-8" />
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<H3 className="text-2xl">Systeme</H3>
|
||||
<BodyText>
|
||||
Web-Applikationen, Portale, interne Tools. Wenn Standard an
|
||||
Grenzen stößt.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
|
||||
<Reveal delay={0.5}>
|
||||
<Card variant="white" padding="small" className="group">
|
||||
<div className="w-16 h-16 bg-slate-50 rounded-xl flex items-center justify-center mb-8 group-hover:scale-110 transition-transform duration-500">
|
||||
<ConceptAutomation className="w-8 h-8" />
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<H3 className="text-2xl">Automatisierung</H3>
|
||||
<BodyText>
|
||||
Verbindung von Tools, automatische Prozesse,
|
||||
Daten-Synchronisation.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
</Reveal>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
@@ -314,26 +277,26 @@ export default function LandingPage() {
|
||||
<div className="space-y-16">
|
||||
<H1 className="text-6xl md:text-8xl">
|
||||
Lassen Sie uns <br />
|
||||
<span className="text-slate-200">starten.</span>
|
||||
<span className="text-slate-400">starten.</span>
|
||||
</H1>
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-16 items-start relative z-10">
|
||||
<div className="space-y-8 flex-1">
|
||||
<LeadText className="text-2xl md:text-3xl text-slate-400">
|
||||
Schreiben Sie mir kurz, worum es geht. Ich melde mich{" "}
|
||||
<span className="text-slate-900">zeitnah</span> bei Ihnen.
|
||||
Beschreiben Sie kurz Ihr Vorhaben. Ich melde mich{" "}
|
||||
<span className="text-slate-900 border-b-2 border-slate-900/10">
|
||||
<Marker color="rgba(255,235,59,0.5)">zeitnah</Marker>
|
||||
</span>{" "}
|
||||
bei Ihnen.
|
||||
</LeadText>
|
||||
<div className="pt-4">
|
||||
<a
|
||||
href="/contact"
|
||||
className="inline-block text-3xl md:text-5xl font-bold text-slate-900 hover:text-slate-400 transition-all duration-700 border-b-2 border-slate-900 hover:border-slate-200 pb-2"
|
||||
>
|
||||
<Button href="/contact" size="large">
|
||||
Projekt anfragen
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-72 space-y-6 p-6 bg-slate-50 rounded-2xl border border-slate-100">
|
||||
<div className="w-full md:w-72 space-y-6 p-6 glass rounded-2xl">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<Label className="text-slate-900">Verfügbarkeit</Label>
|
||||
|
||||
@@ -10,98 +10,129 @@ import {
|
||||
LayerSeparation,
|
||||
DirectService,
|
||||
TaskDone,
|
||||
ConceptAutomation,
|
||||
ConceptCode,
|
||||
ConceptCommunication,
|
||||
ConceptPrototyping,
|
||||
ConceptSystem,
|
||||
ConceptTarget,
|
||||
} from "../../src/components/Landing";
|
||||
import { Check } from "lucide-react";
|
||||
import {
|
||||
H2,
|
||||
H3,
|
||||
H4,
|
||||
LeadText,
|
||||
BodyText,
|
||||
Label,
|
||||
} from "../../src/components/Typography";
|
||||
import { BackgroundGrid, Card } from "../../src/components/Layout";
|
||||
import { MotionButton } from "../../src/components/Button";
|
||||
import { Card } from "../../src/components/Layout";
|
||||
import { Button } from "../../src/components/Button";
|
||||
import { IconList, IconListItem } from "../../src/components/IconList";
|
||||
import {
|
||||
GradientMesh,
|
||||
CodeSnippet,
|
||||
AbstractCircuit,
|
||||
} from "../../src/components/Effects";
|
||||
import { Marker } from "../../src/components/Marker";
|
||||
|
||||
export default function WebsitesPage() {
|
||||
return (
|
||||
<div className="flex flex-col bg-white overflow-hidden relative">
|
||||
<BackgroundGrid />
|
||||
<AbstractCircuit />
|
||||
|
||||
<PageHeader
|
||||
title={
|
||||
<>
|
||||
Websites, die <br />
|
||||
<span className="text-slate-200">einfach funktionieren.</span>
|
||||
<span className="text-slate-400">
|
||||
<Marker color="rgba(255,235,59,0.5)">
|
||||
einfach funktionieren.
|
||||
</Marker>
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
description="Keine Baukästen, keine Plugins, kein Overhead. Nur sauberer Code und maximale Performance."
|
||||
description="Kein Baukasten. Kein Plugin-Chaos. Maßgeschneiderte Architektur für maximale Performance."
|
||||
backLink={{ href: "/", label: "Zurück" }}
|
||||
backgroundSymbol="W"
|
||||
/>
|
||||
|
||||
{/* Intro / Problem */}
|
||||
{/* 01: Architektur – WIE ich baue */}
|
||||
<Section
|
||||
number="01"
|
||||
title="Der Ansatz"
|
||||
title="Architektur"
|
||||
borderTop
|
||||
illustration={<SystemArchitecture className="w-24 h-24" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Ich baue Websites wie Systeme – <br />
|
||||
<span className="text-slate-200">nicht wie Broschüren.</span>
|
||||
Systeme, nicht Broschüren. <br />
|
||||
<span className="text-slate-400">
|
||||
Jede Website ist Ingenieursarbeit.
|
||||
</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
|
||||
Eine Website ist kein Flyer. Sie ist ein{" "}
|
||||
<span className="text-slate-900">Werkzeug</span>, das jeden Tag
|
||||
arbeitet. Deshalb baue ich sie stabil, schnell und wartungsfrei.
|
||||
Ich entwickle Websites von Grund auf – mit modernen Frameworks,
|
||||
eigener Infrastruktur und einem Deployment-Prozess, der{" "}
|
||||
<span className="text-slate-900">
|
||||
<Marker delay={0.2} color="rgba(148,163,184,0.1)">
|
||||
automatisiert und reproduzierbar
|
||||
</Marker>
|
||||
</span>{" "}
|
||||
ist.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
|
||||
{/* Tech Stack Visual */}
|
||||
<Reveal delay={0.4}>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 pt-8">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
{[
|
||||
{ label: "Stabil", icon: ConceptSystem },
|
||||
{ label: "Schnell", icon: ConceptAutomation },
|
||||
{ label: "Wartungsfrei", icon: ConceptCode },
|
||||
{ label: "Sicher", icon: ConceptTarget },
|
||||
{ label: "Next.js", sub: "Framework" },
|
||||
{ label: "TypeScript", sub: "Sprache" },
|
||||
{ label: "Docker", sub: "Infrastruktur" },
|
||||
{ label: "Directus", sub: "CMS" },
|
||||
].map((item, i) => (
|
||||
<div key={i} className="flex flex-col gap-3 group">
|
||||
<div className="w-12 h-12 rounded-xl bg-slate-50 flex items-center justify-center border border-slate-100 group-hover:scale-110 transition-transform duration-500">
|
||||
<item.icon className="w-6 h-6" />
|
||||
<Card
|
||||
key={i}
|
||||
variant="glass"
|
||||
padding="small"
|
||||
techBorder
|
||||
className="group text-center"
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<Label className="text-slate-900 text-sm">
|
||||
{item.label}
|
||||
</Label>
|
||||
<span className="block text-[9px] font-mono text-slate-300 uppercase tracking-widest">
|
||||
{item.sub}
|
||||
</span>
|
||||
</div>
|
||||
<Label className="text-slate-900">{item.label}</Label>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* Decorative Code Snippet */}
|
||||
<Reveal delay={0.6}>
|
||||
<div className="max-w-md opacity-70">
|
||||
<CodeSnippet variant="code" />
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Speed */}
|
||||
{/* 02: Performance */}
|
||||
<Section
|
||||
number="02"
|
||||
title="Performance"
|
||||
borderTop
|
||||
variant="gray"
|
||||
illustration={<SpeedPerformance className="w-24 h-24" />}
|
||||
effects={<GradientMesh variant="metallic" className="opacity-60" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Geschwindigkeit ist <br />
|
||||
<span className="text-slate-200">
|
||||
kein Extra. Sie ist Standard.
|
||||
<span className="text-slate-400">
|
||||
<Marker delay={0.3} color="rgba(148,163,184,0.15)">
|
||||
kein Extra. Sie ist Standard.
|
||||
</Marker>
|
||||
</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
@@ -109,19 +140,18 @@ export default function WebsitesPage() {
|
||||
<div className="md:col-span-7 space-y-8">
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl text-slate-400">
|
||||
Viele Websites sind langsam, weil sie zusammengeklickt sind.
|
||||
Meine sind schnell, weil sie{" "}
|
||||
<span className="text-slate-900">von Grund auf</span>{" "}
|
||||
entwickelt wurden.
|
||||
Jede Seite wird vorab gerendert und über ein CDN ausgeliefert.
|
||||
Das Ergebnis: Ladezeiten unter einer Sekunde. Messbar.{" "}
|
||||
<span className="text-slate-900">Reproduzierbar.</span>
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<Reveal delay={0.4}>
|
||||
<IconList className="space-y-4">
|
||||
{[
|
||||
"Seiten laden ohne Verzögerung",
|
||||
"Optimiert für Suchmaschinen (SEO)",
|
||||
"Bessere Nutzererfahrung",
|
||||
"Höhere Conversion-Rates",
|
||||
"Server-Side Rendering für sofortige Inhalte",
|
||||
"Automatische Bild-Optimierung (WebP, AVIF)",
|
||||
"Lighthouse-Score 90+ als Mindeststandard",
|
||||
"Core Web Vitals im grünen Bereich",
|
||||
].map((item, i) => (
|
||||
<IconListItem key={i} bullet>
|
||||
<LeadText className="text-lg md:text-xl">{item}</LeadText>
|
||||
@@ -133,14 +163,18 @@ export default function WebsitesPage() {
|
||||
<div className="md:col-span-5">
|
||||
<Reveal delay={0.6}>
|
||||
<Card
|
||||
variant="white"
|
||||
variant="glass"
|
||||
padding="normal"
|
||||
techBorder
|
||||
className="text-center group"
|
||||
>
|
||||
<div className="text-7xl md:text-8xl font-bold text-slate-900 tracking-tighter group-hover:scale-110 transition-transform duration-700">
|
||||
90+
|
||||
</div>
|
||||
<Label className="mt-4">Pagespeed Score</Label>
|
||||
<Label className="mt-4">Lighthouse Score</Label>
|
||||
<span className="block text-[9px] font-mono text-slate-300 mt-2 tracking-wider">
|
||||
PERFORMANCE · ACCESSIBILITY · SEO
|
||||
</span>
|
||||
</Card>
|
||||
</Reveal>
|
||||
</div>
|
||||
@@ -148,10 +182,10 @@ export default function WebsitesPage() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* No Maintenance */}
|
||||
{/* 03: Code-Qualität */}
|
||||
<Section
|
||||
number="03"
|
||||
title="Technik"
|
||||
title="Code"
|
||||
borderTop
|
||||
illustration={<SolidFoundation className="w-24 h-24" />}
|
||||
>
|
||||
@@ -159,91 +193,107 @@ export default function WebsitesPage() {
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Keine Plugins. <br />
|
||||
<span className="text-slate-200">Keine Abhängigkeiten.</span>
|
||||
<span className="text-slate-400">Keine Abhängigkeiten.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
|
||||
Ich nutze keine Baukästen, die sich selbst zerstören. Ihre Website
|
||||
besteht aus <span className="text-slate-900">sauberem Code</span>,
|
||||
der Ihnen gehört.
|
||||
Ihre Website besteht aus{" "}
|
||||
<span className="text-slate-900">Ihrem Code</span>. Kein
|
||||
WordPress, kein Wix, keine Blackbox. Alles versioniert, alles
|
||||
nachvollziehbar.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<Reveal delay={0.4}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 pt-8">
|
||||
<Card variant="white" padding="normal" className="group">
|
||||
<div className="space-y-4">
|
||||
<Label className="text-slate-900 mb-2">Code Qualität</Label>
|
||||
<H4 className="text-2xl">Langlebigkeit</H4>
|
||||
<BodyText>
|
||||
Modernste Web-Technologien für maximale Performance und
|
||||
Wartbarkeit.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
<Card variant="white" padding="normal" className="group">
|
||||
<div className="space-y-4">
|
||||
<Label className="text-slate-900 mb-2">Sicherheit</Label>
|
||||
<H4 className="text-2xl">Resilienz</H4>
|
||||
<BodyText>
|
||||
Minimale Angriffsfläche durch Verzicht auf unnötige
|
||||
Drittanbieter-Software.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* Git Branch Visualization */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<Reveal delay={0.4}>
|
||||
<CodeSnippet variant="git" />
|
||||
</Reveal>
|
||||
<Reveal delay={0.5}>
|
||||
<div className="space-y-6">
|
||||
<Card variant="glass" padding="normal" className="group">
|
||||
<div className="space-y-2">
|
||||
<Label className="text-slate-900">Versionskontrolle</Label>
|
||||
<BodyText>
|
||||
Jede Änderung ist dokumentiert. Rollbacks in Sekunden.
|
||||
Kein „wer hat das kaputt gemacht?".
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
<Card variant="glass" padding="normal" className="group">
|
||||
<div className="space-y-2">
|
||||
<Label className="text-slate-900">
|
||||
Automatisches Deployment
|
||||
</Label>
|
||||
<BodyText>
|
||||
Code wird geprüft, getestet und automatisch live
|
||||
geschaltet. Ohne manuellen Eingriff.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Content/Tech Separation */}
|
||||
{/* 04: Content-System */}
|
||||
<Section
|
||||
number="04"
|
||||
title="Inhalte"
|
||||
borderTop
|
||||
variant="gray"
|
||||
illustration={<LayerSeparation className="w-24 h-24" />}
|
||||
effects={<GradientMesh variant="subtle" className="opacity-60" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Inhalte pflegen <br />
|
||||
<span className="text-slate-200">ohne Angst.</span>
|
||||
<span className="text-slate-400">ohne Angst.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<div className="grid grid-cols-1 md:grid-cols-12 gap-12 items-start">
|
||||
<div className="md:col-span-7">
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl md:text-2xl text-slate-400">
|
||||
Sie können Texte und Bilder selbst anpassen, ohne das Design
|
||||
oder die Technik zu gefährden. Ein{" "}
|
||||
<span className="text-slate-900">intuitives System</span>{" "}
|
||||
sorgt dafür, dass alles an seinem Platz bleibt.
|
||||
Technik und Inhalt sind{" "}
|
||||
<span className="text-slate-900">
|
||||
<Marker color="rgba(255,235,59,0.5)">
|
||||
strikt getrennt
|
||||
</Marker>
|
||||
</span>
|
||||
. Sie bearbeiten Texte und Bilder in einem intuitiven System –
|
||||
das Design bleibt geschützt.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
</div>
|
||||
<div className="md:col-span-5">
|
||||
<Reveal delay={0.4}>
|
||||
<Card variant="white" padding="normal" className="space-y-8">
|
||||
<div className="space-y-4">
|
||||
<Label>Ihre Freiheit</Label>
|
||||
<div className="flex items-center gap-3 text-xl font-bold text-slate-900">
|
||||
<div className="w-8 h-8 rounded-full bg-slate-900 flex items-center justify-center">
|
||||
<Check className="w-3 h-3 text-white" />
|
||||
</div>
|
||||
Inhalte flexibel verwalten
|
||||
<Card
|
||||
variant="glass"
|
||||
padding="normal"
|
||||
techBorder
|
||||
className="space-y-6"
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-2 h-2 rounded-full bg-green-500"></div>
|
||||
<Label className="text-slate-900">Sie dürfen</Label>
|
||||
</div>
|
||||
<BodyText className="font-medium">
|
||||
Texte, Bilder und Inhalte frei bearbeiten.
|
||||
</BodyText>
|
||||
</div>
|
||||
<div className="space-y-4 opacity-30">
|
||||
<Label>Mein Schutz</Label>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">
|
||||
Design-Chaos
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-xl font-bold text-slate-900 line-through">
|
||||
Technische Fehler
|
||||
</div>
|
||||
<div className="space-y-3 opacity-40">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-2 h-2 rounded-full bg-slate-300"></div>
|
||||
<Label>Geschützt</Label>
|
||||
</div>
|
||||
<BodyText className="line-through">
|
||||
Design, Layout, Code-Struktur.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</Reveal>
|
||||
@@ -252,90 +302,34 @@ export default function WebsitesPage() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Simple Changes */}
|
||||
{/* 05: Was Sie bekommen */}
|
||||
<Section
|
||||
number="05"
|
||||
title="Service"
|
||||
borderTop
|
||||
illustration={<DirectService className="w-24 h-24" />}
|
||||
>
|
||||
<div className="space-y-12">
|
||||
<Reveal>
|
||||
<H3 className="text-3xl md:text-5xl leading-tight max-w-3xl">
|
||||
Änderungen sind <br />
|
||||
<span className="text-slate-200">Teil des Konzepts.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
<Reveal delay={0.2}>
|
||||
<LeadText className="text-xl md:text-2xl max-w-2xl text-slate-400">
|
||||
Ihr Business entwickelt sich weiter, Ihre Website auch. <br />
|
||||
Keine komplizierten Prozesse, sondern{" "}
|
||||
<span className="text-slate-900">direkte Umsetzung</span> Ihrer
|
||||
Ideen.
|
||||
</LeadText>
|
||||
</Reveal>
|
||||
<Reveal delay={0.4}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 pt-8">
|
||||
<Card
|
||||
variant="white"
|
||||
padding="normal"
|
||||
className="group hover:border-slate-900"
|
||||
>
|
||||
<ConceptCommunication className="w-12 h-12 mb-8 group-hover:scale-110 transition-all duration-700" />
|
||||
<div className="space-y-2">
|
||||
<H4 className="text-2xl">Direkter Draht</H4>
|
||||
<BodyText>
|
||||
Sie sprechen direkt mit dem Entwickler. Keine Stille Post.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
<Card
|
||||
variant="white"
|
||||
padding="normal"
|
||||
className="group hover:border-slate-900"
|
||||
>
|
||||
<ConceptPrototyping className="w-12 h-12 mb-8 group-hover:scale-110 transition-all duration-700" />
|
||||
<div className="space-y-2">
|
||||
<H4 className="text-2xl">Agile Anpassung</H4>
|
||||
<BodyText>
|
||||
Schnelle Iterationen statt langer Wartezeiten.
|
||||
</BodyText>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Result */}
|
||||
<Section
|
||||
number="06"
|
||||
title="Ergebnis"
|
||||
borderTop
|
||||
variant="gray"
|
||||
illustration={<TaskDone className="w-24 h-24" />}
|
||||
>
|
||||
<div className="space-y-16">
|
||||
<Reveal>
|
||||
<H3 className="text-4xl md:text-6xl tracking-tighter">
|
||||
Eine Website, die <br />
|
||||
<span className="text-slate-200">einfach läuft.</span>
|
||||
Was Sie konkret <br />
|
||||
<span className="text-slate-400">bekommen.</span>
|
||||
</H3>
|
||||
</Reveal>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
|
||||
{[
|
||||
{
|
||||
title: "Kein Overhead",
|
||||
desc: "Fokus auf das, was Ihre Kunden wirklich brauchen.",
|
||||
title: "Ihr Code",
|
||||
desc: "Vollständiger Quellcode, versioniert auf GitHub. Kein Vendor Lock-in.",
|
||||
},
|
||||
{
|
||||
title: "Volle Kontrolle",
|
||||
desc: "Der Code gehört Ihnen, ohne Vendor Lock-in.",
|
||||
title: "Ihre Infrastruktur",
|
||||
desc: "Docker-Container, CI/CD-Pipeline, automatisches Deployment.",
|
||||
},
|
||||
{
|
||||
title: "Echte Performance",
|
||||
desc: "Messbare Geschwindigkeit für bessere Ergebnisse.",
|
||||
title: "Ihr CMS",
|
||||
desc: "Eigenes Content-Management-System. Volle Kontrolle über Ihre Inhalte.",
|
||||
},
|
||||
].map((item, i) => (
|
||||
<Reveal key={i} delay={i * 0.1}>
|
||||
@@ -353,12 +347,12 @@ export default function WebsitesPage() {
|
||||
<Reveal delay={0.4}>
|
||||
<div className="pt-16 border-t border-slate-200 flex flex-col md:flex-row justify-between items-start md:items-center gap-8">
|
||||
<div className="space-y-2">
|
||||
<Label>Bereit für mehr?</Label>
|
||||
<Label>Bereit?</Label>
|
||||
<LeadText className="text-2xl">
|
||||
Lassen Sie uns über Ihr nächstes Projekt sprechen.
|
||||
Lassen Sie uns über Ihr Projekt sprechen.
|
||||
</LeadText>
|
||||
</div>
|
||||
<MotionButton href="/contact">Projekt anfragen</MotionButton>
|
||||
<Button href="/contact">Projekt anfragen</Button>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user