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
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.
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 GitHubFrom 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) andeigen(own listings via unified/admin/#eigen). - Immowelt sync upserts/deactivates only
origin=immoweltand never deletesorigin=eigen. - Immowelt profile/account is read-only (no writes).
data/listings.jsonis an export/backup with"sot": "sqlite", not the SoT.- Publish:
node scripts/publish-from-db.mjswrites 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.serviceaufforms.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.
| Ebene | Technik |
|---|---|
| Markup | HTML5 |
| Styling | eine eigene CSS-Codebasis in css/styles.css |
| Browserlogik | Vanilla JavaScript |
| Build-Bundler | keiner |
| React/Vue/Angular | keiner |
| jQuery | keiner |
| CSS-Framework | keines |
| Webfonts | keine externen Google Fonts; System-Font-Stacks |
| Bilder | JPG, WebP, PNG, SVG |
| SEO | statische Meta-Tags, Open Graph, Twitter Cards, JSON-LD, Sitemap |
| Deployment | GitHub Pages aus main |
Die Browserlogik liegt hauptsächlich in:
js/main.js– Navigation, Kontakt-/Exposé-Formulare, Flyer, Gallery, Lightbox, URL-Prefillsjs/cookie-consent.js– Consent-Speicherung und kontrolliertes Laden von Analyticsjs/analytics.js– Google Analytics 4 /gtag.js, Measurement IDG-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:
| Paket | Verwendung | aktuell aufgelöst |
|---|---|---|
playwright | Browser-Automation: Immowelt-Import und Browser-Regressionsprüfungen | 1.63.0 |
sharp | Bildkonvertierung, Größenanpassung, Social-Share-Bilder | 0.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?
- DNS löst
immobilieneichmann.deauf GitHub Pages auf. - GitHub Pages liefert fertige statische Dateien aus.
- Der Browser führt
cookie-consent.jsundmain.jsaus. - Nur beim Absenden eines Kontakt-/Exposé-Formulars wird
forms.digitalisierungsplanung.deaufgerufen. - 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:
idsluglocal_urltitlepricelocationroomsliving_areaplot_areatypestatusshort_descriptiondescriptionfactsexpose_urlmain_image_urlimagesfloor_plansimage_basegallery_basesfloor_plan_basessourceimmowelt_idsync_policymissing_on_immoweltactive– steuert, ob ein Objekt öffentlich erscheint;falsebehält es intern, veröffentlicht es aber nichtdetail_page–falseerlaubt einen öffentlichen Kontakt-Teaser ohne erfundene Exposé-Inhalte; nurtrueerzeugt 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
- GitHub Actions startet einen kurzlebigen Ubuntu-Runner.
- Node 20 und Dependencies werden installiert.
- Playwright Chromium öffnet das öffentliche Immowelt-Profil.
- Öffentliche Objektinformationen werden gelesen.
- Soweit möglich werden Detailseiten für Beschreibung, Bilder, Grundrisse und Fakten angereichert.
- Neue Daten werden gegen
data/listings.jsongemerged. - Objektbilder werden heruntergeladen.
- Sharp erzeugt lokale JPG-/WebP-Versionen.
- JSON wird aktualisiert.
- Karten, Exposé-Seiten und Sitemap werden neu gerendert.
- Geänderte Dateien werden auf
maincommitted. - 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] = trueschützt einen Wert vor Immowelt-Überschreibensource: localist lokal autoritativ- auf Immowelt verschwundene Objekte werden standardmäßig nicht automatisch gelöscht
- stattdessen
missing_on_immowelt: true - nur
sync_policy: mirrorerlaubt 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:
- Anrede* – Select
- Vorname*
- Name*
- Straße und Hausnummer*
- PLZ*
- Ort*
- Telefonnummer – optional
- 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é-Anfrageobjektobjekt_url- ein Honeypot-Feld
botcheck
Mail-Betreff und Empfänger werden serverseitig festgelegt; der Browser darf sie nicht frei bestimmen.
Validierung
js/main.js:
- trimmt Benutzereingaben
- nutzt die nativen HTML-
required-/E-Mail-Regeln - prüft mit
form.checkValidity() - zeigt Browserfehler via
reportValidity() - blockiert den clientseitigen Honeypot
- 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
- 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:
cookie-consent.jslädtjs/analytics.jsanalytics.jslädt Googlesgtag.js- 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:
- freigeschaltete E-Mail-Adresse
- 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 /
sessionStorageToken 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 leftoveradmin-save.ymltooling.
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: localsync_policy: independentmanual_overridesfü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
- Browser liest die Datei als Base64.
- GitHub Contents API committed die Datei nach
assets/listings/. - Das Listing bekommt die neue Bildreferenz.
data/listings.jsonwird committed.- 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.jsonassets/listings/partials/listings-grid.htmlindex.htmlprojekte.htmlobjekt/sitemap.xml
admin-save.yml
Aufgabe:
- Admin-
repository_dispatchempfangen - JSON speichern oder nur rendern
- generierte Outputs committen
- optional Immowelt-Workflow anstoßen
Events:
admin_save_listingsadmin_apply_renderadmin_trigger_sync
apply-legal-baseline.yml
Wird ausgeführt, wenn die Legal-Baseline selbst geändert wird.
Ablauf:
- Baseline anwenden
- Legal-/Privacy-Regressionsprüfung
- Dependencies installieren
- Playwright installieren
- Layout prüfen
- Ä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.jpgshare-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.txtsitemap.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
| Dienst | Wann aufgerufen | Zweck | Welche Daten |
|---|---|---|---|
| GitHub Pages | jeder Seitenaufruf | statisches Hosting/CDN | normale HTTP-Verbindungsdaten |
| GitHub REST API | nur Admin-Nutzung | Listings/Bilder lesen und schreiben, Workflows dispatchen | Repo-Daten + PAT im Request |
| GitHub Actions | Cron, Push, Admin-Dispatch | Scrape, Render, Tests, Bildverarbeitung | Repo-/Build-Daten |
eigenes Formular-Gateway (forms.digitalisierungsplanung.de) | Kontakt-/Exposé-Submit | serverseitige Validierung und Mail-Übergabe | vom Nutzer eingegebene Formulardaten |
| Amazon SES | nach erfolgreicher Gateway-Validierung | transaktionaler E-Mail-Versand | Formulardaten im Mailinhalt + Empfänger/Reply-To |
| Immowelt | automatischer Import / externe Links | öffentliche Objektquelle | öffentliche Objektdaten |
| Google Analytics 4 | nur nach Analytics-Consent | Statistik | Analytics-/Browserdaten nach Google-Konfiguration |
| Google Maps | nur nach Nutzer-Klick | externe Kartenansicht | erst nach Öffnen von Google |
| npm Registry | nur Build/Install | Playwright/Sharp installieren | Build-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?
| Daten | Speicherort |
|---|---|
| statische Website | GitHub Repository + GitHub Pages |
| Immobilien-Stammdaten | data/listings.json im Git-Repo |
| Objektbilder | assets/listings/ im Git-Repo |
| generierte Exposés | objekt/*.html im Git-Repo |
| Kontakt-/Exposé-Eingaben | nicht im Repo/Browser-Speicher; flüchtige Verarbeitung im eigenen Formular-Gateway, danach E-Mail-Versand über Amazon SES |
| Formular-Gateway-Logs | nur technische Metadaten ohne Formularinhalte/Kontaktdaten |
| zugestellte Anfragen | Ziel-Mailbox info@immobilien-eichmann.com |
| Analytics-Daten | Google Analytics, nur nach Consent |
| Consent-Auswahl | Browser-localStorage |
| Admin-PAT | Browser-sessionStorage |
| Admin-Passwort | nicht persistent im Browser; nur Hash liegt öffentlich in Config |
| Git-Historie | GitHub |
| CI-Logs/Artefakte | GitHub 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-
actioninkontakt.html - Exposé-Template in
scripts/sync-immowelt.mjs datenschutz.htmlscripts/test-expose-form.mjsscripts/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
- GitHub Pages: https://docs.github.com/pages
- GitHub REST API: https://docs.github.com/rest
- GitHub Actions: https://docs.github.com/actions
- Amazon SES: https://docs.aws.amazon.com/ses/
- Immowelt: https://www.immowelt.de/
- Google Analytics: https://developers.google.com/analytics
- Playwright: https://playwright.dev/
- Sharp: https://sharp.pixelplumbing.com/
26. Entscheidende Architekturregeln
data/listings.jsonist die Single Source of Truth.- Immowelt ist nur Inbound und wird nie beschrieben.
- Generierte HTML-Seiten nicht als Primärdaten behandeln.
- Öffentliche Website statisch halten; serverseitige Logik nur im getrennten
dp-forms-Gateway. - Keine Secrets in statische Dateien oder ins Repo.
- Admin-PAT nur in der Browser-Sitzung.
- Formularanfragen laufen ausschließlich über den eigenen Gateway und Amazon SES; sie gehören nicht ins Git-Repo.
- Analytics niemals vor Consent laden.
- Objekt-Templateänderungen immer zentral im Generator durchführen.
- 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!
More Developer Tools MCP Servers
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Worldmonitor
Freeby Koala73 · Developer Tools
Live markets, conflicts, country risk, chokepoints, energy, and China decision signals. 86 tools.
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
