Initial import: was v0 exportiert hat

This commit is contained in:
Dieter Schlüter 2026-04-24 17:12:51 +02:00
commit 0194931215
167 changed files with 16465 additions and 0 deletions

73
app/datenschutz/page.tsx Normal file
View file

@ -0,0 +1,73 @@
import Link from 'next/link'
import { ArrowLeft } from 'lucide-react'
import { Button } from '@/components/ui/button'
export const metadata = {
title: 'Datenschutz | Jamulix',
description: 'Datenschutzerklärung für jamulix.de',
}
export default function DatenschutzPage() {
return (
<main className="min-h-screen py-24 lg:py-32">
<div className="max-w-3xl mx-auto px-6 lg:px-8">
<Button asChild variant="ghost" className="mb-8 -ml-4">
<Link href="/">
<ArrowLeft className="mr-2 size-4" />
Zurück
</Link>
</Button>
<h1 className="font-serif text-4xl lg:text-5xl mb-8">Datenschutz</h1>
<div className="prose prose-neutral dark:prose-invert max-w-none space-y-8">
<section>
<h2 className="font-serif text-xl mb-4">1. Datenschutz auf einen Blick</h2>
<h3 className="font-medium mt-6 mb-2">Allgemeine Hinweise</h3>
<p className="text-muted-foreground leading-relaxed">
Die folgenden Hinweise geben einen einfachen Überblick darüber,
was mit Ihren personenbezogenen Daten passiert, wenn Sie diese
Website besuchen.
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">2. Hosting</h2>
<p className="text-muted-foreground leading-relaxed">
Diese Website wird bei Vercel gehostet. Der Anbieter ist
Vercel Inc., 340 S Lemon Ave #4133, Walnut, CA 91789, USA.
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">3. Allgemeine Hinweise</h2>
<p className="text-muted-foreground leading-relaxed">
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen
Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten
vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften
sowie dieser Datenschutzerklärung.
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">4. Datenerfassung auf dieser Website</h2>
<h3 className="font-medium mt-6 mb-2">Server-Log-Dateien</h3>
<p className="text-muted-foreground leading-relaxed">
Der Provider dieser Seiten erhebt und speichert automatisch
Informationen in so genannten Server-Log-Dateien, die Ihr Browser
automatisch an uns übermittelt.
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">5. Kontakt</h2>
<p className="text-muted-foreground leading-relaxed">
Bei Fragen zum Datenschutz können Sie sich jederzeit an uns wenden:<br />
E-Mail: kontakt@jamulix.de
</p>
</section>
</div>
</div>
</main>
)
}

114
app/globals.css Normal file
View file

