Skip to main content

Public Center-Website API — Lückenanalyse & Prioritäten

Stand: Analyse gegen den Code in apps/center-website (v. a. lib/server-data-loader.ts) und apps/dashboard/src/app/api. Ziel: externes Frontend (z. B. v0 + Vercel) kann alle relevanten Reads über https://dashboard.cockpit-os.de (oder konfigurierte DASHBOARD_API_URL) beziehen — ohne Prisma auf der Client-App und ohne Daten-Duplikat.

Legende

SymbolBedeutung
CORS *Access-Control-Allow-Origin: * (und typisch OPTIONS) auf GET-Antworten
Kein CORSJSON wird geliefert, Browser-Cross-Origin-Requests von z. B. *.vercel.app schlagen ohne Proxy fehl
AuthEndpunkt erwartet Session / nicht für anonymes Publikum
Prisma CWCenter-Website lädt heute direkt aus der DB oder über eigene /api-Routen derselben App (nicht Dashboard-URL)

Hinweis: Server-Side Rendering auf Vercel (nur fetch vom Node aus) braucht kein CORS. Sobald die Kollegin Client Components oder Browser-fetch nutzt, sind CORS + OPTIONS auf dem Dashboard nötig.


Quelle der Wahrheit: server-data-loader.ts

Daten / FeatureHeutiger Pfad im LoaderDashboard-Pendant (falls vorhanden)
Shop-KategorienDashboard GET …/website-categories (Dogfooding; Logik in @mall-os/database)GET /api/categories (Dashboard-Liste); Center-Website /api/categories = dünner BFF
Page Content (u. a. Öffnungszeiten)Dashboard GET …/page-content (Dogfooding)GET CORS *
ServicesDashboard GET …/services?publicWebsite=true (Dogfooding)Ohne Flag: nur isActive
BürosDashboard GET /api/offices?centerId=&status= (Dogfooding)Lokale /api/offices optional für BFF
Homepage-TilesDashboard …/homepage-tiles
Category-ThemesDashboard GET …/category-themes-for-website (Dogfooding; @mall-os/database)…/category-themes = roh fürs Cockpit-UI
Office-ThemesDashboard GET …/office-themes (Dogfooding; isActive, nur Büros Aktiv)
Gastronomie-ThemesDashboard …/gastronomy-themes
ShopsDashboard GET …/shops?publicWebsite=true&status=… (Dogfooding; Limit bis 5000)Ohne publicWebsite: breiterer Status-Filter (nicht Inaktiv)
Aktuelles (News, Events, Offers, Jobs)Dashboard GET …/aktuelles-bundle (Dogfooding; max 500 je Typ)Einzelrouten …/news usw. für andere Clients
Baustellen-TagebuchDashboard GET …/news?constructionDiary=true (Dogfooding im Loader)✅ P1; lokale Route /api/construction-diary bleibt im Repo, SSR nutzt sie nicht
Einzel-AngebotDashboard GET …/offers?offerId= (Dogfooding im Loader)✅ P1; lokale Route /api/offers/[id] bleibt im Repo, SSR nutzt sie nicht
Centerplan / FloorsDashboard wayfinding/centerplan + wayfinding/floors (Dogfooding im Loader; Medien wie früher im Loader aufgelöst)Center-Website /api/centers/centerplan = BFF (Slug, kombinierte Antwort)

Zugehörige Dateien (Center-Website):

  • apps/center-website/lib/server-data-loader.ts — Haupt-Loader
  • apps/center-website/app/api/categories/route.ts
  • apps/center-website/app/api/shops/route.ts
  • apps/center-website/app/api/aktuelles/route.ts (Client/BFF)
  • apps/center-website/app/api/construction-diary/route.ts
  • apps/center-website/app/api/offers/[id]/route.ts
  • apps/center-website/app/api/centers/centerplan/route.ts
  • apps/center-website/middleware.ts — u. a. GET …/api/centers/by-domain

P0 — Status (technisches Fundament)

Umgesetzt (CORS * + OPTIONS für öffentliche Reads)

Gemeinsames Modul: apps/dashboard/src/lib/public-api-cors.ts.

BereichDatei
Kategorien GETapps/dashboard/src/app/api/categories/route.ts
Page Content GETapps/dashboard/src/app/api/centers/[centerId]/page-content/route.ts (POST weiterhin ohne breites CORS — Schutz vor Cross-Origin-Schreibzugriff)
Website-Shop-Kategorien GET…/centers/[centerId]/website-categories
Category-Themes (Website-Payload) GET…/centers/[centerId]/category-themes-for-website
Gastronomie-/Category-(Admin)-/Office-Themes GET…/gastronomy-themes, …/category-themes, …/office-themes
Centerplan GETapps/dashboard/src/app/api/wayfinding/centerplan/route.ts
Floors GETapps/dashboard/src/app/api/wayfinding/floors/route.ts
Routing POST + Touchscreen-GETapps/dashboard/src/app/api/wayfinding/routing/route.ts
Eingänge GETapps/dashboard/src/app/api/centers/[centerId]/entrances/route.ts
DOOH öffentlich (Playlists / Player für v0)…/centers/[centerId]/dooh/public/playlists, …/playlist, …/active, …/local-hero — siehe API-Vertrag — DOOH

