# Funktechnik Schubert Website Eigenständige öffentliche Firmenwebsite für Funktechnik Schubert. Dieses Projekt ist nicht Olympus CRM und koppelt nicht direkt an Olympus. ## Technologie - Next.js 16 App Router - TypeScript strict - Serverseitige API-Routen für Kontakt und Reparaturannahme - Geschützter Admin-Bereich unter `/admin` - Lokale Foundation-Datenablage für Anfragen und Einstellungen - Docker - Nginx/Reverse-Proxy-fähig - SEO Metadata, Sitemap und robots.txt Version: `0.3.0` ## Seiten - `/` Startseite - `/leistungen` - `/funkgeraete-service` - `/reparatur` - `/ueber-uns` - `/kontakt` - `/impressum` - `/datenschutz` - `/admin/login` - `/admin` - `/admin/kontaktanfragen` - `/admin/reparaturanfragen` - `/admin/website` - `/admin/medien` - `/admin/einstellungen` - `/admin/smtp` - `/admin/seo` - `/admin/system` ## Lokale Entwicklung ```bash npm install cp .env.example .env npm run dev ``` Die Website läuft lokal unter: ```text http://127.0.0.1:3010 ``` Für den Admin-Bereich müssen in `.env` mindestens gesetzt sein: ```text ADMIN_EMAIL ADMIN_PASSWORD ADMIN_SESSION_SECRET ``` ## Checks ```bash npm run lint npx next build ``` ## Docker ```bash docker compose build docker compose up -d ``` Service: ```text funktechnik-website ``` Port: ```text 3010:3010 ``` Die Runtime-Daten werden über Docker-Volumes gespeichert: - `funktechnik-data` → `/app/data` - `funktechnik-storage` → `/app/storage` - `funktechnik-next-cache` → `/app/.next/cache` Dadurch sind keine manuellen `chmod`- oder `chown`-Befehle notwendig. ## Umgebung `.env.example` kopieren: ```bash cp .env.example .env ``` Variablen: - `NEXT_PUBLIC_SITE_URL`: öffentliche Basis-URL für SEO, Sitemap und Metadaten - `ADMIN_EMAIL`: Admin-Login E-Mail - `ADMIN_PASSWORD`: Admin-Login Passwort - `ADMIN_SESSION_SECRET`: langer Zufallswert zum Signieren der Admin-Session - `AUTH_COOKIE_SECURE`: `true` in Produktion mit HTTPS, lokal `false` - `OLYMPUS_INTAKE_API_URL`: vorbereitet für spätere serverseitige Olympus-Anbindung - `OLYMPUS_INTAKE_API_TOKEN`: vorbereitet für spätere serverseitige Olympus-Anbindung Die Olympus-Variablen sind nur für eine spätere serverseitige Integration vorbereitet. Sie werden nicht im Browser verwendet. Für lokale Entwicklung kann `AUTH_COOKIE_SECURE=false` bleiben. Produktiv muss HTTPS verwendet und `AUTH_COOKIE_SECURE=true` gesetzt werden. `ADMIN_SESSION_SECRET` muss produktiv ein langer zufälliger Wert sein. ## API-Routen - `POST /api/repair` - `POST /api/contact` - `POST /api/admin/login` - `POST /api/admin/logout` - `PATCH /api/admin/contact/[id]` - `PATCH /api/admin/repair/[id]` - `POST /api/admin/settings` - `POST /api/admin/smtp` - `GET/POST /api/admin/media` - `GET /api/health` Aktuell validieren die Routen serverseitig, geben klare JSON-Antworten zurück und schreiben nur technische Metadaten in Server-Logs. Es werden keine Nachrichteninhalte oder Tokens geloggt. Kontakt- und Reparaturanfragen werden lokal unter `data/*.json` gespeichert und nicht versioniert. ## Admin-Bereich Der geschützte Admin-Bereich ist unter `/admin/login` erreichbar. Er verwendet ein signiertes HttpOnly-Cookie und ist für Desktop und Tablet ausgelegt. Funktionen: - Dashboard mit Kennzahlen - Kontaktanfragen verwalten - Reparaturanfragen verwalten - Website-Inhaltsverwaltung vorbereitet - Firmendaten pflegen - SMTP-Konfiguration speichern und Testmail senden - Medien hochladen - SEO-Übersicht - Systemübersicht Publishing von Website-Inhalten und Olympus-Übernahme sind bewusst noch nicht aktiv gekoppelt. SMTP-Versand fuer Kontakt- und Reparaturanfragen ist serverseitig angebunden, sofern `/admin/smtp` vollstaendig konfiguriert ist. ## Runtime Data Im Repository liegen nur: ```text data/.gitkeep data/contact-inquiries.example.json data/repair-inquiries.example.json ``` Echte Runtime-Dateien werden nicht committed: ```text data/contact-inquiries.json data/repair-inquiries.json data/site-settings.json ``` SMTP-Konfiguration wird unter `storage/config/smtp.json` gespeichert und nicht committed. Das SMTP-Passwort wird nicht im Admin-Formular ausgegeben. Uploads liegen unter `storage/uploads/images/`, werden über `/api/media/[filename]` ausgeliefert und nicht committed. Alte Uploads aus `public/uploads/images` werden beim Start einmalig nach `storage/uploads/images` migriert, falls sie dort noch nicht vorhanden sind. ## Healthcheck ```bash scripts/healthcheck.sh ``` Oder direkt: ```bash curl http://127.0.0.1:3010/api/health ``` Antwort: ```json { "status": "ok", "version": "0.3.0", "storage": "ok", "admin": "configured", "smtp": "configured", "timestamp": "..." } ``` ## SMTP SMTP wird im Adminbereich unter `/admin/smtp` konfiguriert. Die Konfiguration wird persistent unter `storage/config/smtp.json` gespeichert und liegt damit im Docker-Storage-Volume, nicht in `public/`. Pflichtfelder: - SMTP Host - SMTP Port - SMTP Benutzername - SMTP Passwort - Verschlüsselung - Absenderadresse - Empfängeradresse Für Apple Mail/iCloud Mail: ```text Host: smtp.mail.me.com Port: 587 Verschlüsselung: STARTTLS Benutzername: vollständige E-Mail-Adresse Passwort: app-spezifisches Passwort ``` Nicht das normale Apple-ID-Passwort verwenden. In der Apple-ID-Verwaltung ein app-spezifisches Passwort erzeugen und dieses als SMTP-Passwort speichern. Nach dem Speichern kann im Adminbereich eine Testmail gesendet werden. Kontakt- und Reparaturanfragen werden weiterhin lokal gespeichert. Wenn SMTP konfiguriert ist, wird zusaetzlich eine E-Mail an die konfigurierte Empfaengeradresse gesendet. Schlaegt der Mailversand fehl, bleibt die Anfrage gespeichert; der Besucher sieht keine technische Fehlermeldung. Troubleshooting: - Host, Port und Verschlüsselung prüfen - bei Apple Mail STARTTLS und Port 587 verwenden - vollständige E-Mail-Adresse als Benutzername verwenden - app-spezifisches Passwort neu erzeugen - letzte Testmail und letzte Fehlermeldung unter `/admin/smtp` prüfen ## Deployment ```bash scripts/deploy.sh ``` Das Skript führt aus: - `docker compose config` - `docker compose build` - `docker compose up -d` - Healthcheck über `/api/health` Produktiv muss die `.env` auf dem Zielsystem gepflegt werden. Secrets werden nicht ins Repository aufgenommen. ## Update ```bash git pull docker compose config docker compose build docker compose up -d scripts/healthcheck.sh ``` ## Backup ```bash scripts/backup.sh ``` Das Backup enthält `data/` und `storage/`. Die `.env` wird bewusst nicht automatisch gesichert. Sie muss separat sicher abgelegt werden. ## Restore ```bash scripts/restore.sh backups/funktechnik-data-YYYYMMDD-HHMMSS.tar.gz ``` Danach Container neu starten: ```bash docker compose up -d scripts/healthcheck.sh ``` ## Nginx Siehe `nginx.example.conf`. Beispiel-Domain: ```text funktechnik-schubert.de ``` Produktiv HTTPS aktivieren, z. B. mit Certbot: ```bash certbot --nginx -d funktechnik-schubert.de -d www.funktechnik-schubert.de ``` ## Offene manuelle Punkte - TODO: Rechtliche Angaben ergänzen - Spätere Olympus-Reparaturannahme serverseitig anbinden - Finale Domain und HTTPS-Konfiguration setzen