# Statische, datengetriebene Website mit PDF-Download je Eintrag (2026-08-08) Muster für eine statische Status-/Listen-Seite auf einer Subdomain, die aus einem JSON-Datensatz rendert und **pro Eintrag ein PDF** zum Download anbietet (wkhtmltopdf, kein PHP/Python-Backend nötig). Beispiel: Zugverbindungs-Liste mit je-Ziel-PDF (urlaub.perfekt-ohne-en.de). ## Bausteine 1. **Datenquelle**: eine `daten.json` im Webroot (Liste von Objekten mit den anzuzeigenden Feldern + Fahrtzeit + Kategorie + Weg). 2. **`index.html`**: lädt `daten.json` per `fetch`, gruppiert nach Kategorie (z.B. Kernziel / über-7h / Fernzone) und rendert Tabellen mit `⬇ PDF`-Buttons. Slug-Funktion: lowercase + NFD-normalisieren + Umlaute streifen + `[^a-z0-9]`→`-`. 3. **PDF-Generator** (`/usr/local/bin/-pdf.sh`): - Python-Schleife: liest `daten.json`, baut je Eintrag eine temporäre HTML-Datei in `/tmp/-html/`, schreibt nach `/var/www//pdf/.pdf`. - `wkhtmltopdf --quiet --enable-local-file-access "$html" "$pdf"`. - Danach `chown -R www-data:www-data ` (write_file erzeugt root:root). - Glob-Sicherheit bei leeren Verzeichnissen: `rm -rf /tmp/.../*` vorher oder `shopt -s nullglob` (vgl. `set -euo pipefail`). ## Pitfalls - **`write_file` weigert sich auf `/etc/nginx/...`** (sensitiver Systempfad). Ersatz: Inhalt nach `/tmp/` schreiben, dann `cp /tmp/ /etc/nginx/...`. - **PDF nicht roh per `grep` prüfbar**: wkhtmltopdf komprimiert den Text. Statt Text-Suche lieber (a) Größe (KB) + valides `%%EOF`-Ende prüfen, oder (b) PDF im Browser öffnen (Browserbase rendert es im PDF-Viewer) als visueller Beweis. ## Verifikation (end-to-end) ```bash for f in /var/www//pdf/*.pdf; do curl -sk -o /dev/null -w "%{http_code}\n" "https://.perfekt-ohne-en.de/pdf/$(basename "$f")" done # Alle 200 => PDFs OK. Zusätztlich index.html + daten.json auf 200 prüfen. ```