Browser fragen /favicon.ico ab — die Deploy-Skripte setzen jetzt einen Symlink auf landingpage/favicon.ico. Programmierer.png liegt jetzt in components/assets/ (statischer Import), damit der Export keine ungenutzte 1,6-MB-Kopie mehr nach landingpage/ legt. README angepasst. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.9 KiB
jamulix.de — Landing Page
Next.js 16 Landing Page für jamulix.de, statisch exportiert und unter /landingpage/ deployed.
Tech Stack
- Next.js 16.2 mit
output: 'export'(statischer Export, kein Node.js-Server nötig) - React 19, TypeScript
- Tailwind CSS v4 + shadcn/ui-Komponenten
- Framer Motion für Animationen
- next-themes für Dark/Light Mode
Projektstruktur
app/
layout.tsx # Root Layout, Fonts, Theme-Init-Script
page.tsx # Hauptseite (alle Sections zusammengesetzt)
globals.css # CSS-Variablen (OKLCH), Tailwind, Fly.io-Farbschema, Timeline-Animationen
impressum/ # Impressum-Seite
datenschutz/ # Datenschutzerklärung
not-found.tsx # 404-Seite
401/ 403/ 500/ 502/ 503/ 504/ # weitere Fehlerseiten
components/
hero.tsx # Hero-Section mit Gradient-Überschrift
about-section.tsx # Motivation, Jamulix-Gesetze, Timeline
timeline-holo.tsx # Hologramm-Illustrationen zur Timeline (SVG)
projects-section.tsx
focus-section.tsx
philosophy-section.tsx
footer.tsx # Footer mit E-Mail (obfuskiert) und Forgejo-Link
header.tsx # Navigation + Theme-Toggle
programmer-graphic.tsx # Foto (statischer Import wegen basePath)
error-page.tsx # Gemeinsames Layout der Fehlerseiten
theme-toggle.tsx
ui/ # shadcn/ui-Basiskomponenten
assets/
Programmierer.png # Foto (statischer Import in programmer-graphic.tsx)
public/
favicon.ico # wird 1:1 nach landingpage/ exportiert
Lokale Entwicklung
npm install
npm run dev
Aufruf im Browser:
- Lokal: http://localhost:3000/landingpage
- Netzwerk: http://192.168.179.124:3000/landingpage (Handy im WLAN)
Port 3000 muss in der Firewall offen sein:
sudo ufw allow 3000/tcp
Build
npm run build
Erzeugt out/, benennt es in landingpage/ um. Dieses Verzeichnis wird deployed.
Persönliche Daten (Impressum / Datenschutz)
Werden nicht im Repository gespeichert, sondern zur Build-Zeit aus .env.local gelesen.
cp .env.local.example .env.local
# .env.local mit echten Daten befüllen
Variablen: OWNER_NAME, OWNER_STREET, OWNER_ZIP_CITY, OWNER_EMAIL,
HOSTER_NAME, HOSTER_STREET, HOSTER_ZIP, HOSTER_CITY, HOSTER_COUNTRY
.env.local ist per .gitignore ausgeschlossen.
Die E-Mail im Footer (footer.tsx) wird als Prop von app/page.tsx übergeben:
<Footer email={process.env.OWNER_EMAIL} />
Deployment
Production (jamulix.de)
./deploy_to_production.sh
- Baut die Seite (
npm run build) - Öffnet eine SSH-Master-Verbindung (Passwort nur einmal eingeben)
- rsync nach
jamulix.de:/var/www/jamulix.de/html/landingpage/ - Setzt Symlink:
/var/www/jamulix.de/html/index.html→landingpage/index.html(nginx folgt dem Link und liefert die Landingpage direkt unterhttps://jamulix.de/aus) - Setzt Symlink
favicon.ico→landingpage/favicon.ico(Browser fragen/favicon.icoab) - Setzt Symlinks
__next.*.txt→landingpage/__next.*.txt(Next.js lädt unter/die RSC-Segmente ohne basePath; ohne die Links gibt es 404 im Netzwerk-Tab) - Kopiert die Fehlerseiten
landingpage/<code>.htmlin den Webroot
Localhost (zum Testen)
./deploy_to_localhost.sh
- rsync nach
/var/www/html/landingpage/ - Symlink:
/var/www/html/index.html→landingpage/index.html - Symlink:
/var/www/html/favicon.ico→landingpage/favicon.ico - Symlinks:
/var/www/html/__next.*.txt→landingpage/__next.*.txt - Kopiert die Fehlerseiten in den Webroot
sudo chown -R www-data:www-data
Warum /landingpage/ als Unterverzeichnis?
basePath: '/landingpage' in next.config.mjs erlaubt es, weitere Projekte
unter jamulix.de/ zu betreiben ohne Konflikte. rsync mit --delete löscht
nur Dateien innerhalb von landingpage/, nicht andere Verzeichnisse im Webroot.
Fehlerseiten
| Code | Quelle | Thema |
|---|---|---|
| 401 | app/401/page.tsx |
Autorisierung erforderlich |
| 403 | app/403/page.tsx |
Zugriff verweigert |
| 404 | app/not-found.tsx |
Seite nicht gefunden |
| 500 | app/500/page.tsx |
Interner Serverfehler |
| 502 | app/502/page.tsx |
Bad Gateway |
| 503 | app/503/page.tsx |
Wartungsarbeiten |
| 504 | app/504/page.tsx |
Gateway Timeout |
Gemeinsames Layout: components/error-page.tsx. Der Build erzeugt
landingpage/<code>.html; die Deploy-Skripte kopieren sie zusätzlich nach
<webroot>/<code>.html. Alle Asset-Pfade sind absolut (/landingpage/_next/…),
daher funktionieren die Kopien im Webroot genauso.
Der nginx-server-Block für jamulix.de (nicht Teil dieses Repos) enthält dafür:
error_page 401 /401.html;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 /500.html;
error_page 502 /502.html;
error_page 503 /503.html;
error_page 504 /504.html;
- Ziel muss ein lokaler Pfad sein, keine vollständige URL (sonst wird daraus ein Redirect).
- Die 401-Seite erscheint erst, wenn der Login-Dialog des Browsers abgebrochen wird.
Design
Fly.io-inspiriertes Farbschema (Variant A+B+C):
- Dark Mode: Tiefes Navy (
oklch(0.10 0.02 260)) + Violet-Akzent (oklch(0.65 0.22 280)) - Light Mode: Warme Papiertöne + Violet-Akzent
- Font: Plus Jakarta Sans (Headlines + Body), JetBrains Mono (Code)
- Hero-Überschrift: Cyan→Violet Gradient im Dark Mode
- Gradient Mesh im Hero-Hintergrund (nur Dark Mode)
Dark/Light Mode wird per localStorage gespeichert. Das Init-Script in
app/layout.tsx verhindert Flash beim Laden.
Timeline-Illustrationen
components/timeline-holo.tsx enthält acht SVG-Szenen, je eine pro
Timeline-Station (Lochkarte, PC, Atari ST, Unix, Linux, WWW, Server, KI).
Stil angelehnt an das Hero-Foto: dunkler Raum, Magenta-Deckenlicht,
Hologramm-Projektor mit Lichtkegel, schwebende Glas-Panels.
- Zuordnung über das Feld
artimtimeline-Array inabout-section.tsx; neue Szene = neuerTimelineArtId+ Eintrag inSCENES. - Desktop: Grafik auf der dem Text gegenüberliegenden Seite; mobil darunter.
- Die Szenen sind in beiden Themes dunkel (wie das Hero-Foto).
- Reines SVG, keine Bilddateien. Filter-/Gradient-IDs sind pro Szene
präfixiert (
holo-<id>-…), da alle acht SVGs auf einer Seite stehen. - Animationen (
tl-blink,tl-pulse,tl-flow,tl-flicker…) stehen inapp/globals.cssund werden beiprefers-reduced-motionabgeschaltet. - Die Lochkarte ist echter Hollerith-Code („C JAMULIX 1976 FORTRAN IV“).
Bilder
components/assets/Programmierer.png wird als statischer Import eingebunden:
import programmiererImg from './assets/Programmierer.png'
// ...
<Image src={programmiererImg} ... />
Grund: next/image mit src="/Programmierer.png" (String) berücksichtigt
basePath nicht korrekt bei statischem Export. Das Bild liegt bewusst nicht in
public/, sonst würde es zusätzlich (1,6 MB, ungenutzt) nach landingpage/ kopiert.