Back to Browse

Eichmannimmobilien MCP Server

Developer ToolsModerate7.0MCP RegistryRemote
Free

Server data from the Official MCP Registry

Live MCP for Immobilien Eichmann listings (Konstanz). Tools: search_listings, get_listing.

About

Live MCP for Immobilien Eichmann listings (Konstanz). Tools: search_listings, get_listing.

Remote endpoints: streamable-http: https://immobilieneichmann.de/mcp

Security Report

7.0
Moderate7.0Low Risk

Valid MCP server (1 strong, 0 medium validity signals). 3 known CVEs in dependencies (0 critical, 3 high severity) Imported from the Official MCP Registry. 1 finding(s) downgraded by scanner intelligence.

2 tools verified · Open access · 4 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

file_system

Check that this permission is expected for this type of plugin.

HTTP Network Access

Connects to external APIs or services over the internet.

env_vars

Check that this permission is expected for this type of plugin.

How to Connect

Remote Plugin

No local installation needed. Your AI client connects to the remote endpoint directly.

Add this to your MCP configuration to connect:

{
  "mcpServers": {
    "de-immobilieneichmann-listings": {
      "url": "https://immobilieneichmann.de/mcp"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

Listings SoT (SQLite)

  • Source of truth: SQLite on the droplet at /var/lib/eichmann/listings.db (not in git, not in the web root).
  • Origins: immowelt (inbound sync only) and eigen (own listings via unified /admin/#eigen).
  • Immowelt sync upserts/deactivates only origin=immowelt and never deletes origin=eigen.
  • Immowelt profile/account is read-only (no writes).
  • data/listings.json is an export/backup with "sot": "sqlite", not the SoT.
  • Publish: node scripts/publish-from-db.mjs writes JSON export + HTML from the DB.
  • Admin: https://immobilieneichmann.de/admin/ — Immowelt visibility + Eigen CRUD. Auth = email + password → HttpOnly cookie via /admin/api/ (localhost Node). No GitHub PAT.
  • Badge for eigen listings: „nur bei uns“.
  • Node on droplet: 20.x + better-sqlite3. App tooling: /var/lib/eichmann/app. Admin API unit: eichmann-admin-api.service.
  • Stabschef note: docs/STABSCHEF-admin-unified-2026-09-25.md

Immobilien Eichmann – technische Architektur und Betrieb

Statische Website für Immobilien Eichmann / Helmut Eichmann in Konstanz.

  • Produktion: https://immobilieneichmann.de/
  • Repository: ChristianHohlfeld/eichmannimmobilien
  • Branch für Produktion: main
  • Hosting: GitHub Pages
  • Formular-Backend: eigener, getrennter Gateway-Dienst auf dem bestehenden VPS
  • eigene Datenbank: keine
  • produktiver Node-Prozess für Formulare: dp-forms.service auf forms.digitalisierungsplanung.de

Stand dieser Dokumentation: 20.09.2026.


1. Architektur in einem Satz

Die öffentliche Website selbst besteht aus statischen HTML-, CSS-, JavaScript-, JSON- und Bilddateien auf GitHub Pages. Kontakt- und Exposé-Anfragen gehen an einen eigenen, technisch getrennten Formular-Gateway-Dienst unter forms.digitalisierungsplanung.de; weitere dynamische Abläufe laufen im Browser, über GitHub API / GitHub Actions oder über klar benannte Dienste wie Immowelt, Amazon SES und – nach Consent – Google Analytics.

Besucher
  |
  v
GitHub Pages / immobilieneichmann.de
  |
  +--> HTML + CSS + Vanilla JavaScript
  |
  +--> Kontakt-/Exposé-Anfrage
  |      Browser -> forms.digitalisierungsplanung.de -> Amazon SES -> info@immobilien-eichmann.com
  |
  +--> Analytics nur nach Consent
  |      Browser -> Google Analytics 4
  |
  +--> Externe Links
         -> Immowelt / Google Maps

Admin-Browser
  |
  +--> GitHub REST API mit Sitzungs-PAT
  |      -> data/listings.json
  |      -> assets/listings/*
  |
  +--> repository_dispatch / workflow_dispatch
         -> GitHub Actions
         -> Renderer
         -> generierte HTML-Seiten / Sitemap
         -> Commit auf main
         -> GitHub Pages Deployment

GitHub Actions Cron
  |
  +--> Playwright -> öffentliches Immowelt-Profil
         -> Merge in data/listings.json
         -> Bilder lokal spiegeln
         -> HTML / Sitemap neu rendern

Die Website-Dateien selbst laufen weiterhin ohne Application Server auf GitHub Pages. Für Formulare existiert bewusst ein kleiner separater Node-Dienst auf dem vorhandenen digitalisierungsplanung.de-VPS. Er hat eigene Runtime/Env, keine gemeinsame Produkt-DB oder Session und speichert keine Formularinhalte in einer eigenen Datenbank. GitHub-Actions-Runner bleiben kurzlebige Build-/Automationsmaschinen.


2. Frontend-Stack

Die Website ist bewusst ohne Frontend-Framework gebaut.

EbeneTechnik
MarkupHTML5
Stylingeine eigene CSS-Codebasis in css/styles.css
BrowserlogikVanilla JavaScript
Build-Bundlerkeiner
React/Vue/Angularkeiner
jQuerykeiner
CSS-Frameworkkeines
Webfontskeine externen Google Fonts; System-Font-Stacks
BilderJPG, WebP, PNG, SVG
SEOstatische Meta-Tags, Open Graph, Twitter Cards, JSON-LD, Sitemap
DeploymentGitHub Pages aus main

Die Browserlogik liegt hauptsächlich in:

  • js/main.js – Navigation, Kontakt-/Exposé-Formulare, Flyer, Gallery, Lightbox, URL-Prefills
  • js/cookie-consent.js – Consent-Speicherung und kontrolliertes Laden von Analytics
  • js/analytics.js – Google Analytics 4 / gtag.js, Measurement ID G-QVRRBPYNVM

Für Objektseiten unter /objekt/ wird über window.__eichmannJsBase sichergestellt, dass die gemeinsamen JavaScript-Dateien mit dem korrekten relativen Pfad geladen werden.


3. Node-/Build-Stack

Dieses Repository benötigt Node lokal und in GitHub Actions für Generierung, Scraping, Bildverarbeitung und Tests. Der separate Formular-Gateway läuft serverseitig als Node-Dienst im Repository ChristianHohlfeld/digitalisierungsplanung.de; er ist nicht Teil des statischen GitHub-Pages-Deployments dieses Repositories.

package.json verlangt Node >= 20.

Direkte Dependencies:

PaketVerwendungaktuell aufgelöst
playwrightBrowser-Automation: Immowelt-Import und Browser-Regressionsprüfungen1.63.0
sharpBildkonvertierung, Größenanpassung, Social-Share-Bilder0.33.5

Wichtige Befehle:

npm ci

npm run sync-immowelt
npm run sync-immowelt:render

npm run test:legal
npm run test:expose-form
npm run test:layout
npm run test:logo
npm run test:share
npm run test:jsonld
npm test

Für Playwright lokal:

npx playwright install chromium

4. Hosting, Domain und Serverfrage

Haben wir einen eigenen Server?

Für die statische Website nein; für Formulare ja.

GitHub Pages liefert die Website aus. Kontakt- und Exposé-POSTs gehen an den vorhandenen VPS unter forms.digitalisierungsplanung.de. Dort terminiert Nginx TLS und routet ausschließlich die Formularpfade an dp-forms.service auf Loopback-Port 8791. Es gibt weiterhin keine eigene Formular-Datenbank.

Wo liegt die Website?

Die Dateien liegen im GitHub-Repository und werden von GitHub Pages statisch ausgeliefert.

Die Datei:

CNAME

enthält:

immobilieneichmann.de

Damit ist die Custom Domain der GitHub-Pages-Site zugeordnet.

Die DNS-Konfiguration selbst liegt außerhalb dieses Repositories beim jeweiligen DNS-Provider. Das Repository enthält keine Zugangsdaten zum DNS-Provider.

Was passiert bei einem normalen Seitenaufruf?

  1. DNS löst immobilieneichmann.de auf GitHub Pages auf.
  2. GitHub Pages liefert fertige statische Dateien aus.
  3. Der Browser führt cookie-consent.js und main.js aus.
  4. Nur beim Absenden eines Kontakt-/Exposé-Formulars wird forms.digitalisierungsplanung.de aufgerufen.
  5. Drittanbieter werden nur für die jeweils beschriebenen Funktionen aufgerufen.

5. Verzeichnisstruktur

/
├── .github/workflows/       GitHub-Actions-Automation
├── admin/                   statisches Exposé-Admin
├── assets/
│   ├── flyer/               Flyerbilder
│   ├── listings/            lokal gespeicherte Objektbilder
│   ├── logo*                Marken-/Header-Assets
│   └── share-card*          Social-Preview-Bilder
├── css/styles.css           gesamtes Public Styling
├── data/listings.json       generierter lokaler Spiegel der Immowelt-Objektdaten
├── js/
│   ├── main.js
│   ├── cookie-consent.js
│   └── analytics.js
├── objekt/*.html            generierte Objekt-/Exposé-Seiten
├── partials/                generierte HTML-Fragmente
├── scripts/                 Generatoren, Importer und Tests
├── index.html               Startseite
├── kontakt.html             allgemeines Kontaktformular
├── impressum.html
├── datenschutz.html
├── widerrufsbelehrung.html
├── vertrag-widerrufen.html
├── sitemap.xml
├── robots.txt
├── llms.txt
├── CNAME
├── .nojekyll
├── package.json
└── package-lock.json

6. Single Source of Truth für Immobilien

Die fachliche Single Source of Truth ist Immowelt. Helmut pflegt dort Titel, Preis, Status, Referenznummern und Objektdaten.

data/listings.json ist ausschließlich der lokale, generierte Spiegel für Rendering und Website-Betrieb. Als lokale Abweichung ist nur site_hidden erlaubt: damit kann ein Immowelt-Objekt auf der eigenen Website ausgeblendet werden, ohne Immowelt zu verändern.

Top-Level-Struktur:

{
  "sot": "local",
  "source": "...",
  "immowelt_profile": "...",
  "scraped_at": "...",
  "listing_count": 13,
  "listings": []
}

Typische Felder eines Listings:

  • id
  • slug
  • local_url
  • title
  • price
  • location
  • rooms
  • living_area
  • plot_area
  • type
  • status
  • short_description
  • description
  • facts
  • expose_url
  • main_image_url
  • images
  • floor_plans
  • image_base
  • gallery_bases
  • floor_plan_bases
  • source
  • immowelt_id
  • sync_policy
  • missing_on_immowelt
  • active – steuert, ob ein Objekt öffentlich erscheint; false behält es intern, veröffentlicht es aber nicht
  • detail_page – false erlaubt einen öffentlichen Kontakt-Teaser ohne erfundene Exposé-Inhalte; nur true erzeugt Detailseite und Sitemap-Eintrag
  • optional manual_overrides

Die HTML-Seiten unter objekt/, die Karten auf Start-/Projektseite und die Objekt-URLs in sitemap.xml werden daraus erzeugt.


7. Immowelt-Import

Immowelt ist nur eine externe Inbound-Quelle.

Das Immowelt-Konto wird von dieser Codebasis niemals beschrieben.

Quelle:

https://www.immowelt.de/profil/3b18336c6a2e401da38e9cc20268270d

Importer:

scripts/sync-immowelt.mjs

Workflow:

.github/workflows/sync-immowelt.yml

Ablauf eines normalen Full-Syncs

  1. GitHub Actions startet einen kurzlebigen Ubuntu-Runner.
  2. Node 20 und Dependencies werden installiert.
  3. Playwright Chromium öffnet das öffentliche Immowelt-Profil.
  4. Öffentliche Objektinformationen werden gelesen.
  5. Soweit möglich werden Detailseiten für Beschreibung, Bilder, Grundrisse und Fakten angereichert.
  6. Neue Daten werden gegen data/listings.json gemerged.
  7. Objektbilder werden heruntergeladen.
  8. Sharp erzeugt lokale JPG-/WebP-Versionen.
  9. JSON wird aktualisiert.
  10. Karten, Exposé-Seiten und Sitemap werden neu gerendert.
  11. Geänderte Dateien werden auf main committed.
  12. GitHub Pages deployed den neuen Stand.

Zeitplan

Der Workflow läuft regulär:

0 */3 * * *

also alle drei Stunden nach UTC.

Zusätzlich kann er manuell gestartet werden.

Wenn scripts/sync-immowelt.mjs oder der Workflow selbst geändert wird, wird auf Push nur aus dem vorhandenen kanonischen JSON gerendert, damit Templateänderungen ohne erneuten Live-Scrape sofort auf alle Objektseiten kommen.

DataDome / Bot-Schutz

Immowelt kann automatisierte Browser mit DataDome/Captcha blockieren.

Darum ist der Import bewusst als Soft-Fail gebaut:

  • bei Scrape-Fehlern bleibt das zuletzt gültige JSON erhalten
  • die öffentliche Site wird nicht leergeräumt
  • kein Login und kein Captcha-Bypass
  • das Immowelt-Konto wird nicht verändert

Merge-Regeln

Standard:

sync_policy = independent

Bedeutung:

  • neue Immowelt-ID -> kann lokal ergänzt werden
  • vorhandene Objekte -> nur nicht manuell geschützte Felder werden aktualisiert
  • manual_overrides[field] = true schützt einen Wert vor Immowelt-Überschreiben
  • source: local ist lokal autoritativ
  • auf Immowelt verschwundene Objekte werden standardmäßig nicht automatisch gelöscht
  • stattdessen missing_on_immowelt: true
  • nur sync_policy: mirror erlaubt Auto-Entfernung eines verknüpften, dort verschwundenen Objekts

8. Bilder

Objektbilder liegen persistent im Git-Repository:

assets/listings/

Der Importer erzeugt in der Regel:

  • JPG für breite Kompatibilität
  • WebP für kleinere Übertragung
  • separate Gallery-Dateien
  • separate Grundriss-Dateien

Sharp übernimmt die Konvertierung.

Nicht mehr referenzierte, vom System verwaltete Objektbilder werden beim Rendern/Sync als Orphans erkannt und aufgeräumt.

Admin-Uploads werden zuerst per GitHub Contents API als Datei committed und danach in data/listings.json referenziert. Das ist ein zweistufiger Vorgang, keine Datenbanktransaktion.


9. Exposé-Anfrageflow

Referenz: bi-bodenseeimmo

Der öffentliche Exposé-Flow von:

https://www.bi-bodenseeimmo.de/

wurde am 20.09.2026 gegen aktuelle Objektseiten geprüft.

Die sichtbaren Personen-/Adressfelder des Eichmann-Exposé-Flows entsprechen diesem Referenzflow:

  1. Anrede* – Select
  2. Vorname*
  3. Name*
  4. Straße und Hausnummer*
  5. PLZ*
  6. Ort*
  7. Telefonnummer – optional
  8. E-Mail-Adresse*

Auf Eichmann-Exposé-Seiten gibt es bewusst kein zusätzliches Freitext-Nachrichtenfeld.

Die bi-bodenseeimmo-Seite zeigt zusätzlich eine Datenschutz-Einwilligungscheckbox. Diese wird hier bewusst nicht kopiert: die Eichmann-Site verwendet für die notwendige Anfragebearbeitung einen Datenschutzhinweis mit Link statt einer zusätzlichen Pflicht-Einwilligung.

Generiert wird der Flow zentral in:

scripts/sync-immowelt.mjs

Dadurch gelten Änderungen automatisch für alle erzeugten Objektseiten.

Versteckte technische Felder

Zusätzlich zu den sichtbaren Feldern werden Objektkontext und Mail-Metadaten mitgegeben:

  • anliegen = Exposé-Anfrage
  • objekt
  • objekt_url
  • ein Honeypot-Feld botcheck

Mail-Betreff und Empfänger werden serverseitig festgelegt; der Browser darf sie nicht frei bestimmen.

Validierung

js/main.js:

  1. trimmt Benutzereingaben
  2. nutzt die nativen HTML-required-/E-Mail-Regeln
  3. prüft mit form.checkValidity()
  4. zeigt Browserfehler via reportValidity()
  5. blockiert den clientseitigen Honeypot
  6. sendet erst dann

Damit ist eine komplett leere Exposé-Anfrage technisch nicht mehr möglich.

Regressionstest:

npm run test:expose-form

Der Test startet Chromium, lädt eine generierte Exposé-Seite, prüft Feldsatz, Reihenfolge, Required-Status, Payload und Success-UI und mockt ausschließlich die Netzwerkgrenze zum eigenen Formular-Gateway.

Serverseitige Trust-Grenze

Zusätzlich zur Browservalidierung validiert der Gateway die Pflichtfelder nochmals serverseitig. Er erzwingt Tenant, erlaubte Origins, feste Empfänger, feste Exposé-URL-Domain, Requestgrößen und Rate-Limits. Erfolg wird erst gemeldet, nachdem Amazon SES den Versand angenommen hat.


10. Allgemeines Kontaktformular

kontakt.html ist vom Exposé-Flow getrennt.

Pflichtfelder:

  • Name
  • E-Mail
  • Nachricht

Optional:

  • Telefon
  • Betreff/Anliegen-Auswahl

Auch hier:

  • Whitespace wird entfernt
  • native Validierung läuft
  • komplett leere Anfragen werden blockiert
  • kein Datenschutz-Pflicht-Haken
  • Datenschutzhinweis mit Link
  • Hinweis: durch Absenden kommt kein Maklervertrag zustande

11. Wie E-Mails tatsächlich verschickt werden

Produktiver Pfad:

Browser auf immobilieneichmann.de
  -> HTTPS JSON POST
  -> https://forms.digitalisierungsplanung.de/v1/immobilieneichmann/{contact|expose}
  -> Nginx
  -> dp-forms.service (127.0.0.1:8791)
  -> Amazon SES
  -> info@immobilien-eichmann.com

Der Gateway ist vom Hauptprodukt digitalisierungsplanung.de getrennt: eigener systemd-Dienst, eigener Linux-User, eigene Environment-Datei, eigener Loopback-Port, keine gemeinsame Account-Datenbank und keine Produktsession.

Bei Erfolg antwortet er mit:

{ "success": true, "requestId": "…" }

Bei Fehler zeigt die Website die bestehende Fehlerbox und den Mailto-Fallback. Die HTML-Formulare besitzen zusätzlich ein normales action auf denselben Gateway und method="POST" als einfachen No-JavaScript-Fallback.

Speicherung und Logs

Kontakt-/Exposé-Eingaben werden nicht in dieses GitHub-Repository, Local Storage, Session Storage oder eine eigene Formular-Datenbank geschrieben. Der Gateway verarbeitet sie im Arbeitsspeicher für Validierung und Mailversand. Seine technischen Logs enthalten Request-ID, Tenant, Flow, Status und Dauer, aber keine Formularinhalte oder Kontaktdaten. Danach liegt die Anfrage als E-Mail im Zielpostfach info@immobilien-eichmann.com, abhängig von dessen Aufbewahrungseinstellungen.

GitHub Pages hostet die Website, nicht das E-Mail-Postfach. Der Versand erfolgt über Amazon SES; die konkrete Mailbox-/MX-Infrastruktur von immobilien-eichmann.com wird weiterhin nicht in diesem Repository konfiguriert.

12. Datenschutz- und Consent-Runtime

Consent-Code:

js/cookie-consent.js

Browser-Key:

eichmann_cookie_consent_v1

Gespeichert wird in localStorage:

{
  "necessary": true,
  "analytics": false,
  "ts": 0
}

Es wird also nur die Consent-Entscheidung lokal im Browser gespeichert.

Google Analytics

Analytics wird nicht beim ersten Seitenaufruf automatisch geladen.

Nur wenn der Nutzer „Alle akzeptieren“ wählt:

  1. cookie-consent.js lädt js/analytics.js
  2. analytics.js lädt Googles gtag.js
  3. GA4 startet mit Measurement ID G-QVRRBPYNVM

Ohne Analytics-Consent wird googletagmanager.com von unserer Analytics-Logik nicht geladen.

Google Fonts

Keine externen Google Fonts.

Die Website verwendet lokale/System-Font-Stacks. Dadurch entsteht beim normalen Rendern kein Fonts-Request an Google.

Google Maps

Es gibt keinen automatisch geladenen Maps-Iframe.

Auf der Kontaktseite gibt es nur einen externen Link. Erst wenn der Nutzer ihn anklickt, wird Google Maps geöffnet.


13. Admin-System

URL:

https://immobilieneichmann.de/admin/

Unified UI (tabs: Immowelt | Eigen-Inserate). /admin/eigen/ redirects to /admin/#eigen.

Details: admin/README.md and docs/STABSCHEF-admin-unified-2026-09-25.md.

Login-Modus

admin/config.json:

auth_mode = password_session

Login benötigt:

  1. freigeschaltete E-Mail-Adresse
  2. Admin-Passwort

Kein GitHub-PAT. Der Browser ruft POST /admin/api/login auf; nginx proxyt auf 127.0.0.1:3847. Die API prüft Allowlist + password_sha256 und setzt ein HttpOnly Secure SameSite=Strict Cookie.

Speichern

Browser → /admin/api/{eigen|visibility|publish}
       → eichmann-admin-api (systemd)
       → SQLite SoT → publish-from-db → /var/www/…

Immowelt-Konto bleibt read-only. Immowelt-Import weiterhin über sync-immowelt.yml.

Entfernt (2026-09-25)

  • Sitzungs-PAT / sessionStorage Token
  • admin-eigen-save.yml (repository_dispatch → SSH upsert)
  • Standalone Eigen-UI (nur Redirect)

14. Admin-Speicherflow (Legacy / GitHub Contents — deprecated)

Deprecated 2026-09-25: Day-to-day CRUD uses /admin/api/ on the droplet. The flows below describe the old PAT + Contents API path and may still apply to leftover admin-save.yml tooling.

Objekt bearbeiten

Primärer Pfad:

Admin-Browser
  -> GET data/listings.json + SHA über GitHub Contents API
  -> Benutzer ändert Felder
  -> PUT data/listings.json mit bisherigem SHA
  -> GitHub Commit
  -> repository_dispatch admin_apply_render
  -> GitHub Action rendert
  -> Commit generierte Outputs
  -> GitHub Pages Deployment

Die Verwendung des aktuellen File-SHA ist eine einfache Form von Optimistic Concurrency: ein offensichtlich veralteter Stand kann von GitHub mit Konflikt abgewiesen werden.

Fallback

Wenn der direkte Contents-API-Save fehlschlägt:

repository_dispatch: admin_save_listings

Dann schreibt admin-save.yml die komplette vom Browser gesendete JSON-Datei und rendert anschließend.

Dieser Fallback ist funktional, aber keine transaktionale Multi-User-Datenbank. Gleichzeitiges Bearbeiten durch mehrere Admins sollte vermieden werden.

Neues Objekt

Das Admin erzeugt:

  • neue UUID
  • stabilen Slug
  • lokalen Datensatz
  • source: local
  • sync_policy: independent
  • manual_overrides für manuell gepflegte Felder

Eine optionale Immowelt-URL/UUID kann als Inbound-Verknüpfung hinterlegt werden.

Löschen

Löschen entfernt den Datensatz aus data/listings.json.

Der anschließende Render entfernt:

  • die nicht mehr benötigte objekt/{slug}.html
  • systemverwaltete orphaned Bilder, soweit sie nicht mehr referenziert sind
  • die Objekt-URL aus der Sitemap

Foto-Upload

  1. Browser liest die Datei als Base64.
  2. GitHub Contents API committed die Datei nach assets/listings/.
  3. Das Listing bekommt die neue Bildreferenz.
  4. data/listings.json wird committed.
  5. Render läuft.

Maximale vom Admin akzeptierte Uploadgröße: ungefähr 4,5 MB.

Erlaubte Dateitypen im aktuellen Adminpfad:

  • JPG/JPEG
  • PNG
  • WebP

15. Manuelle Overrides

Wird ein Feld im Admin manuell verändert, schreibt das Admin:

"manual_overrides": {
  "title": true,
  "price": true,
  "updated_at": "..."
}

Der Immowelt-Importer respektiert diese Locks.

Geschützte Feldgruppen umfassen unter anderem:

  • Titel
  • Preis
  • Ort
  • Zimmer
  • Wohn-/Grundstücksfläche
  • Typ
  • Status
  • Kurzbeschreibung
  • Beschreibung
  • Bilder/Gallery
  • Grundrisse
  • Fakten
  • Hauptbild

So bleibt lokal gepflegter Inhalt autoritativ.


16. GitHub-Actions-Pipelines

sync-immowelt.yml

Aufgabe:

  • regelmäßiger öffentlicher Immowelt-Import
  • manueller Sync
  • Render-only
  • Generatoränderungen auf Push neu ausrollen

Schreibziel:

  • data/listings.json
  • assets/listings/
  • partials/listings-grid.html
  • index.html
  • projekte.html
  • objekt/
  • sitemap.xml

admin-save.yml

Aufgabe:

  • Admin-repository_dispatch empfangen
  • JSON speichern oder nur rendern
  • generierte Outputs committen
  • optional Immowelt-Workflow anstoßen

Events:

  • admin_save_listings
  • admin_apply_render
  • admin_trigger_sync

apply-legal-baseline.yml

Wird ausgeführt, wenn die Legal-Baseline selbst geändert wird.

Ablauf:

  1. Baseline anwenden
  2. Legal-/Privacy-Regressionsprüfung
  3. Dependencies installieren
  4. Playwright installieren
  5. Layout prüfen
  6. Änderungen gegebenenfalls committen

layout-regression.yml

Hard Gate für relevante Frontendänderungen.

Prüft:

  • Legal-/Privacy-Baseline
  • Exposé-Formular-Feldsatz und Payload
  • Desktop-Layout
  • Mobile-Layout
  • Horizontal Overflow
  • Header/Logo
  • Flyer-Geometrie
  • Kontaktformular kann leer nicht absenden

Screenshots werden als GitHub-Actions-Artefakt hochgeladen.

logo-consistency.yml

Prüft Logo-Dateien, Versionierung und bekannte Fehlerbilder.

Der Logo-Test selbst läuft aktuell standardmäßig soft; die Header-Logo-Sicherheitsversion ist:

assets/logo-header.svg?v=header-safe-v1

Der zusätzliche rechte SVG-Viewport verhindert, dass das letzte N im Header wieder abgeschnitten wird.

share-card.yml

Auf jedem Push/PR:

npm run test:share

Prüft unter anderem:

  • 1200 × 630
  • JPEG
  • Dateigröße
  • korrekte OG-/Twitter-Referenzen
  • keine Abweichung vom freigegebenen Plain-Bild

refresh-share-card.yml

Nur bei Änderungen am Refresh-Script/Workflow.

Lädt das freigegebene Immobilienbild, erzeugt 1200 × 630 und schreibt:

  • share-card-source-plain-v2.jpg
  • share-card-plain-v2.jpg
  • Legacy-Dateien

Es werden kein Text und kein Logo-Overlay hinzugefügt.

GitHub Pages Deployment

Das Pages-Build-/Deploy ist ein GitHub-eigener Workflow und liegt deshalb nicht zwingend als eigene YAML-Datei in diesem Verzeichnis.

Jeder relevante Commit auf main wird anschließend über GitHub Pages veröffentlicht.


17. Tests

Gesamtsuite

npm test

Einzeltests

npm run test:share
npm run test:logo
npm run test:jsonld
npm run test:legal
npm run test:layout
npm run test:expose-form

Legal-/Privacy-Test

scripts/test-legal-baseline.mjs prüft unter anderem:

  • keine externen Google Fonts
  • kein automatisch eingebettetes Google Maps
  • keine ausgeschaltete native Formvalidierung
  • keine Legal-Platzhalter
  • keine unnötige Datenschutz-Pflichtcheckbox
  • Impressumsbehörde vorhanden
  • Datenschutz nennt reale eingesetzte Dienste
  • Widerruf enthält 14-Tage-Regel und keine alte 30-Tage-Fassung
  • generierte Objektseiten nutzen Consent-Gate
  • Header-Logo-Sicherheitsversion bleibt erhalten

Exposé-Flow-Test

scripts/test-expose-form.mjs prüft mit echtem Chromium unseren kompletten Browserflow und mockt kontrolliert nur die Netzwerkgrenze zum eigenen Formular-Gateway. Feldsatz, Validierung, Payload und Success-UI bleiben dadurch deterministisch testbar.


18. Social Sharing

Root-Seiten verwenden:

https://immobilieneichmann.de/assets/share-card-plain-v2.jpg

Maße:

1200 × 630

Das Bild ist bewusst plain, ohne zusätzlichen Text und ohne zusätzliches Logo.

Generierte Objektseiten verwenden nach Möglichkeit das jeweilige Immobilienbild als Social Preview und fallen sonst auf die allgemeine Share-Card zurück.


19. SEO / strukturierte Daten

Vorhanden:

  • robots.txt
  • sitemap.xml
  • Canonical URLs
  • Open Graph
  • Twitter Card Meta
  • JSON-LD
  • llms.txt

robots.txt erlaubt die öffentliche Site und disallowt /admin/ für Crawler.

Wichtig: robots.txt ist keine Zugriffskontrolle.


20. Drittanbieter und externe Abhängigkeiten

DienstWann aufgerufenZweckWelche Daten
GitHub Pagesjeder Seitenaufrufstatisches Hosting/CDNnormale HTTP-Verbindungsdaten
GitHub REST APInur Admin-NutzungListings/Bilder lesen und schreiben, Workflows dispatchenRepo-Daten + PAT im Request
GitHub ActionsCron, Push, Admin-DispatchScrape, Render, Tests, BildverarbeitungRepo-/Build-Daten
eigenes Formular-Gateway (forms.digitalisierungsplanung.de)Kontakt-/Exposé-Submitserverseitige Validierung und Mail-Übergabevom Nutzer eingegebene Formulardaten
Amazon SESnach erfolgreicher Gateway-Validierungtransaktionaler E-Mail-VersandFormulardaten im Mailinhalt + Empfänger/Reply-To
Immoweltautomatischer Import / externe Linksöffentliche Objektquelleöffentliche Objektdaten
Google Analytics 4nur nach Analytics-ConsentStatistikAnalytics-/Browserdaten nach Google-Konfiguration
Google Mapsnur nach Nutzer-Klickexterne Kartenansichterst nach Öffnen von Google
npm Registrynur Build/InstallPlaywright/Sharp installierenBuild-Metadaten

Nicht vorhanden:

  • eigene SQL-/NoSQL-Datenbank
  • WordPress
  • PHP
  • serverseitiges Session-System
  • eigenes SMTP
  • externe Google Fonts
  • automatisch eingebettetes Google Maps
  • Schreibzugriff auf Immowelt

21. Welche Daten liegen wo?

DatenSpeicherort
statische WebsiteGitHub Repository + GitHub Pages
Immobilien-Stammdatendata/listings.json im Git-Repo
Objektbilderassets/listings/ im Git-Repo
generierte Exposésobjekt/*.html im Git-Repo
Kontakt-/Exposé-Eingabennicht im Repo/Browser-Speicher; flüchtige Verarbeitung im eigenen Formular-Gateway, danach E-Mail-Versand über Amazon SES
Formular-Gateway-Logsnur technische Metadaten ohne Formularinhalte/Kontaktdaten
zugestellte AnfragenZiel-Mailbox info@immobilien-eichmann.com
Analytics-DatenGoogle Analytics, nur nach Consent
Consent-AuswahlBrowser-localStorage
Admin-PATBrowser-sessionStorage
Admin-Passwortnicht persistent im Browser; nur Hash liegt öffentlich in Config
Git-HistorieGitHub
CI-Logs/ArtefakteGitHub Actions

22. Sicherheit und Grenzen

Was schützt das Admin wirklich?

Nicht der HTML-Login allein.

Da das Admin vollständig statisch ist, kann jeder Besucher seinen JavaScript-Code lesen.

Der tatsächliche Schreibschutz ist GitHub:

  • ohne gültigen PAT keine GitHub-Schreiboperation
  • Token sollte minimal berechtigt sein
  • Token nie committen
  • bei Leak sofort bei GitHub widerrufen

Gleichzeitige Bearbeitung

Es gibt keine transaktionale Datenbank und kein eigenes Locking-System.

Der normale Contents-API-Save nutzt den letzten bekannten SHA und erkennt dadurch viele Stale-Write-Situationen.

Der Fallback admin_save_listings kann jedoch die komplette JSON aus dem Browserzustand schreiben. Daher sollte das Admin nicht von mehreren Personen gleichzeitig am selben Objekt benutzt werden.

Formulare

Die Browservalidierung verhindert normale leere Submits.

Da Client-Code grundsätzlich manipulierbar ist, validiert dp-forms.service dieselben Pflichtfelder serverseitig. Der Gateway erzwingt feste Tenant-/Origin-/Empfängerregeln, Body- und Rate-Limits und akzeptiert für Exposés nur Objekt-URLs der Eichmann-Domain.


23. Lokale Entwicklung

git clone <repo>
cd eichmannimmobilien
npm ci
npx playwright install chromium

Einfacher Static Server:

npx serve .

Danach zum Beispiel:

http://localhost:3000/
http://localhost:3000/admin/

Nur rendern, ohne Immowelt live zu lesen:

node scripts/sync-immowelt.mjs --render-only

Live-Import:

node scripts/sync-immowelt.mjs

Seed aus anderer JSON:

node scripts/sync-immowelt.mjs --from-json /pfad/datei.json

24. Betrieb: typische Änderungen

Objekttext ändern

Bevorzugt über /admin/.

Resultat:

Admin -> GitHub JSON -> Render Action -> Commit -> Pages

Neues Objekt von Immowelt übernehmen

Immowelt-Workflow manuell starten oder nächsten 3-Stunden-Lauf abwarten.

Neues lokales Objekt

Im Admin „+ Neues Objekt“.

Template aller Exposé-Seiten ändern

scripts/sync-immowelt.mjs ändern und pushen.

Der Push-Trigger rendert alle Objektseiten aus data/listings.json neu.

Analytics ändern

js/analytics.js und gegebenenfalls datenschutz.html anpassen.

Kontakttransport ändern

Mindestens prüfen/anpassen:

  • js/main.js
  • Formular-action in kontakt.html
  • Exposé-Template in scripts/sync-immowelt.mjs
  • datenschutz.html
  • scripts/test-expose-form.mjs
  • scripts/test-legal-baseline.mjs

Logo ändern

Header verwendet die crop-sichere Datei assets/logo-header.svg.

Logoänderungen immer gemeinsam mit scripts/test-logo-consistency.mjs prüfen.


25. Wichtige externe Dokumentation


26. Entscheidende Architekturregeln

  1. data/listings.json ist die Single Source of Truth.
  2. Immowelt ist nur Inbound und wird nie beschrieben.
  3. Generierte HTML-Seiten nicht als Primärdaten behandeln.
  4. Öffentliche Website statisch halten; serverseitige Logik nur im getrennten dp-forms-Gateway.
  5. Keine Secrets in statische Dateien oder ins Repo.
  6. Admin-PAT nur in der Browser-Sitzung.
  7. Formularanfragen laufen ausschließlich über den eigenen Gateway und Amazon SES; sie gehören nicht ins Git-Repo.
  8. Analytics niemals vor Consent laden.
  9. Objekt-Templateänderungen immer zentral im Generator durchführen.
  10. Nach Änderungen Tests und Pages-Deployment prüfen.

Objektstandort statt Objektadresse

Exakte Objektadressen werden öffentlich nicht ausgegeben. Angebotskarten, Exposé-Fakten, Beschreibungen und die öffentliche data/listings.json werden auf Stadtteil/Ort reduziert. Die Geschäftsadresse von Immobilien Eichmann in Footer/Impressum bleibt davon unberührt.

Reviews

No reviews yet

Be the first to review this server!