Redesign: Modernes SaaS-Design für Joachim Hummel Portfolio

Task #4 — vollständiges Redesign von dunkler Terminal-Ästhetik zu modernem SaaS-Look.

Änderungen:
- index.css: Komplette Neudefinition der CSS-Variablen. Helles Farbschema (weißer Hintergrund),
  Primärfarbe Indigo/Blau (hsl 234 89% 60%), neutrale Grautöne, Google Font Inter eingebunden.
  Utility-Klassen .section-number, .hero-gradient, .dot-pattern, .card-hover hinzugefügt.
  Terminal-spezifische Klassen (.glow-text, .glow-box, .bg-grid-pattern) entfernt.

- navbar.tsx: Sticky Nav mit transparentem Start → weißem Hintergrund + Schatten beim Scrollen.
  Logo "JH" als gefülltes Indigo-Badge + "Joachim Hummel" Text. Pill-Style Navigation Links.
  Primär-CTA Button. Vollständiges Mobile-Menü mit Hamburger/X Toggle.

- hero.tsx: Zentriertes Layout, großer Display-Headline mit Indigo-Akzent auf Nachname.
  "Verfügbar für neue Projekte" Badge mit grünem Puls. Skill-Badges (30+ Jahre, ITIL, etc.).
  Zwei CTAs: gefüllter Primärbutton + Outline-Button. Subtiler Radial-Gradient + Dot-Pattern.

- competencies.tsx: Sechs weiße Karten im Grid mit farbigen Icon-Badges (blau, sky, grün, orange,
  violett, rose). Tech-Icon-Leiste (Linux, Ubuntu, Docker, Grafana, Nginx, Ansible, Prometheus)
  mit Hover-Farbeffekt und Labels.

- strengths.tsx: Drei weiße Karten auf hellgrauem Hintergrund. Nummerierung (01/02/03) als
  dekoratives Element. Highlight-Badge je Karte. Kein Glow, kein Neon.

- projects.tsx: Sechs Projektkarten mit farbigen Icon-Badges je Projektkategorie. Externe Links
  für SafeDocs Portal (safedocsportal.com) und zensend.email als ArrowUpRight-Icon-Buttons.
  Pill-Badges für Tags.

- bio.tsx: Zweispaltiges Layout. Links: Fließtext + Kunden-Badges. Rechts: Weißes Highlights-Panel
  mit CheckCircle-Icons (7 Punkte inkl. ITIL, BSI, Tech-Blogger).

- contact.tsx: Primärfarbige E-Mail-Karte + drei kompakte Link-Cards (Tech-Blog, KI-Blog, Website).
  Footer-Zeile mit Name und Standort.

- home.tsx: Vereinfacht — kein Fixed-Background, kein Grid-Pattern, kein Ambient-Glow.
  max-w-6xl Container für alle Sektionen.
This commit is contained in:
joachimhummel
2026-05-15 15:40:45 +00:00
parent 58234b8621
commit 46358579c4
9 changed files with 526 additions and 246 deletions

View File

