cursor effect & metadata fix

This commit is contained in:
Mike Karl 2026-05-06 09:11:43 +02:00
parent 3fae67d83b
commit 365c39d228
17 changed files with 85 additions and 6 deletions

View file

@ -1,9 +1,12 @@
import type { Metadata } from "next";
import Link from "next/link"; import Link from "next/link";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import { values, aboutPage } from "@/data/about"; import { values, aboutPage } from "@/data/about";
import { site } from "@/data/site"; import { site } from "@/data/site";
import { Icon } from "@/lib/icons"; import { Icon } from "@/lib/icons";
export const metadata: Metadata = aboutPage.metadata;
export default function AboutPage() { export default function AboutPage() {
return ( return (
<main className="min-h-screen bg-deep-space"> <main className="min-h-screen bg-deep-space">

View file

@ -1,7 +1,10 @@
import type { Metadata } from "next";
import { site } from "@/data/site"; import { site } from "@/data/site";
import { contactContent, contactPage } from "@/data/contact"; import { contactContent, contactPage } from "@/data/contact";
import { Mail } from "lucide-react"; import { Mail } from "lucide-react";
export const metadata: Metadata = contactPage.metadata;
export default function ContactPage() { export default function ContactPage() {
return ( return (
<main className="min-h-screen bg-deep-space"> <main className="min-h-screen bg-deep-space">

View file

@ -1,6 +1,9 @@
import type { Metadata } from "next";
import { hobbies, hobbiesPage } from "@/data/hobbies"; import { hobbies, hobbiesPage } from "@/data/hobbies";
import { Icon } from "@/lib/icons"; import { Icon } from "@/lib/icons";
export const metadata: Metadata = hobbiesPage.metadata;
export default function HobbiesPage() { export default function HobbiesPage() {
return ( return (
<main className="min-h-screen bg-deep-space"> <main className="min-h-screen bg-deep-space">

View file

@ -31,9 +31,12 @@ const ibmPlexMono = IBM_Plex_Mono({
}); });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Mike Karl — Portfolio", title: {
default: "Mike Karl — Portfolio",
template: "%s — Mike Karl",
},
description: 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: { icons: {
icon: "/favicon.svg", icon: "/favicon.svg",
}, },

View file

@ -1,3 +1,5 @@
import type { Metadata } from "next";
import { homeMetadata } from "@/data/site";
import HeroSection from "@/sections/HeroSection"; import HeroSection from "@/sections/HeroSection";
import AboutSection from "@/sections/AboutSection"; import AboutSection from "@/sections/AboutSection";
import HobbiesSection from "@/sections/HobbiesSection"; import HobbiesSection from "@/sections/HobbiesSection";
@ -5,6 +7,8 @@ import ProjectsSection from "@/sections/ProjectsSection";
import TimelineSection from "@/sections/TimelineSection"; import TimelineSection from "@/sections/TimelineSection";
import ContactSection from "@/sections/ContactSection"; import ContactSection from "@/sections/ContactSection";
export const metadata: Metadata = homeMetadata;
export default function HomePage() { export default function HomePage() {
return ( return (
<main> <main>

View file

@ -1,6 +1,9 @@
import type { Metadata } from "next";
import ProjectPageLayout from "@/components/ProjectPageLayout"; import ProjectPageLayout from "@/components/ProjectPageLayout";
import { emulatorProject } from "@/data/projects"; import { emulatorProject } from "@/data/projects";
export const metadata: Metadata = emulatorProject.metadata;
export default function ProjectEmulatorPage() { export default function ProjectEmulatorPage() {
return ( return (
<ProjectPageLayout <ProjectPageLayout

View file

@ -1,6 +1,9 @@
import type { Metadata } from "next";
import ProjectPageLayout from "@/components/ProjectPageLayout"; import ProjectPageLayout from "@/components/ProjectPageLayout";
import { raycasterProject } from "@/data/projects"; import { raycasterProject } from "@/data/projects";
export const metadata: Metadata = raycasterProject.metadata;
export default function ProjectRaycasterPage() { export default function ProjectRaycasterPage() {
return ( return (
<ProjectPageLayout <ProjectPageLayout

View file

@ -1,6 +1,9 @@
import type { Metadata } from "next";
import ProjectPageLayout from "@/components/ProjectPageLayout"; import ProjectPageLayout from "@/components/ProjectPageLayout";
import { raytracerProject } from "@/data/projects"; import { raytracerProject } from "@/data/projects";
export const metadata: Metadata = raytracerProject.metadata;
export default function ProjectRaytracerPage() { export default function ProjectRaytracerPage() {
return ( return (
<ProjectPageLayout <ProjectPageLayout

View file

@ -1,7 +1,10 @@
import type { Metadata } from "next";
import Link from "next/link"; import Link from "next/link";
import { projects, projectsPage } from "@/data/projects"; import { projects, projectsPage } from "@/data/projects";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
export const metadata: Metadata = projectsPage.metadata;
export default function ProjectsPage() { export default function ProjectsPage() {
return ( return (
<main className="min-h-screen bg-deep-space"> <main className="min-h-screen bg-deep-space">

View file

@ -1,5 +1,8 @@
import type { Metadata } from "next";
import { timeline, timelinePage } from "@/data/timeline"; import { timeline, timelinePage } from "@/data/timeline";
export const metadata: Metadata = timelinePage.metadata;
export default function TimelinePage() { export default function TimelinePage() {
return ( return (
<main className="min-h-screen bg-deep-space"> <main className="min-h-screen bg-deep-space">

View file

@ -98,17 +98,23 @@ export default function ParticleGrid() {
mouseRef.current = { x: -1000, y: -1000 }; mouseRef.current = { x: -1000, y: -1000 };
}; };
const isTouchDevice = window.matchMedia("(hover: none)").matches;
init(); init();
animate(); animate();
window.addEventListener("resize", init); window.addEventListener("resize", init);
if (!isTouchDevice) {
canvas.addEventListener("mousemove", handleMouseMove); canvas.addEventListener("mousemove", handleMouseMove);
canvas.addEventListener("mouseleave", handleMouseLeave); canvas.addEventListener("mouseleave", handleMouseLeave);
}
return () => { return () => {
cancelAnimationFrame(animRef.current); cancelAnimationFrame(animRef.current);
window.removeEventListener("resize", init); window.removeEventListener("resize", init);
if (!isTouchDevice) {
canvas.removeEventListener("mousemove", handleMouseMove); canvas.removeEventListener("mousemove", handleMouseMove);
canvas.removeEventListener("mouseleave", handleMouseLeave); canvas.removeEventListener("mouseleave", handleMouseLeave);
}
}; };
}, []); }, []);

View file

@ -28,6 +28,11 @@ export const aboutContent = {
}; };
export const aboutPage = { 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", label: "01 / About",
pageTitle: "Über mich", pageTitle: "Über mich",
pageSubtitle: pageSubtitle:

View file

@ -5,6 +5,11 @@ export const contactContent = {
}; };
export const contactPage = { export const contactPage = {
metadata: {
title: "Kontakt",
description:
"Ich ziehe neue Projekte an Land oder werfe mich kopfüber in legacy software.",
},
label: "05 / Kontakt", label: "05 / Kontakt",
pageSubtitle: pageSubtitle:
"Ich ziehe neue Projekte an Land oder werfe mich kopfüber in legacy software.", "Ich ziehe neue Projekte an Land oder werfe mich kopfüber in legacy software.",

View file

@ -1,4 +1,9 @@
export const hobbiesPage = { export const hobbiesPage = {
metadata: {
title: "Hobbies",
description:
"Motorradfahren und Astrofotografie – Ruhe, Gelassenheit, Abenteuer und Entdeckung",
},
label: "02 / Hobbies", label: "02 / Hobbies",
sectionSubtitle: "Was ich außerhalb des Terminals mache.", sectionSubtitle: "Was ich außerhalb des Terminals mache.",
pageTitle: "Außerhalb des Terminals", pageTitle: "Außerhalb des Terminals",

View file

@ -29,6 +29,10 @@ export const projects = [
]; ];
export const emulatorProject = { export const emulatorProject = {
metadata: {
title: "6502 Emulator",
description: "Cycle-accurate CPU-Simulation in C++ mit eigenem Assembler-Parser.",
},
title: "6502 Emulator", title: "6502 Emulator",
subtitle: "Cycle-accurate CPU-Simulation in C++", subtitle: "Cycle-accurate CPU-Simulation in C++",
tags: ["C++", "6502 Assembly", "Systems Programming", "Emulation"], tags: ["C++", "6502 Assembly", "Systems Programming", "Emulation"],
@ -81,6 +85,10 @@ export const emulatorProject = {
}; };
export const raytracerProject = { export const raytracerProject = {
metadata: {
title: "Software Raytracer",
description: "Monte-Carlo-Pfad-Tracing-Renderer in C. Multithreading, BVH-Beschleunigung, sanfte Schatten.",
},
title: "Software Raytracer", title: "Software Raytracer",
subtitle: "Monte-Carlo-Pfad-Tracing in C", subtitle: "Monte-Carlo-Pfad-Tracing in C",
tags: ["C", "Computer Graphics", "Multithreading"], tags: ["C", "Computer Graphics", "Multithreading"],
@ -145,6 +153,10 @@ export const projectLayout = {
}; };
export const projectsPage = { export const projectsPage = {
metadata: {
title: "Projekte",
description: "Systeme, die ich aus der Transistor-Ebene heraus gebaut habe.",
},
sectionLabel: "03 / Ausgewählte Projekte", sectionLabel: "03 / Ausgewählte Projekte",
pageLabel: "03 / Projekte", pageLabel: "03 / Projekte",
pageTitle: "Ausgewählte Projekte", pageTitle: "Ausgewählte Projekte",
@ -157,6 +169,10 @@ export const projectsPage = {
}; };
export const raycasterProject = { export const raycasterProject = {
metadata: {
title: "Raycasting Engine",
description: "Wolfenstein-3D-Style-Renderer mit DDA-Algorithmus und Textur-Mapping.",
},
title: "Raycasting Engine", title: "Raycasting Engine",
subtitle: "Wolfenstein-3D-Style-Renderer mit DDA-Algorithmus", subtitle: "Wolfenstein-3D-Style-Renderer mit DDA-Algorithmus",
tags: ["C++", "Game Dev", "Algorithms"], tags: ["C++", "Game Dev", "Algorithms"],

View file

@ -26,6 +26,12 @@ export const footerContent = {
builtWith: "Built with Next.js, React & Tailwind CSS", 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 = { export const heroContent = {
subtitle: [ subtitle: [
"Full-Stack Entwickler", "Full-Stack Entwickler",

View file

@ -1,4 +1,9 @@
export const timelinePage = { export const timelinePage = {
metadata: {
title: "Werdegang",
description:
'Vom ersten "Hello World" bis zur professionellen Softwareentwicklung.',
},
label: "04 / Werdegang", label: "04 / Werdegang",
subtitle: subtitle:
'Vom ersten "Hello World" bis zur professionellen Softwareentwicklung.', 'Vom ersten "Hello World" bis zur professionellen Softwareentwicklung.',