This commit is contained in:
2026-01-29 19:06:45 +01:00
parent 2b56f317f7
commit 1cc583c976
7 changed files with 675 additions and 176 deletions

191
app/blog/page.tsx Normal file
View File

@@ -0,0 +1,191 @@
'use client';
import React, { 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';
export default function BlogPage() {
const [searchQuery, setSearchQuery] = useState('');
const [filteredPosts, setFilteredPosts] = useState(blogPosts);
// Sort posts by date
const allPosts = [...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 || [])));
useEffect(() => {
const query = searchQuery.toLowerCase().trim();
if (query.startsWith('#')) {
const tag = query.slice(1);
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);
}));
}
}, [searchQuery]);
const filterByTag = (tag: string) => {
setSearchQuery(`#${tag}`);
};
return (
<div className="container">
{/* Clean Hero Section */}
<section className="pt-10 pb-8 md:pt-12 md:pb-10 relative overflow-hidden">
{/* Animated Background */}
<div className="absolute inset-0 bg-gradient-to-br from-white via-slate-50/30 to-blue-50/20 animate-gradient-shift"></div>
{/* Morphing Blob */}
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
<div className="w-48 h-48 bg-gradient-to-br from-blue-200/15 via-purple-200/10 to-indigo-200/15 animate-morph"></div>
</div>
{/* Animated Drawing Paths */}
<svg className="absolute inset-0 w-full h-full pointer-events-none" viewBox="0 0 100 100">
<path d="M10,50 Q50,10 90,50 T90,90" stroke="rgba(59,130,246,0.1)" strokeWidth="0.5" fill="none" className="animate-draw"></path>
<path d="M10,70 Q50,30 90,70" stroke="rgba(147,51,234,0.1)" strokeWidth="0.5" fill="none" className="animate-draw-delay"></path>
<path d="M20,20 Q50,80 80,20" stroke="rgba(16,185,129,0.1)" strokeWidth="0.5" fill="none" className="animate-draw-reverse"></path>
</svg>
{/* Floating Shapes */}
<div className="absolute top-10 left-10 w-20 h-20 bg-blue-100/20 rounded-full animate-float-1"></div>
<div className="absolute top-20 right-20 w-16 h-16 bg-indigo-100/20 rotate-45 animate-float-2"></div>
<div className="absolute bottom-20 left-1/4 w-12 h-12 bg-purple-100/20 rounded-full animate-float-3"></div>
<div className="absolute bottom-10 right-1/3 w-24 h-24 bg-cyan-100/20 animate-float-4"></div>
<div className="max-w-3xl mx-auto px-6 relative z-10">
<div className="text-center animate-fade-in">
<h1 className="text-3xl md:text-4xl font-serif font-light text-slate-900 tracking-tight mb-3">
Marc Mintel
</h1>
<p className="text-base md:text-lg text-slate-600 leading-relaxed font-serif italic">
"A public notebook of things I figured out, mistakes I made, and tools I tested."
</p>
<div className="flex items-center justify-center gap-3 text-[13px] text-slate-500 font-sans mt-3">
<span className="inline-flex items-center gap-1">
<svg className="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2a8 8 0 100 16 8 8 0 000-16zm0 12a4 4 0 110-8 4 4 0 010 8z"/></svg>
Vulkaneifel, Germany
</span>
<span aria-hidden="true"></span>
<span>Digital problem solver</span>
</div>
</div>
</div>
</section>
{/* Search */}
<section className="mb-8 mt-8">
<div id="search-container">
<SearchBar value={searchQuery} onChange={setSearchQuery} />
</div>
</section>
{/* Topics */}
{allTags.length > 0 && (
<section className="mb-8">
<h2 className="text-lg font-semibold text-slate-800 mb-4">Topics</h2>
<div className="tag-cloud flex flex-wrap gap-2">
{allTags.map((tag, index) => (
<button
key={tag}
onClick={() => filterByTag(tag)}
className="inline-block"
>
<Tag tag={tag} index={index} />
</button>
))}
</div>
</section>
)}
{/* All Posts */}
<section>
<div id="posts-container" className="not-prose grid grid-cols-1 md:grid-cols-2 gap-3 md:gap-4">
{filteredPosts.length === 0 ? (
<div className="empty-state col-span-full">
<p>No posts found matching your criteria.</p>
</div>
) : (
filteredPosts.map(post => (
<MediumCard key={post.slug} post={post} />
))
)}
</div>
</section>
<style jsx global>{`
@keyframes gradient-shift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.animate-gradient-shift {
background-size: 200% 200%;
animation: gradient-shift 20s ease infinite;
}
@keyframes morph {
0%, 100% { border-radius: 50%; transform: scale(1) rotate(0deg); }
25% { border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; transform: scale(1.1) rotate(90deg); }
50% { border-radius: 20% 80% 20% 80% / 80% 20% 80% 20%; transform: scale(0.9) rotate(180deg); }
75% { border-radius: 70% 30% 50% 50% / 50% 70% 30% 50%; transform: scale(1.05) rotate(270deg); }
}
.animate-morph {
animation: morph 25s ease-in-out infinite;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
.animate-draw {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate;
}
.animate-draw-delay {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate 4s;
}
.animate-draw-reverse {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate-reverse 2s;
}
@keyframes float-1 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-20px) rotate(180deg); }
}
.animate-float-1 { animation: float-1 15s ease-in-out infinite; }
@keyframes float-2 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-15px) rotate(90deg); }
}
.animate-float-2 { animation: float-2 18s ease-in-out infinite; }
@keyframes float-3 {
0%, 100% { transform: translateY(0px) scale(1); }
50% { transform: translateY(-10px) scale(1.1); }
}
.animate-float-3 { animation: float-3 12s ease-in-out infinite; }
@keyframes float-4 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-25px) rotate(-90deg); }
}
.animate-float-4 { animation: float-4 20s ease-in-out infinite; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in { animation: fadeIn 0.6s ease-out both; }
`}</style>
</div>
);
}