Öffentliches Konfig-Bundle (Whitelist, kein website-config)

RouteDatei
GET /api/centers/[centerId]/public-visitor-surfaceapps/dashboard/src/app/api/centers/[centerId]/public-visitor-surface/route.ts

Liefert nur explizit erlaubte Felder (Branding, SEO, Chatbot-UI, Centerplan-/Wayfinding-Hinweise, apiHints). Keine API-Keys, kein companionConfig, kein analyticsPagePassword, kein vollständiges templateContent / themeOverrides.

Weiterhin auth-pflichtig: GET /api/centers/[centerId]/website-config — für Dashboard-Editoren; externe Sites nutzen public-visitor-surface + by-slug / theme-config nach Bedarf.

Chatbot (Besucher)

POST /api/ai/visitor-chatbot hatte bereits CORS * — Konversation läuft serverseitig im Dashboard (OpenAI-Key in der Dashboard-Umgebung). Body: centerId und/oder WordPress-apiKey (siehe Route-Doku).

Bereits mit CORS * (Referenz): u. a. …/[centerId]/shops, news, events, offers, jobs, services, homepage-tiles, hotpicks, by-slug/[slug], by-slug/[slug]/theme-config, by-domain, offices, visitor-chatbot.


P1 — Parität (Stand)

ThemaUmsetzung
Baustellen-TagebuchGET …/centers/[centerId]/news?constructionDiary=true (+ optional status) — inkl. linkedShops, Datumsfenster wie Website
Einzel-AngebotGET …/centers/[centerId]/offers?offerId={uuid}websiteOfferPublicFilter, kein To-Go-exklusiv
Aktuelles-BundleGET …/centers/[centerId]/aktuelles-bundle — CORS *, Limits parametrisierbar (max 500 je Typ)
Hot PicksGET …/centers/[centerId]/hotpicks — öffentlich, max. 50 aktive Einträge; Pfad auch data.apiHints.hotPicksGet auf public-visitor-surface
OpenAPI‑Snapshotscockpit-docs/static/openapi/agencyos-integration.yaml + public-wayfinding-read.yaml (öffentliche Wayfinding‑GETs); Markdown‑Vertrag bleibt führend bei Widersprüchen

P2 — Qualität, Dogfooding, Betrieb

ThemaDatei / OrtEmpfehlung
Loader nur noch über HTTPapps/center-website/lib/server-data-loader.tsErledigt: alle bisher genannten Reads inkl. Shop-Kategorien + Category-Themes (Website-Payload). Optional: OpenAPI
Rate Limiting / Abusepublic-visitor-rate-limit.ts + Redis (rate-limit.ts)Erledigt für: POST /api/ai/visitor-chatbot, POST /api/wayfinding/routing (pro IP, 429 + CORS). Edge-Middleware bleibt generell; neue teure öffentliche POSTs analog prüfen. Env: COCKPIT_DISABLE_PUBLIC_VISITOR_RATE_LIMIT=1
Medien-URLsLoader resolveMediaUrlExternes Frontend: gleiche URL-Auflösung dokumentieren oder Dashboard liefert konsistent absolute URLs
AgencyOS /context vs. Floorplan…/agencyos/v1/centers/{id}/contextinclude=floors_summary: kompakte Etage ohne mapSvg-Body (Längen-/Hybrid-Heuristik, Mapping-Zähler). Volles SVG: GET …/wayfinding/floors oder MCP cockpit_public_wayfinding_floors. OpenAPI: /openapi/agencyos-integration.yaml (FloorsSummaryItem), /openapi/public-wayfinding-read.yaml.
AgencyOS Schreiben Website-UIHomepage-Kacheln, Page Content, Mediathek-ListeErledigt: …/homepage-tiles, …/page-content, GET …/media; MCP cockpit_agencyos_homepage_tiles, cockpit_agencyos_page_content, cockpit_agencyos_list_media. Suche inkl. Jobs/Offices: cockpit_agencyos_search_content.
SEO / Revalidateapps/center-website/app/api/revalidate/route.tsAgencyOS content_push triggert Revalidate automatisch (CENTER_WEBSITE_URLS + REVALIDATION_SECRET). Externe v0/Vercel: gleiche Route + Secret + URL in CENTER_WEBSITE_URLS; MCP cockpit_agencyos_revalidate_website.

Kurz-Checkliste für den Product-/Tech-Entscheid

  1. P0: Öffentliche Read-Konfiguration (ohne Session) + CORS auf allen Endpunkten, die der Browser von einer anderen Origin trifft.
  2. P1: Baustellen-Tagebuch + Angebots-Detail + ggf. Aggregat + geschriebener API-Vertrag.
  3. P2: Center-Website auf dieselben URLs umstellen und Betrieb absichern.

Verwandte Pakete / Konfiguration

  • packages/dashboard-api/src/index.tsgetDashboardApiUrl() (Env: DASHBOARD_API_URL, NEXT_PUBLIC_DASHBOARD_URL, NEXT_PUBLIC_API_URL)

Verwandte Doku

Nutzungsstatistik: Seitenaufrufe werden anonymisiert erfasst. Im Umami-Dashboard nach diesem Pfad filtern: /en/developer-guide/public-center-website-api-gap-analyse