Die offizielle Website für die Devils Rock Trails in Hennweiler, Rheinland-Pfalz.
- Responsive Design für alle Geräte, Burger-Menü unter 1100px
- Statische Seiten auf Cloudflare Workers (Schriften und Icons lokal, kein Tracking)
- Trail-Status nach Saison, manuell überschreibbar über
status.json - Schadensmeldung mit Foto-Upload über einen Cloudflare Worker
- WhatsApp-Zugang mit Cloudflare Turnstile und serverseitiger Prüfung
- Open-Graph-Vorschau,
sitemap.xml,robots.txt, 404-Seite
npm install # einmalig, lädt Font Awesome für die Icon-Sprite
npm run serve # http://localhost:8000Die Seite muss über einen HTTP-Server am Domain-Root laufen (alle Pfade sind absolut, z. B. /css/base.css).
Navigation, Footer und der gemeinsame <head>-Block werden nicht per JavaScript geladen, sondern von scripts/build.mjs direkt in jede Seite geschrieben. Cloudflare Workers liefert die Dateien als Static Assets aus.
components/nav.htmlodercomponents/footer.htmlbearbeiten (oder eine Seite)npm run buildnpm run check && npm testnpm run deployveröffentlicht die gesamte Website inklusive Worker- Geänderte Dateien committen und nach GitHub pushen (Quellcode und CI)
In den Seiten markieren Kommentare die generierten Bereiche – dazwischen nichts von Hand ändern:
<!-- @head --> … <!-- /@head -->
<!-- @nav --> … <!-- /@nav -->
<!-- @footer --> … <!-- /@footer -->Der @head-Block erzeugt Favicons, Stylesheets und Open-Graph-Tags aus <title>, <meta name="description"> und <link rel="canonical"> der Seite. Der Build aktualisiert außerdem sitemap.xml (alle Seiten mit Canonical-URL) und die Icon-Sprite.
Die GitHub Action .github/workflows/check.yml führt npm run check aus und schlägt fehl, wenn ein Build vergessen wurde.
crew/index.html kopieren, Titel, Beschreibung, Canonical und Inhalt anpassen, npm run build ausführen. Soll sie in die Navigation, den Link in components/nav.html ergänzen.
Icons sind Font Awesome 6 Free als SVG-Sprite (assets/icons/icons.svg):
<svg class="icon" aria-hidden="true"><use href="/assets/icons/icons.svg#bicycle"></use></svg>Den Namen von fontawesome.com/search verwenden und npm run build ausführen. Der Build nimmt nur Icons auf, deren vollständige Referenz (icons.svg#name) wörtlich in einer HTML- oder JS-Datei steht.
Ohne Eingriff richtet sich der Status nach der Saison:
- Geöffnet: 1. April – 31. Oktober
- Geschlossen: 1. November – 31. März
Für kurzfristige Sperrungen oder Freigaben status.json bearbeiten (geht auch direkt im GitHub-Webinterface, ohne Build):
{
"mode": "closed",
"message": "Sturmschäden auf dem XC-Trail – bis auf Weiteres gesperrt.",
"updated": "2026-10-13"
}mode:"auto"(Saison),"open"oder"closed"message: optionaler Text, sonst Standardtextupdated: optionales Datum, wird als „Stand: …“ angezeigt
Nach dem Commit dauert es durch Caching bis zu ca. 10 Minuten, bis alle Besucher den neuen Status sehen. Zurück zur Saison-Logik: "mode": "auto".
Das Formular auf /schaden-melden sendet an https://www.devilsrock.de/api/schaden-melden. Diese Route und die statische Website bedient der Worker devilsrock-forms in worker/. Der Worker schickt die Meldung inkl. bis zu 3 Fotos per Cloudflare Email Sending an REPORT_TO und speichert nichts.
- Absender:
trails@send.devilsrock.de. Die Subdomainsend.devilsrock.deist für Email Sending eingerichtet. Der Empfang auf der Hauptdomain läuft seit dem 19.10.2026 über Cloudflare Email Routing; die bisherigen iCloud-MX/SPF-Einträge wurden ersetzt. Weiterleitungen benötigen bestätigte Zieladressen. Die Weiterleitungen fürdom@,julian@undflo@sind eingerichtet; Flos Zieladresse wurde am 21.10.2026 bestätigt und seine Regel aktiviert. Der Catch-all ist deaktiviert. - Empfänger und Absender stehen als
varsinworker/wrangler.jsonc. - Spam-Schutz: Honeypot-Feld, Origin-Prüfung, max. 5 Meldungen pro Minute und IP.
- Fotos werden im Browser auf max. 1600px verkleinert (entfernt auch GPS-Metadaten). Eine E-Mail darf inkl. Anhängen höchstens 5 MiB groß sein; zu große Fotos werden weggelassen und in der Mail aufgelistet.
- Ohne JavaScript funktioniert das Formular auch: der Worker leitet zurück auf
/schaden-melden/#gesendetbzw.#fehler.
cd worker
wrangler dev # lokal testen, E-Mails werden nur simuliert
cd .. && npm run deploy # gesamte Website veröffentlichen
wrangler tail # Live-LogsEinmalige Einrichtung (erledigt am 13.10.2026): wrangler email sending enable send.devilsrock.de.
Die Website wird vollständig durch Cloudflare Workers Static Assets ausgeliefert. www.devilsrock.de und devilsrock.de sind Custom Domains des Workers; die Hauptdomain leitet auf www weiter. GitHub ist nur Quellcode-Repository und führt die CI-Prüfungen aus. Ein Push allein veröffentlicht keine Website; zum Deploy npm run deploy mit angemeldetem Wrangler ausführen.
scripts/package-site.mjs kopiert nur ausdrücklich freigegebene Website-Dateien nach dist/. Repository-Dateien, Worker-Quellcode, Tests und Secrets werden niemals als Assets veröffentlicht. worker/wrangler.jsonc enthält die Deployment-Konfiguration. Der Worker behält seinen vorhandenen Namen devilsrock-forms, damit die E-Mail-Bindung und Secrets erhalten bleiben.
Alle Website-Links führen nach /community/. Nur diese Seite lädt Cloudflare Turnstile (Managed-Modus, ohne Pre-Clearance). Der öffentliche Sitekey kommt von GET /api/community. Das Formular sendet das Einmaltoken an POST /api/community; der Worker prüft es mit Cloudflares Siteverify, einschließlich Hostname und Aktion community, und leitet erst danach zu WhatsApp weiter.
- Cloudflare-Secrets:
TURNSTILE_SECRET,WHATSAPP_INVITE_URL. Den Einladungslink niemals in HTML, JavaScript, README oder öffentliche Konfiguration schreiben. - Neuen Einladungslink setzen:
wrangler secret put WHATSAPP_INVITE_URL --config worker/wrangler.jsoncund den Wert interaktiv eingeben. - Maximal 10 Versuche pro Minute/IP; keine Freigabe bei fehlender Konfiguration, ungültigem Token oder Ausfall von Cloudflare.
- API-Antworten und Weiterleitung sind nicht cachebar; der Einladungslink wird nicht geloggt.
npm testprüft unter anderem Tokenfehler, Wiederverwendung, falschen Hostnamen/Aktion, Rate Limit und erfolgreiche Weiterleitung.- Ein einmal freigegebener WhatsApp-Link kann weitergegeben werden. Das Captcha schützt den Zugang über die Website, nicht den direkten Beitritt mit bereits bekanntem Link.
devilsrock.de/
├── index.html # Startseite
├── 404.html # Fehlerseite (Cloudflare)
├── community/index.html # Captcha → /api/community
├── crew/index.html # /crew – Mitglied werden
├── datenschutz/index.html # /datenschutz
├── nutzungsbestimmungen/index.html
├── schaden-melden/index.html # Formular → Worker
├── spenden/index.html # Weiterleitung zu PayPal
├── pages/design.html # Design Guidelines
├── pages/nutzungsbestimmungen.html # alte URL, leitet weiter
├── status.json # Trail-Status-Override
├── sitemap.xml, robots.txt, site.webmanifest
├── components/ # Quellen für @nav / @footer
├── css/ # fonts, base, components, layout, pages
├── js/
│ ├── site.js # Burger-Menü, Navbar, Footer-Jahr
│ ├── animations.js # Scroll-Animationen
│ ├── trail-status.js # Trail-Status (nur Startseite)
│ └── damage-form.js # Schadensmeldung
├── scripts/build.mjs # statischer Build (s. o.)
├── worker/ # Cloudflare Worker und Sicherheitstests
├── dist/ # generierte, veröffentlichbare Dateien (ignoriert)
└── assets/ # docs, fonts, gpx, icons, images, logo, team
- Facebook: Devils Rock Trails
- WhatsApp: Community
- Instagram: @devils_rock_trail_hennweiler
- Julian Fritz - Vorsitzender Radsport (julian@devilsrock.de)
- Florian Bauer - Jugendtrainer Radsport (flo@devilsrock.de)
- Dominik Ottenbreit - Koordination Trailbau (dom@devilsrock.de)
Devils Rock Trails - Mountainbike Trails in Hennweiler, Rheinland-Pfalz