Task #1: Kontaktdaten, Titel & Projektlinks

Changes:
- hero.tsx: Extended title subtitle to two lines covering all six roles:
  "Senior IT-Consultant · Service Manager · Technical Writer" (line 1)
  "KI-Automation Experte · IT-Systems Engineer · Vibe-Coder" (line 2)
  Uses <br> hidden on mobile, visible on sm+ screens for clean wrapping.

- navbar.tsx: Added blogLinks array (Tech-Blog, KI-Blog) rendered after a
  visual separator (1px divider) in the desktop nav and mobile menu.
  Each blog link opens in a new tab with rel="noopener noreferrer" and
  an ExternalLink icon (3px, half-opacity) as a visual cue.
  Added ExternalLink import from lucide-react.

- projects.tsx: Removed leftover `color` field from the "Mailserver &
  Groupware" entry (cleanup from prior task).

Already complete from Task #4 (redesign):
- contact.tsx: jh@unixweb.de, blog.unixweb.de, ki-blog.unixweb.de,
  joachimhummel.de all wired up with correct target="_blank" links.
- projects.tsx: SafeDocs Portal (safedocsportal.com) and zensend.email
  already had url fields and ArrowUpRight link buttons rendering.
  No address or phone number anywhere on the site.

No deviations from scope.
This commit is contained in:
joachimhummel
2026-05-15 15:43:48 +00:00
parent ba482b5e7a
commit 9d143d7979
3 changed files with 42 additions and 9 deletions

View File

@@ -36,8 +36,10 @@ export function Hero() {
<span className="text-primary">Hummel</span>
</h1>
<p className="text-lg md:text-xl font-medium text-muted-foreground mb-4 tracking-wide" data-testid="text-hero-title">
Senior IT-Consultant &middot; Service Manager &middot; Technical Writer &middot; Vibe-Coder
<p className="text-base md:text-lg font-medium text-muted-foreground mb-4 tracking-wide leading-relaxed" data-testid="text-hero-title">
Senior IT-Consultant &middot; Service Manager &middot; Technical Writer
<br className="hidden sm:block" />
KI-Automation Experte &middot; IT-Systems Engineer &middot; Vibe-Coder
</p>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed mb-10" data-testid="text-hero-description">

View File

@@ -1,6 +1,6 @@
import { useState } from "react";
import { motion, useScroll, useMotionValueEvent } from "framer-motion";
import { Menu, X } from "lucide-react";
import { Menu, X, ExternalLink } from "lucide-react";
export function Navbar() {
const [isScrolled, setIsScrolled] = useState(false);
@@ -12,11 +12,16 @@ export function Navbar() {
});
const navLinks = [
{ name: "Kompetenzen", href: "#competencies" },
{ name: "Stärken", href: "#strengths" },
{ name: "Projekte", href: "#projects" },
{ name: "Über mich", href: "#bio" },
{ name: "Kontakt", href: "#contact" },
{ name: "Kompetenzen", href: "#competencies", external: false },
{ name: "Stärken", href: "#strengths", external: false },
{ name: "Projekte", href: "#projects", external: false },
{ name: "Über mich", href: "#bio", external: false },
{ name: "Kontakt", href: "#contact", external: false },
];
const blogLinks = [
{ name: "Tech-Blog", href: "https://blog.unixweb.de" },
{ name: "KI-Blog", href: "https://ki-blog.unixweb.de" },
];
return (
@@ -53,6 +58,20 @@ export function Navbar() {
{link.name}
</a>
))}
<div className="w-px h-4 bg-border mx-1" />
{blogLinks.map((link) => (
<a
key={link.name}
href={link.href}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-all"
data-testid={`link-nav-${link.name.toLowerCase().replace(/\s/g, '-')}`}
>
{link.name}
<ExternalLink className="w-3 h-3 opacity-50" />
</a>
))}
</nav>
<div className="hidden md:block">
@@ -90,6 +109,19 @@ export function Navbar() {
{link.name}
</a>
))}
<div className="border-t border-border my-1" />
{blogLinks.map((link) => (
<a
key={link.name}
href={link.href}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-4 py-3 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-all"
>
{link.name}
<ExternalLink className="w-3 h-3 opacity-50" />
</a>
))}
<a
href="#contact"
onClick={() => setMobileOpen(false)}

View File

@@ -46,7 +46,6 @@ const projects = [
},
{
icon: Server,
color: "from-slate-500 to-gray-600",
iconBg: "bg-slate-100 text-slate-600",
title: "Mailserver & Groupware",
desc: "Betrieb eigener Mailinfrastruktur mit iRedMail, Mailcow, SOGo inklusive vollständiger DNS-Konfiguration, SPF/DKIM/DMARC und Zustellbarkeitsanalyse.",