From 365c39d228e0d2c360f87176264698c2caa35984 Mon Sep 17 00:00:00 2001 From: Mike Karl Date: Wed, 6 May 2026 09:11:43 +0200 Subject: [PATCH] cursor effect & metadata fix --- src/app/about/page.tsx | 3 +++ src/app/contact/page.tsx | 3 +++ src/app/hobbies/page.tsx | 3 +++ src/app/layout.tsx | 7 +++++-- src/app/page.tsx | 4 ++++ src/app/project/emulator/page.tsx | 3 +++ src/app/project/raycaster/page.tsx | 3 +++ src/app/project/raytracer/page.tsx | 3 +++ src/app/projects/page.tsx | 3 +++ src/app/timeline/page.tsx | 3 +++ src/components/ParticleGrid.tsx | 14 ++++++++++---- src/data/about.ts | 5 +++++ src/data/contact.ts | 5 +++++ src/data/hobbies.ts | 5 +++++ src/data/projects.ts | 16 ++++++++++++++++ src/data/site.ts | 6 ++++++ src/data/timeline.ts | 5 +++++ 17 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 353d9bf..344ab4a 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -1,9 +1,12 @@ +import type { Metadata } from "next"; import Link from "next/link"; import { ArrowRight } from "lucide-react"; import { values, aboutPage } from "@/data/about"; import { site } from "@/data/site"; import { Icon } from "@/lib/icons"; +export const metadata: Metadata = aboutPage.metadata; + export default function AboutPage() { return (
diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx index 68ad1a0..d81a4bf 100644 --- a/src/app/contact/page.tsx +++ b/src/app/contact/page.tsx @@ -1,7 +1,10 @@ +import type { Metadata } from "next"; import { site } from "@/data/site"; import { contactContent, contactPage } from "@/data/contact"; import { Mail } from "lucide-react"; +export const metadata: Metadata = contactPage.metadata; + export default function ContactPage() { return (
diff --git a/src/app/hobbies/page.tsx b/src/app/hobbies/page.tsx index f55ad5a..3fd001d 100644 --- a/src/app/hobbies/page.tsx +++ b/src/app/hobbies/page.tsx @@ -1,6 +1,9 @@ +import type { Metadata } from "next"; import { hobbies, hobbiesPage } from "@/data/hobbies"; import { Icon } from "@/lib/icons"; +export const metadata: Metadata = hobbiesPage.metadata; + export default function HobbiesPage() { return (
diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7d12096..099051d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -31,9 +31,12 @@ const ibmPlexMono = IBM_Plex_Mono({ }); export const metadata: Metadata = { - title: "Mike Karl — Portfolio", + title: { + default: "Mike Karl — Portfolio", + template: "%s — Mike Karl", + }, description: - "Mike Karl — Systementwickler & Creative Technologist aus Köln. Portfolio mit Projekten aus Systems Programming, Computer Graphics und Low-Level-Entwicklung.", + "Portfolio von Mike Karl — Systementwickler & Creative Technologist. Projekte aus Systems Programming, Computer Graphics und Low-Level-Entwicklung.", icons: { icon: "/favicon.svg", }, diff --git a/src/app/page.tsx b/src/app/page.tsx index 91782b4..276012f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,3 +1,5 @@ +import type { Metadata } from "next"; +import { homeMetadata } from "@/data/site"; import HeroSection from "@/sections/HeroSection"; import AboutSection from "@/sections/AboutSection"; import HobbiesSection from "@/sections/HobbiesSection"; @@ -5,6 +7,8 @@ import ProjectsSection from "@/sections/ProjectsSection"; import TimelineSection from "@/sections/TimelineSection"; import ContactSection from "@/sections/ContactSection"; +export const metadata: Metadata = homeMetadata; + export default function HomePage() { return (
diff --git a/src/app/project/emulator/page.tsx b/src/app/project/emulator/page.tsx index d3b2720..c1fb4d4 100644 --- a/src/app/project/emulator/page.tsx +++ b/src/app/project/emulator/page.tsx @@ -1,6 +1,9 @@ +import type { Metadata } from "next"; import ProjectPageLayout from "@/components/ProjectPageLayout"; import { emulatorProject } from "@/data/projects"; +export const metadata: Metadata = emulatorProject.metadata; + export default function ProjectEmulatorPage() { return ( diff --git a/src/app/timeline/page.tsx b/src/app/timeline/page.tsx index 8199b35..fb4987c 100644 --- a/src/app/timeline/page.tsx +++ b/src/app/timeline/page.tsx @@ -1,5 +1,8 @@ +import type { Metadata } from "next"; import { timeline, timelinePage } from "@/data/timeline"; +export const metadata: Metadata = timelinePage.metadata; + export default function TimelinePage() { return (
diff --git a/src/components/ParticleGrid.tsx b/src/components/ParticleGrid.tsx index a764ab3..56f3b35 100644 --- a/src/components/ParticleGrid.tsx +++ b/src/components/ParticleGrid.tsx @@ -98,17 +98,23 @@ export default function ParticleGrid() { mouseRef.current = { x: -1000, y: -1000 }; }; + const isTouchDevice = window.matchMedia("(hover: none)").matches; + init(); animate(); window.addEventListener("resize", init); - canvas.addEventListener("mousemove", handleMouseMove); - canvas.addEventListener("mouseleave", handleMouseLeave); + if (!isTouchDevice) { + canvas.addEventListener("mousemove", handleMouseMove); + canvas.addEventListener("mouseleave", handleMouseLeave); + } return () => { cancelAnimationFrame(animRef.current); window.removeEventListener("resize", init); - canvas.removeEventListener("mousemove", handleMouseMove); - canvas.removeEventListener("mouseleave", handleMouseLeave); + if (!isTouchDevice) { + canvas.removeEventListener("mousemove", handleMouseMove); + canvas.removeEventListener("mouseleave", handleMouseLeave); + } }; }, []); diff --git a/src/data/about.ts b/src/data/about.ts index ab4a5b8..dc4faa2 100644 --- a/src/data/about.ts +++ b/src/data/about.ts @@ -28,6 +28,11 @@ export const aboutContent = { }; export const aboutPage = { + metadata: { + title: "Über mich", + description: + "Full-Stack & Systementwickler aus Grafenau. Ich baue Dinge von der Hardware-Ebene bis zur Benutzeroberfläche.", + }, label: "01 / About", pageTitle: "Über mich", pageSubtitle: diff --git a/src/data/contact.ts b/src/data/contact.ts index 828ef0e..d663614 100644 --- a/src/data/contact.ts +++ b/src/data/contact.ts @@ -5,6 +5,11 @@ export const contactContent = { }; export const contactPage = { + metadata: { + title: "Kontakt", + description: + "Ich ziehe neue Projekte an Land oder werfe mich kopfüber in legacy software.", + }, label: "05 / Kontakt", pageSubtitle: "Ich ziehe neue Projekte an Land oder werfe mich kopfüber in legacy software.", diff --git a/src/data/hobbies.ts b/src/data/hobbies.ts index aa5079b..3976a28 100644 --- a/src/data/hobbies.ts +++ b/src/data/hobbies.ts @@ -1,4 +1,9 @@ export const hobbiesPage = { + metadata: { + title: "Hobbies", + description: + "Motorradfahren und Astrofotografie – Ruhe, Gelassenheit, Abenteuer und Entdeckung", + }, label: "02 / Hobbies", sectionSubtitle: "Was ich außerhalb des Terminals mache.", pageTitle: "Außerhalb des Terminals", diff --git a/src/data/projects.ts b/src/data/projects.ts index 86d4841..c0a8a5c 100644 --- a/src/data/projects.ts +++ b/src/data/projects.ts @@ -29,6 +29,10 @@ export const projects = [ ]; export const emulatorProject = { + metadata: { + title: "6502 Emulator", + description: "Cycle-accurate CPU-Simulation in C++ mit eigenem Assembler-Parser.", + }, title: "6502 Emulator", subtitle: "Cycle-accurate CPU-Simulation in C++", tags: ["C++", "6502 Assembly", "Systems Programming", "Emulation"], @@ -81,6 +85,10 @@ export const emulatorProject = { }; export const raytracerProject = { + metadata: { + title: "Software Raytracer", + description: "Monte-Carlo-Pfad-Tracing-Renderer in C. Multithreading, BVH-Beschleunigung, sanfte Schatten.", + }, title: "Software Raytracer", subtitle: "Monte-Carlo-Pfad-Tracing in C", tags: ["C", "Computer Graphics", "Multithreading"], @@ -145,6 +153,10 @@ export const projectLayout = { }; export const projectsPage = { + metadata: { + title: "Projekte", + description: "Systeme, die ich aus der Transistor-Ebene heraus gebaut habe.", + }, sectionLabel: "03 / Ausgewählte Projekte", pageLabel: "03 / Projekte", pageTitle: "Ausgewählte Projekte", @@ -157,6 +169,10 @@ export const projectsPage = { }; export const raycasterProject = { + metadata: { + title: "Raycasting Engine", + description: "Wolfenstein-3D-Style-Renderer mit DDA-Algorithmus und Textur-Mapping.", + }, title: "Raycasting Engine", subtitle: "Wolfenstein-3D-Style-Renderer mit DDA-Algorithmus", tags: ["C++", "Game Dev", "Algorithms"], diff --git a/src/data/site.ts b/src/data/site.ts index 51665f8..fc5af49 100644 --- a/src/data/site.ts +++ b/src/data/site.ts @@ -26,6 +26,12 @@ export const footerContent = { builtWith: "Built with Next.js, React & Tailwind CSS", }; +export const homeMetadata = { + title: "Mike Karl — Portfolio", + description: + "Mike Karl — Systementwickler & Creative Technologist aus Grafenau. Portfolio mit Projekten aus Systems Programming, Computer Graphics und Low-Level-Entwicklung.", +}; + export const heroContent = { subtitle: [ "Full-Stack Entwickler", diff --git a/src/data/timeline.ts b/src/data/timeline.ts index 36e29e2..1cf0cc4 100644 --- a/src/data/timeline.ts +++ b/src/data/timeline.ts @@ -1,4 +1,9 @@ export const timelinePage = { + metadata: { + title: "Werdegang", + description: + 'Vom ersten "Hello World" bis zur professionellen Softwareentwicklung.', + }, label: "04 / Werdegang", subtitle: 'Vom ersten "Hello World" bis zur professionellen Softwareentwicklung.',