# Next.js Website Starter Neutrale, wiederverwendbare technische Basis für eine neue Website. Das Repository enthält eine produktionsfähige Next.js-Anwendung mit Kalender-API, Bildpipeline, Tests, Containerisierung sowie CI/CD, aber bewusst keine fachlichen Inhalte oder produktiven Daten. ## Technologie-Stack - Node.js 24 und npm - Next.js 16 App Router mit React 19 und TypeScript - Standalone-Serverausgabe für Docker - ICS-Kalender mit `ical.js`, `rrule` und Temporal - Zod für Runtime-Konfiguration - Vitest sowie ein produktionsnaher E2E-Smoke-Test - ESLint, Husky und lint-staged - Sharp für responsive Bildvarianten und Metadatenbereinigung - Docker Compose, Traefik und Trivy - Gitea-Actions-kompatible Workflows unter `.gitea/workflows/` Eine Datenbank und eine Authentifizierung sind nicht Bestandteil dieser Vorlage, weil das technische Ausgangsprojekt keine solchen Systeme verwendet. ## Struktur - `src/app/`: Seiten, Metadaten-, API- und Health-Routen - `src/components/`: wiederverwendbare Server- und Client-Komponenten - `src/server/calendar/`: ICS-Abruf, Parser, Cache, Fehlerbehandlung und Readiness - `src/trip-reports/`: registrierbare TSX-Beitragsmodule; im Starter leer - `src/data/`: neutrale Datenregistries für Downloads, Galerien und Inhaltskarten - `.media-source/`: Originalbilder für die Bildpipeline - `public/`: generierte Bilder, lokale Schriften und öffentliche Dateien - `scripts/`: Build-, Medien-, E2E-, Security- und Deploy-Hilfen - `.gitea/workflows/`: CI, Deployment, Rollback und geplante Rebuilds Die vorhandenen deutschsprachigen Routen bleiben aus Kompatibilitätsgründen erhalten: `/`, `/ueber-uns`, `/informationen`, `/kalender`, `/fahrten`, `/fahrten/[slug]`, `/bilder`, `/impressum` und `/datenschutz`. ## Lokale Installation Voraussetzungen sind Node.js gemäß `.node-version`, npm und für Container-Workflows Docker. ```bash npm ci cp .env.example .env.local npm run dev ``` Die Anwendung ist anschließend standardmäßig unter `http://localhost:3000` erreichbar. Für echte Kalenderdaten muss `CALENDAR_URL` auf eine erreichbare HTTPS-ICS-Datei zeigen. ## Environment-Variablen Alle Werte in `.env.example` sind ungefährliche Beispiele. | Variable | Zweck | | --- | --- | | `APP_NAME` | Öffentlicher Name der Website | | `APP_URL` | Kanonische Basis-URL für SEO, Sitemap, Hostprüfung und CORS-Default | | `COMPANY_NAME` | Betreiber-/Organisationsname | | `CONTACT_EMAIL` | Öffentliche Kontaktadresse | | `CONTACT_PHONE` | Öffentliche Telefonnummer | | `CONTACT_ADDRESS` | Öffentliche Anschrift | | `PRIMARY_DOMAIN` | Hostname für Traefik | | `CALENDAR_URL` | HTTPS-URL des ICS-Kalenders; zur Laufzeit erforderlich | | `CORS_ORIGIN` | Kommagetrennte erlaubte Origins; Standard ist `APP_URL` | | `TRUSTED_PROXIES` | JSON-Liste oder CSV vertrauenswürdiger Proxy-Netze | | `CALENDAR_CACHE_DURATION_MS` | Cache-Dauer für Kalenderdaten | | `CALENDAR_FETCH_TIMEOUT_MS` | Timeout für den ICS-Abruf | | `DEFAULT_CALENDAR_TIMEZONE` | IANA-Zeitzone für schwebende ICS-Zeitangaben | | `MAX_RECURRENCE_WINDOW_MONTHS` | Maximales Vorschaufenster wiederkehrender Termine | | `MAX_ICS_BYTES` | Maximale Größe der Kalenderdatei | | `MAX_OCCURRENCES_PER_EVENT` | Obergrenze je wiederkehrendem Termin | | `ROUTINE_EVENT_TITLES` | Titel regulärer Termine, die nicht hervorgehoben werden | `CALENDAR_URL` ist ein Runtime-Secret und wird nicht als Docker-Build-Argument verwendet. Öffentliche Identitätswerte werden beim Container-Build gesetzt, da Next.js Metadaten statisch erzeugen kann, und zusätzlich zur Laufzeit an den Container übergeben. ## Befehle ```bash npm run dev npm run lint npm run typecheck npm run test npm run build npm run test:e2e ``` `npm run build` bereinigt öffentliche Dateien, erzeugt beziehungsweise entfernt Bildvarianten, entfernt Bildmetadaten, prüft PDF-Metadaten und führt `next build` aus. Der E2E-Test baut die Standalone-Ausgabe, startet eine lokale ICS-Fixture und prüft Seiten, API, ETag sowie Health-Routen. Mit `npm run content:new` kann ein neues TSX-Beitragsmodul samt optionalen Originalbildern angelegt werden. ## Bilder und Dateien Originalbilder gehören in die Unterverzeichnisse von `.media-source/`. `npm run images` erzeugt responsive JPEG-, WebP- und AVIF-Varianten in `public/images/`; `npm run images:prune` entfernt Varianten ohne Quelle. Neue Alt-Texte werden projektspezifisch in der Medienkonfiguration oder im erzeugten Manifest gepflegt. Downloads werden in `public/downloads/` abgelegt und in `src/data/downloads.ts` registriert. Keine personenbezogenen, produktiven oder vertraulichen Dateien committen. ## Docker Für einen lokalen Start über den vorhandenen Traefik-Stack: ```bash CALENDAR_URL=https://example.com/calendar.ics docker compose up --build ``` Das externe Netzwerk heißt standardmäßig `traefik-external` und kann mit `TRAEFIK_NETWORK_NAME` geändert werden. Für einen isolierten Test ohne vorhandenes Traefik-Netz kann die Compose-Datei projektspezifisch überschrieben werden. Das Runtime-Image läuft ohne Root-Rechte, mit read-only Dateisystem, entfernten Linux-Capabilities, Healthcheck und Ressourcenlimits. ## CI/CD und Deployment Die Workflows bleiben vollständig erhalten: - `.gitea/workflows/ci.yml` führt Lint, Tests, Typecheck, Build, E2E sowie Secret- und Schwachstellenscans aus. - `.gitea/workflows/deploy.yml` baut und scannt Images, deployt `dev` und `master`, prüft die laufende Anwendung, unterstützt Rollbacks und führt wöchentliche Rebuilds aus aktuellen Basis-Images aus. CI ist für den lokalen Start nicht technisch erforderlich. Für gemeinsame Branches und Deployments sollte sie aktiv bleiben, weil sie reproduzierbar Build, Tests, Secret-Scans und Container prüft. Auf einem warmen Runner ist für die reine App-Prüfung typischerweise mit etwa 2–5 Minuten zu rechnen; ein kalter Runner mit LFS-, Container- und Trivy-Downloads kann etwa 5–15 Minuten benötigen. Die Security-Jobs laufen parallel. Die tatsächliche Dauer hängt von Runner, Cache, Medienumfang und Netzwerk ab; die Job-Timeouts liegen je nach Aufgabe bei 5–45 Minuten. Vor dem ersten Deployment sind mindestens folgende Repository-Variablen zu setzen: - `CI_RUNNER`, optional `PROD_RUNNER` - `CONTAINER_REGISTRY` - `APP_IMAGE_REPOSITORY` - `APP_NAME`, `COMPANY_NAME`, `CONTACT_EMAIL`, `CONTACT_PHONE`, `CONTACT_ADDRESS` - `DEV_PRIMARY_DOMAIN`, `PROD_PRIMARY_DOMAIN` - optional `DEV_APP_URL`, `PROD_APP_URL`, `DEV_CORS_ORIGIN`, `PROD_CORS_ORIGIN` - optional Stack- und Netzwerkwerte `*_DEPLOY_STACK_NAME`, `*_TRAEFIK_NETWORK_NAME` Benötigte Secrets: - `CALENDAR_URL` - `PACKAGES_USERNAME`, `PACKAGES_TOKEN` - `DEV_TRAEFIK_CERTRESOLVER`, `PROD_TRAEFIK_CERTRESOLVER` Runner benötigen Docker, Zugriff auf das Zielnetzwerk und bei produktiven Deployments Zugriff auf den Zielhost. ## Für ein neues Projekt anpassen 1. Alle Werte aus `.env.example` für die neue Installation festlegen. 2. Texte und Navigation in `src/app/` und `src/components/Header.tsx` ersetzen. 3. Rechtstexte fachlich und rechtlich erstellen lassen. 4. Neues Logo, Farbschema, Schriften und Medien einpflegen. 5. Kalenderquelle und Titel regulärer Termine konfigurieren. 6. Beitrags-, Download- und Galerie-Registries befüllen. 7. Registry, Runner, Domains, Traefik und Secrets in CI/CD konfigurieren. 8. Alle Qualitätsprüfungen und den finalen Secret-Scan ausführen. Die Beispielwerte sind nicht für eine produktive Veröffentlichung bestimmt.