View File

@@ -2,6 +2,7 @@ import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { Footer } from '../src/components/Footer';
import { Header } from '../src/components/Header';
import { InteractiveElements } from '../src/components/InteractiveElements';
import { Analytics } from '../src/components/Analytics';
@@ -28,7 +29,8 @@ export default function RootLayout({
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
</head>
<body className="min-h-screen bg-white">
<main className="container">
<Header />
<main>
{children}
</main>
<Footer />

View File

@@ -1,191 +1,301 @@
'use client';
import React, { 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';
export default function HomePage() {
const [searchQuery, setSearchQuery] = useState('');
const [filteredPosts, setFilteredPosts] = useState(blogPosts);
// Sort posts by date
const allPosts = [...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 || [])));
useEffect(() => {
const query = searchQuery.toLowerCase().trim();
if (query.startsWith('#')) {
const tag = query.slice(1);
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);
}));
}
}, [searchQuery]);
const filterByTag = (tag: string) => {
setSearchQuery(`#${tag}`);
};
import React from 'react';
import Link from 'next/link';
import { Check, ArrowRight, MessageSquare } from 'lucide-react';
export default function LandingPage() {
return (
<>
{/* Clean Hero Section */}
<section className="pt-10 pb-8 md:pt-12 md:pb-10 relative overflow-hidden">
{/* Animated Background */}
<div className="absolute inset-0 bg-gradient-to-br from-white via-slate-50/30 to-blue-50/20 animate-gradient-shift"></div>
{/* Morphing Blob */}
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
<div className="w-48 h-48 bg-gradient-to-br from-blue-200/15 via-purple-200/10 to-indigo-200/15 animate-morph"></div>
<div className="flex flex-col gap-32 py-20 md:py-32">
{/* Hero Section */}
<section className="narrow-container animate-fade-in">
<h1 className="text-4xl md:text-6xl font-bold text-slate-900 tracking-tight mb-10 leading-[1.1]">
Digitale Systeme für Unternehmen, die keinen Overhead wollen
</h1>
<div className="space-y-4 text-xl md:text-2xl text-slate-500 font-serif italic leading-relaxed">
<p>Agenturen sind zu langsam.</p>
<p>CMS will keiner pflegen.</p>
<p>Digitale Themen bleiben liegen.</p>
</div>
<p className="mt-12 text-2xl font-semibold text-slate-900">
Ich mache das anders.
</p>
</section>
{/* Animated Drawing Paths */}
<svg className="absolute inset-0 w-full h-full pointer-events-none" viewBox="0 0 100 100">
<path d="M10,50 Q50,10 90,50 T90,90" stroke="rgba(59,130,246,0.1)" strokeWidth="0.5" fill="none" className="animate-draw"></path>
<path d="M10,70 Q50,30 90,70" stroke="rgba(147,51,234,0.1)" strokeWidth="0.5" fill="none" className="animate-draw-delay"></path>
<path d="M20,20 Q50,80 80,20" stroke="rgba(16,185,129,0.1)" strokeWidth="0.5" fill="none" className="animate-draw-reverse"></path>
</svg>
{/* Was ich mache */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Was ich mache</h2>
</div>
<div className="md:col-span-8">
<div className="prose prose-slate font-serif text-xl leading-relaxed text-slate-700">
<p>
Ich setze digitale Systeme für Unternehmen um direkt, sauber und ohne Agentur-Zirkus.
</p>
<p className="font-sans font-bold text-slate-900 mt-8 text-2xl">
Websites, Funktionen, Systeme, interne Tools.
</p>
<p className="mt-4">
Keine Workshops. Keine Tickets. Kein Tech-Blabla.
</p>
<p className="mt-10 text-slate-900">
Sie erklären mir, was Sie brauchen. <br />
Ich sorge dafür, dass es funktioniert.
</p>
</div>
</div>
</div>
</section>
{/* Floating Shapes */}
<div className="absolute top-10 left-10 w-20 h-20 bg-blue-100/20 rounded-full animate-float-1"></div>
<div className="absolute top-20 right-20 w-16 h-16 bg-indigo-100/20 rotate-45 animate-float-2"></div>
<div className="absolute bottom-20 left-1/4 w-12 h-12 bg-purple-100/20 rounded-full animate-float-3"></div>
<div className="absolute bottom-10 right-1/3 w-24 h-24 bg-cyan-100/20 animate-float-4"></div>
{/* Für wen das ist */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Für wen das ist</h2>
</div>
<div className="md:col-span-8">
<p className="text-xl text-slate-900 font-bold mb-8">Für Unternehmen, die:</p>
<ul className="space-y-4 mb-12">
{[
'regelmäßig Änderungen an Website oder Systemen brauchen',
'keine Lust auf Agenturen haben',
'kein CMS anfassen wollen',
'keine Tickets schreiben möchten',
'keinen Entwickler einstellen wollen',
'und wollen, dass Dinge einfach erledigt werden',
].map((item, i) => (
<li key={i} className="flex items-start gap-4">
<Check className="w-5 h-5 text-slate-900 shrink-0 mt-1" />
<span className="text-lg text-slate-600 font-serif">{item}</span>
</li>
))}
</ul>
<div className="p-8 bg-slate-50 rounded-sm border-l-4 border-slate-900">
<p className="text-xl font-serif italic text-slate-700 leading-relaxed">
Wenn bei Ihnen öfter der Satz fällt: <br />
<span className="font-bold not-italic text-slate-900">Das müsste man mal machen </span>
</p>
<p className="mt-4 text-slate-500">
aber es passiert nie dann sind Sie hier richtig.
</p>
</div>
</div>
</div>
</section>
<div className="max-w-3xl mx-auto px-6 relative z-10">
<div className="text-center animate-fade-in">
<h1 className="text-3xl md:text-4xl font-serif font-light text-slate-900 tracking-tight mb-3">
Marc Mintel
</h1>
<p className="text-base md:text-lg text-slate-600 leading-relaxed font-serif italic">
"A public notebook of things I figured out, mistakes I made, and tools I tested."
{/* Das eigentliche Problem */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Das Problem</h2>
</div>
<div className="md:col-span-8">
<div className="prose prose-slate font-serif text-xl leading-relaxed text-slate-700">
<p>
Digitale Arbeit scheitert nicht an Technik. <br />
Sie scheitert an <span className="text-slate-900 font-bold underline decoration-slate-200 underline-offset-4">Zuständigkeit</span>.
</p>
<div className="space-y-4 mt-10 font-sans text-base not-italic text-slate-500">
<p className="pb-4 border-b border-slate-100">Agenturen wollen Projekte.</p>
<p className="pb-4 border-b border-slate-100">Mitarbeiter haben Wichtigeres zu tun.</p>
<p className="pb-4 border-b border-slate-100">IT ist ausgelastet.</p>
<p>Kleine Aufgaben sind zu klein für große Angebote.</p>
</div>
<p className="mt-10 font-bold text-slate-900 text-2xl">Also bleibt alles liegen.</p>
</div>
</div>
</div>
</section>
{/* Warum keine Agentur */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Warum keine Agentur</h2>
</div>
<div className="md:col-span-8">
<p className="text-xl font-serif text-slate-600 mb-16 leading-relaxed">
Ich habe über 15 Jahre in Agenturen gearbeitet. Ich kenne das Spiel. Und ich weiß, warum es nervt.
</p>
<div className="flex items-center justify-center gap-3 text-[13px] text-slate-500 font-sans mt-3">
<span className="inline-flex items-center gap-1">
<svg className="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2a8 8 0 100 16 8 8 0 000-16zm0 12a4 4 0 110-8 4 4 0 010 8z"/></svg>
Vulkaneifel, Germany
</span>
<span aria-hidden="true"></span>
<span>Digital problem solver</span>
<div className="space-y-20">
<div className="group">
<h3 className="text-2xl font-bold text-slate-900 mb-6">Agenturen machen einfache Dinge kompliziert</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-start">
<div className="space-y-2 text-slate-400 text-sm font-mono">
<p>Ein Button ändern?</p>
<p> Konzeptcall</p>
<p> Abstimmung</p>
<p> internes Meeting</p>
<p> Angebot</p>
<p> Warten</p>
<p> Rechnung</p>
</div>
<div className="pt-4 border-t-2 border-slate-900">
<p className="font-bold text-slate-900 mb-2 uppercase tracking-wider text-xs">Mein Ansatz</p>
<p className="text-2xl font-bold text-slate-900">Ich mache es einfach fertig.</p>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-16">
<div>
<h4 className="font-bold text-slate-900 mb-3 text-lg">Prozesse statt Ergebnisse</h4>
<p className="text-slate-500 font-serif leading-relaxed">
Workshops, Slides, Roadmaps. Klingt nach Fortschritt, ist oft nur Beschäftigungstherapie. Bei mir zählt nur Umsetzung.
</p>
</div>
<div>
<h4 className="font-bold text-slate-900 mb-3 text-lg">Stundenabrechnung</h4>
<p className="text-slate-500 font-serif leading-relaxed">
Das dauert nur kurz Überraschung auf der Rechnung. Ich arbeite mit Fixpreisen. Sie wissen vorher, was es kostet.
</p>
</div>
<div>
<h4 className="font-bold text-slate-900 mb-3 text-lg">Aufgaben-Ping-Pong</h4>
<p className="text-slate-500 font-serif leading-relaxed">
Heute Projektmanager, morgen Entwickler, übermorgen niemand. Bei mir: Eine Person. Eine Verantwortung.
</p>
</div>
<div>
<h4 className="font-bold text-slate-900 mb-3 text-lg">Verschwinden nach dem Projekt</h4>
<p className="text-slate-500 font-serif leading-relaxed">
Kleine Änderung? Neues Angebot. Dringend? Warteschleife. Ich bleibe, solange Sie Dinge brauchen.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Search */}
<section className="mb-8 mt-8">
<div id="search-container">
<SearchBar value={searchQuery} onChange={setSearchQuery} />
</div>
</section>
{/* Topics */}
{allTags.length > 0 && (
<section className="mb-8">
<h2 className="text-lg font-semibold text-slate-800 mb-4">Topics</h2>
<div className="tag-cloud flex flex-wrap gap-2">
{allTags.map((tag, index) => (
<button
key={tag}
onClick={() => filterByTag(tag)}
className="inline-block"
>
<Tag tag={tag} index={index} />
</button>
))}
{/* Wie ich arbeite */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Arbeitsweise</h2>
</div>
</section>
)}
{/* All Posts */}
<section>
<div id="posts-container" className="not-prose grid grid-cols-1 md:grid-cols-2 gap-3 md:gap-4">
{filteredPosts.length === 0 ? (
<div className="empty-state col-span-full">
<p>No posts found matching your criteria.</p>
<div className="md:col-span-8">
<p className="text-2xl font-bold text-slate-900 mb-8">
Ich baue zuerst. Dann reden wir drüber.
</p>
<div className="prose prose-slate font-serif text-xl leading-relaxed text-slate-700">
<p>
Sie erklären mir Ihre Vorstellung. Ich setze den ersten echten Stand um.
</p>
<div className="flex flex-wrap gap-x-8 gap-y-2 my-10 not-prose border-y border-slate-100 py-6">
<span className="text-sm font-bold text-slate-400 uppercase tracking-widest">Keine Slides</span>
<span className="text-sm font-bold text-slate-400 uppercase tracking-widest">Kein Konzept-PDF</span>
<span className="text-sm font-bold text-slate-400 uppercase tracking-widest">Kein Ratespiel</span>
</div>
<p>
Dann arbeiten wir direkt am Ergebnis, bis es passt. Ohne jedes Mal ein neues Angebot. Ohne Scope-Diskussionen. Ohne Theater.
</p>
</div>
) : (
filteredPosts.map(post => (
<MediumCard key={post.slug} post={post} />
))
)}
</div>
</div>
</section>
<style jsx global>{`
@keyframes gradient-shift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
.animate-gradient-shift {
background-size: 200% 200%;
animation: gradient-shift 20s ease infinite;
}
@keyframes morph {
0%, 100% { border-radius: 50%; transform: scale(1) rotate(0deg); }
25% { border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; transform: scale(1.1) rotate(90deg); }
50% { border-radius: 20% 80% 20% 80% / 80% 20% 80% 20%; transform: scale(0.9) rotate(180deg); }
75% { border-radius: 70% 30% 50% 50% / 50% 70% 30% 50%; transform: scale(1.05) rotate(270deg); }
}
.animate-morph {
animation: morph 25s ease-in-out infinite;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
.animate-draw {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate;
}
.animate-draw-delay {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate 4s;
}
.animate-draw-reverse {
stroke-dasharray: 200;
stroke-dashoffset: 200;
animation: draw 8s ease-in-out infinite alternate-reverse 2s;
}
@keyframes float-1 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-20px) rotate(180deg); }
}
.animate-float-1 { animation: float-1 15s ease-in-out infinite; }
@keyframes float-2 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-15px) rotate(90deg); }
}
.animate-float-2 { animation: float-2 18s ease-in-out infinite; }
@keyframes float-3 {
0%, 100% { transform: translateY(0px) scale(1); }
50% { transform: translateY(-10px) scale(1.1); }
}
.animate-float-3 { animation: float-3 12s ease-in-out infinite; }
@keyframes float-4 {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-25px) rotate(-90deg); }
}
.animate-float-4 { animation: float-4 20s ease-in-out infinite; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in { animation: fadeIn 0.6s ease-out both; }
`}</style>
</>
{/* Was ich konkret umsetze */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Leistungen</h2>
</div>
<div className="md:col-span-8">
<div className="space-y-20">
<div>
<h3 className="text-2xl font-bold text-slate-900 mb-6">Websites</h3>
<ul className="space-y-3 text-slate-600 font-serif text-lg">
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> neue Websites (klarer Standard)</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> bestehende Websites übernehmen</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Seiten ändern oder ergänzen</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Performance & SEO</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Hosting & Betrieb (inklusive)</li>
</ul>
<div className="mt-8">
<Link href="/websites" className="inline-flex items-center gap-2 text-slate-900 font-bold border-b-2 border-slate-900 pb-1 hover:text-slate-600 hover:border-slate-300 transition-all">
Details zu Websites & Preisen <ArrowRight className="w-4 h-4" />
</Link>
</div>
</div>
<div>
<h3 className="text-2xl font-bold text-slate-900 mb-6">Funktionen & Systeme</h3>
<ul className="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-3 text-slate-600 font-serif text-lg">
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Produktbereiche</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Blogs, News, Jobs</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Formulare</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Suche & Filter</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> PDF-Generatoren</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> API-Ausgaben & Daten-Sync</li>
</ul>
</div>
<div>
<h3 className="text-2xl font-bold text-slate-900 mb-6">Interne Tools</h3>
<ul className="space-y-3 text-slate-600 font-serif text-lg">
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> kleine Inhouse-Tools</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Excel ersetzen</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Automatisierung</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-300" /> Importe & Exporte</li>
</ul>
</div>
</div>
</div>
</div>
</section>
{/* Warum Kunden bleiben */}
<section className="narrow-container">
<div className="grid grid-cols-1 md:grid-cols-12 gap-8">
<div className="md:col-span-4">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mt-0">Vorteile</h2>
</div>
<div className="md:col-span-8">
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-10">
{[
{ label: 'Schnelligkeit', desc: 'Dinge passieren schnell' },
{ label: 'Erledigt', desc: 'Aufgaben verschwinden wirklich' },
{ label: 'Kein Erklären', desc: 'Ich verstehe, was Sie brauchen' },
{ label: 'Kein Nachfassen', desc: 'Ich melde mich, wenn es fertig ist' },
{ label: 'Kein Stress', desc: 'Kein Projektstress' },
{ label: 'Ruhe', desc: 'Kein Agentur-Zirkus' },
].map((item, i) => (
<div key={i} className="border-l border-slate-100 pl-6">
<div className="font-bold text-slate-900 mb-1 text-lg">{item.label}</div>
<div className="text-slate-500 font-serif">{item.desc}</div>
</div>
))}
</div>
<p className="mt-20 text-4xl font-serif italic text-slate-900">
Kurz: Ruhe.
</p>
</div>
</div>
</section>
{/* CTA */}
<section className="narrow-container">
<div className="bg-slate-900 text-white p-12 md:p-20 rounded-sm text-center">
<h2 className="text-3xl md:text-5xl font-bold mb-8 tracking-tight">Interesse?</h2>
<p className="text-xl md:text-2xl mb-12 text-slate-400 font-serif leading-relaxed">
Schreiben Sie mir einfach, was Sie brauchen. <br />
Ich sage Ihnen ehrlich, ob ich es mache und was es kostet.
</p>
<a
href="mailto:marc@mintel.me"
className="inline-flex items-center gap-3 bg-white text-slate-900 px-10 py-5 rounded-sm font-bold text-lg hover:bg-slate-100 transition-colors"
>
<MessageSquare className="w-5 h-5" />
Projekt anfragen
</a>
<div className="mt-12">
<Link href="/blog" className="text-slate-500 hover:text-white text-sm font-mono uppercase tracking-widest transition-colors">
Zum Blog
</Link>
</div>
</div>
</section>
</div>
);
}

View File

@@ -32,8 +32,8 @@ export default async function TagPage({ params }: { params: Promise<{ tag: strin
</div>
<div className="mt-8 pt-6 border-t border-slate-200">
<Link href="/" className="text-blue-600 hover:text-blue-800 inline-flex items-center">
Back to home
<Link href="/blog" className="text-blue-600 hover:text-blue-800 inline-flex items-center">
Back to blog
</Link>
</div>
</div>

164
app/websites/page.tsx Normal file
View File

@@ -0,0 +1,164 @@
import React from 'react';
import { Check, Info, ArrowLeft, Mail } from 'lucide-react';
import Link from 'next/link';
export default function WebsitesPage() {
return (
<div className="flex flex-col gap-24 py-20 md:py-32">
{/* Header */}
<section className="narrow-container">
<Link href="/" className="inline-flex items-center gap-2 text-slate-400 hover:text-slate-900 mb-12 transition-colors font-mono text-xs uppercase tracking-widest">
<ArrowLeft className="w-3 h-3" /> Zurück
</Link>
<h1 className="text-4xl md:text-6xl font-bold text-slate-900 tracking-tight mb-8 leading-tight">
Websites & Preise
</h1>
<p className="text-xl md:text-2xl text-slate-500 font-serif italic leading-relaxed">
Ich baue digitale Systeme mit klaren Preisen und Ergebnissen keine Stunden, keine Überraschungen.
</p>
</section>
{/* 1. Website - Fixpreis */}
<section className="narrow-container">
<div className="border-t-4 border-slate-900 pt-12">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mb-8">1. Website Fixpreis</h2>
<div className="flex flex-col md:flex-row md:items-baseline gap-4 mb-12">
<div className="text-6xl font-bold text-slate-900">6.000 </div>
<div className="text-slate-400 font-serif italic text-xl">einmalige Basis</div>
</div>
<div className="space-y-10">
<p className="text-xl text-slate-700 font-serif leading-relaxed">
Die Grundlage für jede Website:
</p>
<ul className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-4">
{[
'Projekt-Setup & Infrastruktur',
'Hosting-Bereitstellung',
'Grundstruktur & Design-Vorlage',
'technisches SEO-Basics',
'Analytics (mit Mail-Report)',
'Livegang',
].map((item, i) => (
<li key={i} className="flex items-center gap-3 border-b border-slate-50 pb-2">
<Check className="w-4 h-4 text-slate-900 shrink-0" />
<span className="text-slate-600 font-serif">{item}</span>
</li>
))}
</ul>
<div className="pt-8 flex items-start gap-3 text-sm text-slate-400 italic font-serif">
<Info className="w-4 h-4 shrink-0 mt-0.5 text-slate-300" />
<p>Enthält keine Seiten, Inhalte oder Funktionen. Diese werden nach Bedarf ergänzt.</p>
</div>
</div>
</div>
</section>
{/* 2. Entwicklung (Produktion) */}
<section className="narrow-container">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mb-12">2. Entwicklung (Produktion)</h2>
<div className="space-y-16">
{/* Seite */}
<div className="group">
<div className="flex justify-between items-baseline mb-4 border-b border-slate-100 pb-4">
<h3 className="text-2xl font-bold text-slate-900">Seite</h3>
<div className="text-2xl font-bold text-slate-900">800 </div>
</div>
<p className="text-slate-500 font-serif text-lg leading-relaxed max-w-xl">
Individuell gestaltete Seite mit Layout, Struktur, Textaufteilung, responsivem Design.
</p>
</div>
{/* Feature */}
<div className="group">
<div className="flex justify-between items-baseline mb-4 border-b border-slate-100 pb-4">
<h3 className="text-2xl font-bold text-slate-900">Feature (System)</h3>
<div className="text-2xl font-bold text-slate-900">2.000 </div>
</div>
<p className="text-slate-500 font-serif text-lg leading-relaxed max-w-xl mb-6">
Ein in sich geschlossenes System mit Datenstruktur, Darstellung und Pflegefähigkeit.
</p>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{['Blog', 'News', 'Jobs', 'Referenzen', 'Events', 'Produktbereich'].map(tag => (
<span key={tag} className="text-xs font-mono uppercase tracking-widest text-slate-400">{tag}</span>
))}
</div>
</div>
{/* Funktion */}
<div className="group">
<div className="flex justify-between items-baseline mb-4 border-b border-slate-100 pb-4">
<h3 className="text-2xl font-bold text-slate-900">Funktion (Logik)</h3>
<div className="text-2xl font-bold text-slate-900">1.000 </div>
</div>
<p className="text-slate-500 font-serif text-lg leading-relaxed max-w-xl mb-8">
Funktionen liefern Logik und Interaktion.
</p>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 text-sm font-mono uppercase tracking-wider text-slate-400">
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> Kontaktformular</div>
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> Suche & Filter</div>
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> PDF-Export</div>
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> API-Anbindungen</div>
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> Mailversand</div>
<div className="flex items-center gap-2"><div className="w-1 h-1 bg-slate-200 rounded-full" /> Automatisierung</div>
</div>
</div>
</div>
</section>
{/* 3. Design & Interaktion */}
<section className="narrow-container">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mb-12">3. Design & Interaktion (Extras)</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<div>
<h3 className="font-bold text-slate-900 mb-2 text-lg">Visuelle Inszenierung</h3>
<div className="text-slate-900 font-bold mb-4 text-xl">2.000 <span className="text-sm text-slate-400 font-normal">/ Abschnitt</span></div>
<p className="text-slate-500 font-serif leading-relaxed">
Erweiterte Gestaltung: Hero-Story, visuelle Abläufe, Scroll-Effekte, speziell inszenierte Sektionen.
</p>
</div>
<div>
<h3 className="font-bold text-slate-900 mb-2 text-lg">Komplexe Interaktion</h3>
<div className="text-slate-900 font-bold mb-4 text-xl">1.500 <span className="text-sm text-slate-400 font-normal">/ Interaktion</span></div>
<p className="text-slate-500 font-serif leading-relaxed">
Dargestellte, interaktive UI-Erlebnisse: Konfiguratoren, Live-Previews, mehrstufige Auswahlprozesse.
</p>
</div>
</div>
</section>
{/* 5. Betrieb & Wartung */}
<section className="narrow-container">
<div className="bg-slate-50 p-12 rounded-sm border border-slate-100">
<h2 className="text-sm font-bold uppercase tracking-widest text-slate-400 mb-8">5. Betrieb & Wartung (Pflicht)</h2>
<div className="flex items-baseline gap-2 mb-10">
<div className="text-5xl font-bold text-slate-900">120 </div>
<div className="text-slate-400 font-serif italic text-xl">/ Monat</div>
</div>
<ul className="grid grid-cols-1 md:grid-cols-2 gap-4 text-slate-600 font-serif">
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-900" /> Webhosting & Verfügbarkeit</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-900" /> Sicherheitsupdates & Backups</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-900" /> Analytics inkl. Reports</li>
<li className="flex items-center gap-3"><Check className="w-4 h-4 text-slate-900" /> Medien-Speicher (20 GB)</li>
</ul>
</div>
</section>
{/* CTA */}
<section className="narrow-container text-center py-20 border-t border-slate-100">
<h2 className="text-3xl md:text-5xl font-bold text-slate-900 mb-8 tracking-tight">Bereit für ein Projekt?</h2>
<p className="text-xl text-slate-500 font-serif mb-12 leading-relaxed">
Schreiben Sie mir einfach, was Sie vorhaben. <br />
Ich erstelle Ihnen ein passendes Angebot.
</p>
<a
href="mailto:marc@mintel.me"
className="inline-flex items-center gap-3 bg-slate-900 text-white px-10 py-5 rounded-sm font-bold text-lg hover:bg-slate-800 transition-colors"
>
<Mail className="w-5 h-5" />
Anfrage senden
</a>
</section>
</div>
);
}

View File

@@ -44,7 +44,7 @@ export const BlogPostClient: React.FC<BlogPostClientProps> = ({ readingTime, tit
}, 100);
setTimeout(() => {
router.push('/?from=post');
router.push('/blog?from=post');
}, 500);
};

32
src/components/Header.tsx Normal file
View File

@@ -0,0 +1,32 @@
import React from 'react';
import Link from 'next/link';
export const Header: React.FC = () => {
return (
<header className="bg-white/80 backdrop-blur-md sticky top-0 z-50">
<div className="max-w-4xl mx-auto px-6 py-8 flex items-center justify-between">
<Link href="/" className="flex items-center gap-3 group">
<div className="w-10 h-10 bg-slate-900 rounded-sm flex items-center justify-center group-hover:bg-slate-700 transition-colors">
<span className="text-white text-lg font-bold">M</span>
</div>
<span className="text-slate-900 font-bold tracking-tight text-xl">Marc Mintel</span>
</Link>
<nav className="flex items-center gap-8">
<Link href="/websites" className="text-xs font-bold uppercase tracking-widest text-slate-400 hover:text-slate-900 transition-colors">
Websites
</Link>
<Link href="/blog" className="text-xs font-bold uppercase tracking-widest text-slate-400 hover:text-slate-900 transition-colors">
Blog
</Link>
<a
href="mailto:marc@mintel.me"
className="text-xs font-bold uppercase tracking-widest text-slate-900 hover:text-slate-600 transition-colors"
>
Kontakt
</a>
</nav>
</div>
</header>
);
};