# ToolCTRL — Website Mehrseitige Website im Visitenkarten-Stil: Landing Page mit Lead-Formular, TechDay-2026-Seite, AI-GameJam-Seite mit Datei-Upload sowie Impressum und Datenschutz. Monochrom (weiß / schwarz), an die ToolCTRL Brand Identity angelehnt. Der Server läuft ohne npm-Pakete (nur Node-Standardbibliothek). ## Starten ```bash node server.js ``` Der Server sucht automatisch einen freien Port (zuerst `4317`) und gibt lokale und Netzwerk-URL aus. Stoppen mit `Strg + C`. Voraussetzung: Node.js (getestet mit v26). ## Aufbau ``` public/ statische Website index.html Landing Page + Kontaktformular techday.html TechDay Bruchsal 2026 gamejam.html AI GameJam (eigenes Styling, Spiel-Upload) impressum.html Impressum datenschutz.html Datenschutzerklärung styles.css Designsystem script.js Formular-Logik & Mobile-Navigation assets/ Logos, Emblem, Favicon, Icons, Schriften, Mockups server.js abhängigkeitsfreier Node-HTTP-Server + API leads/ gesammelte Kontaktanfragen (wird automatisch angelegt) gamejam/ GameJam-Einreichungen, Metadaten (wird automatisch angelegt) ``` `leads/`, `gamejam/` und hochgeladene Spiele sind per `.gitignore` vom Repo ausgeschlossen. ## Leads `POST /api/lead` (JSON, Pflichtfelder `name`, `email`, `nachricht`). Jede Anfrage landet sofort lokal in `leads/leads.csv` **und** `leads.ndjson` — so geht auf der Messe nichts verloren. Ein Honeypot-Feld fängt einfache Bots ab. ## GameJam-Upload & Virenscan (ClamAV) `POST /api/gamejam/upload` nimmt eine `.html`-Datei entgegen (max. 5 MB). **Jede hochgeladene Datei wird vor dem Speichern per ClamAV auf Viren geprüft.** Befund → Ablehnung; ist der Scanner nicht erreichbar, wird der Upload ebenfalls abgelehnt (fail-closed, kein ungeprüftes Speichern). Der Server spricht den ClamAV-Daemon `clamd` direkt über sein Socket-Protokoll an — keine zusätzliche Abhängigkeit. Voraussetzung: ClamAV ist installiert und `clamd` läuft. Beim Start meldet der Server `Virenscan: aktiv` bzw. eine Warnung, falls `clamd` nicht erreichbar ist. ### ClamAV einrichten — macOS ```bash brew install clamav cd "$(brew --prefix)/etc/clamav" cp freshclam.conf.sample freshclam.conf cp clamd.conf.sample clamd.conf # In BEIDEN Dateien die Zeile "Example" entfernen oder auskommentieren. # In clamd.conf zusätzlich diese zwei Zeilen aktivieren (Raute entfernen): # TCPSocket 3310 # TCPAddr 127.0.0.1 freshclam # Virendefinitionen laden (einmalig) clamd # Daemon starten ``` ### ClamAV einrichten — Linux (Debian/Ubuntu) ```bash sudo apt install clamav clamav-daemon # In /etc/clamav/clamd.conf: TCPSocket 3310 und TCPAddr 127.0.0.1 setzen sudo systemctl restart clamav-daemon ``` ### Konfiguration Host/Port und An/Aus stehen in `server.js` im Objekt `CLAMAV`. Mit `enabled: false` läuft der Upload ohne Virenscan (nur für lokale Tests ohne ClamAV gedacht). Per Environment kann der Runtime-Betrieb konfiguriert werden: ```bash PORT=3000 HOST=0.0.0.0 DATA_DIR=/app/data CLAMAV_HOST=127.0.0.1 CLAMAV_PORT=3310 CLAMAV_ENABLED=true APP_REVISION= ``` `/healthz` ist die leichte Liveness-Probe für Container und Coolify. `/readyz` prüft zusätzlich Schreibzugriff auf die Datenverzeichnisse und, falls aktiv, die Erreichbarkeit von ClamAV. ### Funktion testen Eine Datei mit der EICAR-Testsignatur hochladen — `clamd` meldet dann `Eicar-Test-Signature FOUND`, der Upload wird abgelehnt. ## Hinweis für die Messe Für den QR-Code am Stand muss der Rechner im selben WLAN erreichbar sein. Soll die Seite öffentlich laufen, hinter einen Reverse-Proxy mit HTTPS setzen oder bei einem Hoster bereitstellen — `tool-ctrl.de`. ## Deployment Deployment folgt dem Gitea-Infra-Standard aus `toolctrl-labs/infra`: 1. Push auf `main` triggert `.gitea/workflows/deploy.yml`. 2. Gitea Actions baut das Docker-Image und pusht es nach `git.hg-int.dev/toolctrl-labs/toolctrl-website`. 3. Tags: kurzer Commit-SHA und `main`. 4. Coolify-App `toolctrl-website` (`ocwtt7rd2zijtlszgua005k9`) zieht `:main` auf der Marketing-VM und startet neu. Die Coolify-App läuft im Projekt `Marketing`, Environment `production`, Server `marketing-vm`, Port `3000`, mit persistentem Storage auf `/app/data`.