design
This commit is contained in:
191
app/blog/page.tsx
Normal file
191
app/blog/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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 />
|
||||
|
||||
454
app/page.tsx
454
app/page.tsx
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
164
app/websites/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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
32
src/components/Header.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user