330 lines
8.8 KiB
Markdown
330 lines
8.8 KiB
Markdown
# 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 Storage-Datenablage für Anfragen, Einstellungen, Medien und Website-Inhalte
|
|
- Docker
|
|
- Nginx/Reverse-Proxy-fähig
|
|
- SEO Metadata, Sitemap und robots.txt
|
|
|
|
Version: `0.4.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/PUT /api/admin/content`
|
|
- `GET /api/content/settings`
|
|
- `GET /api/media/[filename]`
|
|
- `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-Inhalte pflegen und sofort veröffentlichen
|
|
- Firmendaten pflegen
|
|
- SMTP-Konfiguration speichern und Testmail senden
|
|
- Medien hochladen
|
|
- SEO-Übersicht
|
|
- Systemübersicht
|
|
|
|
Website-Inhalte werden unter `/admin/website` gepflegt und beim Speichern sofort auf der öffentlichen Website wirksam. Die Content-Architektur ist bewusst über einen zentralen `ContentService` gekapselt, damit später Olympus CMS oder PostgreSQL als Backend angebunden werden können. 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.
|
|
|
|
Website-Inhalte liegen unter `storage/content/` und werden nicht committed:
|
|
|
|
```text
|
|
storage/content/home.json
|
|
storage/content/services.json
|
|
storage/content/radio-service.json
|
|
storage/content/about.json
|
|
storage/content/contact.json
|
|
storage/content/settings.json
|
|
storage/content/backups/
|
|
```
|
|
|
|
Jede Seite besitzt eine eigene JSON-Datei. React-Komponenten lesen diese Dateien nicht direkt, sondern ausschließlich über `lib/content/service.ts`. Vor jedem Speichern erzeugt der Service eine Backup-Datei unter `storage/content/backups/` und behält pro Dokument die letzten 20 Versionen. Änderungen benötigen keinen Neustart und keinen Docker-Build.
|
|
|
|
Bearbeitbar sind aktuell:
|
|
|
|
- Startseite mit Hero, Call-to-Actions, Featureboxen, Leistungsboxen und Kundenversprechen
|
|
- Leistungen mit beliebig vielen sortierbaren und ein-/ausblendbaren Einträgen
|
|
- Funkgeräte-Service mit Einleitung, Marken, Fehlerbildern, Ablauf, Messmöglichkeiten, Abgleich und Reparaturtexten
|
|
- Über Uns mit Firmenbeschreibung, Werkstattbeschreibung und Philosophie
|
|
- Kontakt mit Kontaktinformationen, Öffnungszeiten, Maps-Link und Seitentexten
|
|
- Footer, Logo, Copyright, Header-CTA und globale SEO-Einstellungen
|
|
- SEO pro Seite inklusive Meta Title, Meta Description, Keywords, OpenGraph und Social Image
|
|
|
|
Bilder für Logo und Social Image werden aus dem Medienbestand ausgewählt. Neue Uploads bleiben im privaten Storage und werden über `/api/media/[filename]` ausgeliefert.
|
|
|
|
## Healthcheck
|
|
|
|
```bash
|
|
scripts/healthcheck.sh
|
|
```
|
|
|
|
Oder direkt:
|
|
|
|
```bash
|
|
curl http://127.0.0.1:3010/api/health
|
|
```
|
|
|
|
Antwort:
|
|
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"version": "0.4.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
|