@ -0,0 +1,114 @@
@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
:root {
/* Light mode - warm paper tones */
--background: oklch(0.98 0.005 90);
--foreground: oklch(0.18 0.01 270);
--card: oklch(0.96 0.005 90);
--card-foreground: oklch(0.18 0.01 270);
--popover: oklch(0.98 0.005 90);
--popover-foreground: oklch(0.18 0.01 270);
--primary: oklch(0.18 0.01 270);
--primary-foreground: oklch(0.98 0.005 90);
--secondary: oklch(0.94 0.005 90);
--secondary-foreground: oklch(0.25 0.01 270);
--muted: oklch(0.92 0.005 90);
--muted-foreground: oklch(0.45 0.01 270);
--accent: oklch(0.65 0.15 145);
--accent-foreground: oklch(0.15 0.02 145);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.577 0.245 27.325);
--border: oklch(0.88 0.005 90);
--input: oklch(0.92 0.005 90);
--ring: oklch(0.65 0.15 145);
--radius: 0.5rem;
}
.dark {
/* Dark mode - deep charcoal with warmth */
--background: oklch(0.13 0.01 270);
--foreground: oklch(0.92 0.01 90);
--card: oklch(0.16 0.01 270);
--card-foreground: oklch(0.92 0.01 90);
--popover: oklch(0.16 0.01 270);
--popover-foreground: oklch(0.92 0.01 90);
--primary: oklch(0.92 0.01 90);
--primary-foreground: oklch(0.13 0.01 270);
--secondary: oklch(0.22 0.01 270);
--secondary-foreground: oklch(0.85 0.01 90);
--muted: oklch(0.20 0.01 270);
--muted-foreground: oklch(0.60 0.01 90);
--accent: oklch(0.72 0.14 140);
--accent-foreground: oklch(0.13 0.01 270);
--destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--border: oklch(0.25 0.01 270);
--input: oklch(0.22 0.01 270);
--ring: oklch(0.72 0.14 140);
}
@theme inline {
--font-sans: 'Inter', 'Inter Fallback', system-ui, sans-serif;
--font-serif: 'Instrument Serif', 'Georgia', serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
html {
scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
}
/* Selection colors */
::selection {
background: oklch(0.72 0.14 140 / 0.3);
}
.dark ::selection {
background: oklch(0.72 0.14 140 / 0.4);
}

61
app/impressum/page.tsx Normal file
View file

@ -0,0 +1,61 @@
import Link from 'next/link'
import { ArrowLeft } from 'lucide-react'
import { Button } from '@/components/ui/button'
export const metadata = {
title: 'Impressum | Jamulix',
description: 'Impressum und Angaben gemäß § 5 TMG für jamulix.de',
}
export default function ImpressumPage() {
return (
<main className="min-h-screen py-24 lg:py-32">
<div className="max-w-3xl mx-auto px-6 lg:px-8">
<Button asChild variant="ghost" className="mb-8 -ml-4">
<Link href="/">
<ArrowLeft className="mr-2 size-4" />
Zurück
</Link>
</Button>
<h1 className="font-serif text-4xl lg:text-5xl mb-8">Impressum</h1>
<div className="prose prose-neutral dark:prose-invert max-w-none space-y-8">
<section>
<h2 className="font-serif text-xl mb-4">Angaben gemäß § 5 TMG</h2>
<p className="text-muted-foreground">
[Name]<br />
[Straße und Hausnummer]<br />
[PLZ Ort]<br />
Deutschland
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">Kontakt</h2>
<p className="text-muted-foreground">
E-Mail: kontakt@jamulix.de
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">Verantwortlich für den Inhalt</h2>
<p className="text-muted-foreground">
[Name]<br />
[Adresse]
</p>
</section>
<section>
<h2 className="font-serif text-xl mb-4">Haftungsausschluss</h2>
<p className="text-muted-foreground leading-relaxed">
Die Inhalte dieser Seiten wurden mit größter Sorgfalt erstellt.
Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte
kann jedoch keine Gewähr übernommen werden.
</p>
</section>
</div>
</div>
</main>
)
}

90
app/layout.tsx Normal file
View file

@ -0,0 +1,90 @@
import type { Metadata, Viewport } from 'next'
import { Inter, Instrument_Serif, JetBrains_Mono } from 'next/font/google'
import { Analytics } from '@vercel/analytics/next'
import './globals.css'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
display: 'swap',
})
const instrumentSerif = Instrument_Serif({
weight: '400',
subsets: ['latin'],
variable: '--font-instrument-serif',
display: 'swap',
})
const jetbrainsMono = JetBrains_Mono({
subsets: ['latin'],
variable: '--font-jetbrains-mono',
display: 'swap',
})
export const metadata: Metadata = {
title: 'Jamulix | 40 Jahre Code',
description: 'Seit 40 Jahren Code. Von Fortran IV bis KI-Projekte in Python und Rust. Erfahrener Programmierer, Linux-Veteran und KI-Entwickler.',
keywords: ['Programmierung', 'Linux', 'KI', 'Python', 'Rust', 'Software-Entwicklung', 'AI', 'Fortran', 'Unix'],
authors: [{ name: 'Jamulix' }],
creator: 'Jamulix',
openGraph: {
type: 'website',
locale: 'de_DE',
url: 'https://jamulix.de',
siteName: 'Jamulix',
title: 'Jamulix | 40 Jahre Code',
description: 'Seit 40 Jahren Code. Von Fortran IV bis KI-Projekte in Python und Rust.',
},
twitter: {
card: 'summary_large_image',
title: 'Jamulix | 40 Jahre Code',
description: 'Seit 40 Jahren Code. Von Fortran IV bis KI-Projekte in Python und Rust.',
},
robots: {
index: true,
follow: true,
},
}
export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#faf9f7' },
{ media: '(prefers-color-scheme: dark)', color: '#1a1a1f' },
],
width: 'device-width',
initialScale: 1,
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html
lang="de"
className={`${inter.variable} ${instrumentSerif.variable} ${jetbrainsMono.variable} dark bg-background`}
suppressHydrationWarning
>
<head>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
const stored = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = stored || (prefersDark ? 'dark' : 'light');
document.documentElement.classList.toggle('dark', theme === 'dark');
})();
`,
}}
/>
</head>
<body className="font-sans antialiased min-h-screen">
{children}
{process.env.NODE_ENV === 'production' && <Analytics />}
</body>
</html>
)
}

23
app/page.tsx Normal file
View file

@ -0,0 +1,23 @@
import { Header } from '@/components/header'
import { Hero } from '@/components/hero'
import { AboutSection } from '@/components/about-section'
import { ProjectsSection } from '@/components/projects-section'
import { FocusSection } from '@/components/focus-section'
import { PhilosophySection } from '@/components/philosophy-section'
import { Footer } from '@/components/footer'
export default function Home() {
return (
<>
<Header />
<main>
<Hero />
<AboutSection />
<ProjectsSection />
<FocusSection />
<PhilosophySection />
</main>
<Footer />
</>
)
}