2026-04-26 04:17:46 +02:00
|
|
|
# jamulix.de — Landing Page
|
|
|
|
|
|
|
|
|
|
Next.js 16 Landing Page für [jamulix.de](https://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)
|
2026-10-07 19:51:14 +02:00
|
|
|
globals.css # CSS-Variablen (OKLCH), Tailwind, Fly.io-Farbschema, Timeline-Animationen
|
2026-04-26 04:17:46 +02:00
|
|
|
impressum/ # Impressum-Seite
|
|
|
|
|
datenschutz/ # Datenschutzerklärung
|
2026-10-07 19:51:14 +02:00
|
|
|
not-found.tsx # 404-Seite
|
|
|
|
|
401/ 403/ 500/ 502/ 503/ 504/ # weitere Fehlerseiten
|
2026-04-26 04:17:46 +02:00
|
|
|
components/
|
|
|
|
|
hero.tsx # Hero-Section mit Gradient-Überschrift
|
2026-10-07 19:51:14 +02:00
|
|
|
about-section.tsx # Motivation, Jamulix-Gesetze, Timeline
|
|
|
|
|
timeline-holo.tsx # Hologramm-Illustrationen zur Timeline (SVG)
|
2026-04-26 04:17:46 +02:00
|
|
|
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)
|
2026-10-07 19:51:14 +02:00
|
|
|
error-page.tsx # Gemeinsames Layout der Fehlerseiten
|
2026-04-26 04:17:46 +02:00
|
|
|
theme-toggle.tsx
|
|
|
|
|
ui/ # shadcn/ui-Basiskomponenten
|
|
|
|
|
public/
|
|
|
|
|
Programmierer.png # Foto (statischer Import in programmer-graphic.tsx)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Lokale Entwicklung
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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:
|
|
|
|
|
```tsx
|
|
|
|
|
<Footer email={process.env.OWNER_EMAIL} />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Deployment
|
|
|
|
|
|
|
|
|
|
### Production (jamulix.de)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
./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/`
|
2026-10-07 20:07:24 +02:00
|
|
|
- Setzt Symlink: `/var/www/jamulix.de/html/index.html` → `landingpage/index.html`
|
|
|
|
|
(nginx folgt dem Link und liefert die Landingpage direkt unter `https://jamulix.de/` aus)
|
2026-10-07 09:55:02 +02:00
|
|
|
- Kopiert die Fehlerseiten `landingpage/<code>.html` in den Webroot
|
2026-04-26 04:17:46 +02:00
|
|
|
|
|
|
|
|
### Localhost (zum Testen)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
./deploy_to_localhost.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- rsync nach `/var/www/html/landingpage/`
|
2026-10-07 20:07:24 +02:00
|
|
|
- Symlink: `/var/www/html/index.html` → `landingpage/index.html`
|
2026-10-07 09:55:02 +02:00
|
|
|
- Kopiert die Fehlerseiten in den Webroot
|
2026-04-26 04:17:46 +02:00
|
|
|
- `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.
|
|
|
|
|
|
2026-10-07 09:55:02 +02:00
|
|
|
### 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.
|
|
|
|
|
|
2026-10-07 20:07:24 +02:00
|
|
|
Der nginx-`server`-Block für jamulix.de (nicht Teil dieses Repos) enthält dafür:
|
2026-10-07 09:55:02 +02:00
|
|
|
|
2026-10-07 18:21:48 +02:00
|
|
|
```nginx
|
|
|
|
|
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;
|
2026-10-07 09:55:02 +02:00
|
|
|
```
|
|
|
|
|
|
2026-10-07 18:21:48 +02:00
|
|
|
- Ziel muss ein lokaler Pfad sein, keine vollständige URL (sonst wird daraus ein Redirect).
|
2026-10-07 09:55:02 +02:00
|
|
|
- Die 401-Seite erscheint erst, wenn der Login-Dialog des Browsers abgebrochen wird.
|
|
|
|
|
|
2026-04-26 04:17:46 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 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.
|
|
|
|
|
|
2026-10-07 19:51:14 +02:00
|
|
|
### 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 `art` im `timeline`-Array in `about-section.tsx`;
|
|
|
|
|
neue Szene = neuer `TimelineArtId` + Eintrag in `SCENES`.
|
|
|
|
|
- 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 in
|
|
|
|
|
`app/globals.css` und werden bei `prefers-reduced-motion` abgeschaltet.
|
|
|
|
|
- Die Lochkarte ist echter Hollerith-Code („C JAMULIX 1976 FORTRAN IV“).
|
|
|
|
|
|
2026-04-26 04:17:46 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Bilder
|
|
|
|
|
|
|
|
|
|
`public/Programmierer.png` muss als **statischer Import** eingebunden werden:
|
|
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
import programmiererImg from '../public/Programmierer.png'
|
|
|
|
|
// ...
|
|
|
|
|
<Image src={programmiererImg} ... />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Grund: `next/image` mit `src="/Programmierer.png"` (String) berücksichtigt
|
|
|
|
|
`basePath` nicht korrekt bei statischem Export.
|