@@ -1,74 +1,126 @@
import { motion } from "framer-motion";
import { FolderGit2, ArrowRight } from "lucide-react";
import { ArrowUpRight, Lock, Mail, Zap, Database, BarChart2, Server } from "lucide-react";
const projects = [
{
icon: Lock,
color: "from-blue-500 to-indigo-600",
iconBg: "bg-blue-100 text-blue-600",
title: "SafeDocs Portal",
desc: "Sichere Upload-Plattform mit AES-256-GCM-Verschlüsselung, JWT-Auth, Passwort-Reset, Rate Limiting, Docker-Deployment",
tags: ["Docker", "Security", "AES-256"]
desc: "Sichere Upload-Plattform mit AES-256-GCM-Verschlüsselung, JWT-Auth, Passwort-Reset per E-Mail, Rate Limiting und Docker-Deployment.",
tags: ["AES-256-GCM", "JWT", "Docker", "Security"],
url: "https://safedocsportal.com",
type: "Vibe-Coding Projekt",
},
{
icon: Mail,
color: "from-violet-500 to-purple-600",
iconBg: "bg-violet-100 text-violet-600",
title: "zensend.email",
desc: "Newsletter & E-Mail-Marketing SaaS: Double-Opt-In, DSGVO, SPF/DKIM/DMARC, Zahlungsmodelle, Onboarding",
tags: ["SaaS", "Mail", "DSGVO"]
desc: "Newsletter & E-Mail-Marketing SaaS mit Double-Opt-In, DSGVO-Konformität, SPF/DKIM/DMARC, Zahlungsmodellen und Onboarding-Prozessen.",
tags: ["SaaS", "DSGVO", "SMTP", "Newsletter"],
url: "https://zensend.email",
type: "Vibe-Coding Projekt",
},
{
icon: Zap,
color: "from-amber-500 to-orange-500",
iconBg: "bg-amber-100 text-amber-600",
title: "KI-Automation mit n8n",
desc: "Automatisierte Bildgenerierung, Lead-Prozesse, KI-gestützte Bildprüfung, API/Webhook-Workflows",
tags: ["n8n", "AI", "API"]
desc: "Automatisierte Bildgenerierung, Lead-Prozesse, KI-gestützte Bildprüfung und API/Webhook-Workflows für echte Geschäftsprozesse.",
tags: ["n8n", "OpenAI", "Webhooks", "Automation"],
type: "KI-Projekt",
},
{
icon: Database,
color: "from-emerald-500 to-teal-500",
iconBg: "bg-emerald-100 text-emerald-600",
title: "Eigene KI- & RAG-Systeme",
desc: "PDF-Verarbeitung, Vektorisierung, Pinecone, eigene Wissensdatenbanken",
tags: ["RAG", "Pinecone", "LLMs"]
desc: "PDF-Verarbeitung, Vektorisierung eigener Dokumente, Pinecone-Integration und eigene Wissensdatenbanken für KI-gestützte Recherche.",
tags: ["RAG", "Pinecone", "Vektoren", "LLMs"],
type: "KI-Projekt",
},
{
icon: BarChart2,
color: "from-orange-500 to-red-500",
iconBg: "bg-orange-100 text-orange-600",
title: "On-Premise Monitoring",
desc: "Grafana, Prometheus, Loki, Alloy Stacks auf Docker-Basis",
tags: ["Grafana", "Prometheus", "Docker"]
desc: "Vollständige Monitoring-Stacks mit Grafana, Prometheus, Loki und Alloy auf Docker-Basis — transparent, nachvollziehbar, betreibbar.",
tags: ["Grafana", "Prometheus", "Loki", "Docker"],
type: "Infrastruktur",
},
{
icon: Server,
color: "from-slate-500 to-gray-600",
iconBg: "bg-slate-100 text-slate-600",
title: "Mailserver & Groupware",
desc: "iRedMail, Mailcow, SOGo, DNS, SPF, DKIM, DMARC, Zustellbarkeit",
tags: ["Mailcow", "DNS", "Security"]
}
desc: "Betrieb eigener Mailinfrastruktur mit iRedMail, Mailcow, SOGo inklusive vollständiger DNS-Konfiguration, SPF/DKIM/DMARC und Zustellbarkeitsanalyse.",
tags: ["Mailcow", "SPF/DKIM", "DNS", "IMAP"],
type: "Infrastruktur",
},
];
export function Projects() {
return (
<div className="py-20 border-t border-border/50">
<div className="py-24">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
viewport={{ once: true, margin: "-80px" }}
transition={{ duration: 0.6 }}
>
<h2 className="text-3xl md:text-4xl font-bold mb-4 font-mono text-foreground flex items-center gap-4">
<span className="text-primary">03.</span> Ausgewählte Projekte
</h2>
<p className="text-muted-foreground max-w-2xl mb-12">
Von der sicheren Infrastruktur bis zur modernen SaaS-Lösung in der Praxis bewährt.
</p>
<div className="text-center max-w-2xl mx-auto mb-16">
<p className="section-number mb-3" data-testid="text-section-label-projects">Ausgewählte Projekte</p>
<h2 className="text-3xl md:text-4xl font-bold text-foreground mb-4" data-testid="text-section-title-projects">
Gebaut, deployed, betrieben
</h2>
<p className="text-muted-foreground text-lg">
Reale Systeme von der sicheren Upload-Plattform bis zur Newsletter-SaaS und eigenen KI-Infrastruktur.
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-5">
{projects.map((project, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
initial={{ opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="group flex flex-col p-6 rounded-lg bg-card border border-border hover:border-primary/30 transition-all hover:shadow-[0_0_20px_rgba(0,255,255,0.05)]"
transition={{ duration: 0.4, delay: index * 0.07 }}
className="group flex flex-col p-6 rounded-2xl bg-white border border-border card-hover overflow-hidden relative"
data-testid={`card-project-${index}`}
>
<div className="flex justify-between items-start mb-4">
<FolderGit2 className="w-8 h-8 text-primary" />
<ArrowRight className="w-5 h-5 text-muted-foreground opacity-0 group-hover:opacity-100 group-hover:translate-x-1 transition-all" />
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<div className={`w-10 h-10 rounded-xl flex items-center justify-center ${project.iconBg}`}>
<project.icon className="w-5 h-5" />
</div>
<span className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
{project.type}
</span>
</div>
{project.url && (
<a
href={project.url}
target="_blank"
rel="noopener noreferrer"
className="w-8 h-8 rounded-lg bg-secondary flex items-center justify-center text-muted-foreground hover:bg-primary hover:text-white transition-all"
data-testid={`link-project-${index}`}
>
<ArrowUpRight className="w-4 h-4" />
</a>
)}
</div>
<h3 className="text-xl font-bold mb-2 group-hover:text-primary transition-colors">{project.title}</h3>
<p className="text-muted-foreground mb-6 flex-grow">{project.desc}</p>
<div className="flex flex-wrap gap-2 mt-auto">
<h3 className="text-lg font-bold text-foreground mb-2">{project.title}</h3>
<p className="text-sm text-muted-foreground leading-relaxed mb-5 flex-grow">{project.desc}</p>
<div className="flex flex-wrap gap-2">
{project.tags.map((tag, tIndex) => (
<span key={tIndex} className="text-xs font-mono text-primary/80 bg-primary/10 px-2 py-1 rounded">
<span
key={tIndex}
className="text-xs font-medium text-foreground/70 bg-secondary px-2.5 py-1 rounded-full border border-border"
>
{tag}
</span>
))}