Standortdaten vergleichbar machen, vom Landkreis bis zur Gemeinde
Ein Dashboard, mit dem Wirtschaftsförderungen ihre Region an frei gewählten Vergleichsregionen messen und daraus fertige Berichte ziehen. Dieselben Zahlen gibt es inzwischen per API, als Widget für die eigene Website und direkt in Claude oder ChatGPT. Das Beratungsunternehmen verkauft das Ganze als eigenes Produkt weiter.
Ausgangslage
Wer einen Standort bewerten will, braucht viele Kennzahlen gleichzeitig und immer im Vergleich: Beschäftigung, Fachkräfte, Kaufkraft, Pendlersaldo, Altersstruktur, Steuereinnahmen. Die Daten sind öffentlich, liegen aber bei verschiedenen Statistikämtern, jedes mit eigenem Format und eigenem Stichtag. In Rohform hilft das in einem Beratungsgespräch niemandem.
Statistikportale gibt es genug, und sie liefern Zahlen. Die Frage, die im Gespräch tatsächlich kommt, beantworten sie nicht: Wie steht meine Region gegenüber vergleichbaren Regionen da, und was zeige ich damit am Donnerstag im Ausschuss?
Ziel
Ein Werkzeug, das die Wirtschaftsförderung selbst bedient, ohne Datenanalyse-Kenntnisse. Frei konfigurierbar, bis hinunter auf Gemeindeebene, und am Ende steht ein Bericht, den man ohne Nacharbeit weitergeben kann.
Das Corporate Design des Kunden war verbindlich, bis hin zu Farbwerten und Hausschrift, weil das Ergebnis unter seinem Namen beim Endkunden landet.
Lösung
Beim Start wählt man Ebene, eigene Region und Vergleichsregionen. Danach stellt man sich ein Board aus Kennzahlen-Kacheln zusammen, aus 28 Kennzahlen auf Kreis- und 20 auf Gemeindeebene. Jede Kachel zeigt den eigenen Wert, auf Kreisebene auch den Rang im Vergleichsraum, und schaltet zwischen Verhältnis, Entwicklung und Absolutwert um. Ein Klick öffnet Karte, Zeitreihe über zehn Jahre, Tabelle und den KI-Assistenten zu genau diesem Datensatz.
Auf Kreisebene entsteht aus allen Kacheln ein gewichtetes Gesamtranking, bei dem man pro Kennzahl festlegt, wie stark sie zählt. Raus kommt ein PDF-Bericht im Corporate Design oder eine Excel-Datei je Kennzahl, und die ganze Zusammenstellung lässt sich speichern und im Team wieder laden.
Seit September 2026 geht es auch ohne Dashboard. Eine API liefert die Kennzahlen als JSON, CSV oder Parquet, dazu Karte, Zeitreihe und Ranking als Widgets, die eine Wirtschaftsförderung per iframe in ihre Website einbaut und die mit jedem Datenupdate nachziehen. Über einen MCP-Server fragen Claude, ChatGPT oder Cursor die Kennzahlen direkt ab, mit dem Login aus dem Dashboard. Wer eine öffentliche Standortseite braucht, bekommt eine eigene Instanz mit fest eingestellter Region und nur den freigegebenen Funktionen.
Ergebnis
„Stefan hat für uns ein Dashboard entwickelt, mit dem wir die wichtigsten Standortdaten mit nur wenigen Klicks ermitteln und miteinander vergleichen können. Für unsere Beratungskunden ist es besonders wertvoll, dass auch Mitarbeiter ohne Datenanalyse-Kenntnisse selbstständig mit dem Tool arbeiten können. Gleichzeitig erhalten sie Zugang zu präzisen Standorterkenntnissen auf kleinster Ebene. Die KI-Unterstützung beantwortet sogar direkt Fragen zu den Ergebnissen.“
Wo es knifflig wurde
Eine Rechenschicht für alles
Erst kam die Gemeindeebene dazu, mit 27-mal so vielen Zeilen und einer Codebasis, die überall von Kreisen sprach. Dann die API, die dieselben Zahlen nach außen gibt. Beide Male wäre eine zweite Implementierung schneller fertig gewesen und irgendwann auseinandergelaufen. Zeigt das Widget auf der Website des Landkreises eine andere Zahl als das Dashboard im Beratungsgespräch, glaubt man keinem von beiden mehr. Dashboard und API rechnen deshalb über dieselben Funktionen. Sonderfälle gibt es nur dort, wo ein Ranking auf Gemeindeebene fachlich keinen Sinn ergibt.
Ein Board, das seinen Zustand nicht verliert
Kacheln kommen und gehen, dieselbe Kennzahl liegt mehrfach mit unterschiedlichen Filtern auf dem Board, die Ebene ist umschaltbar, und eine gespeicherte Analyse ersetzt den ganzen Zustand auf einmal. Jede Kachel hat eigenen Filter-, Darstellungs- und Datenzustand, und Karte, Plot, Tabelle, Chat und Ranking hängen alle daran. Der naheliegende Weg, das alles am Namen des Datensatzes festzumachen, hält genau bis zur zweiten Kachel mit derselben Kennzahl.
Ein Assistent mit SQL-Zugriff, der nichts kaputt machen kann
Der Assistent braucht echtes SQL, sonst kann er die Fragen nicht beantworten, für die es im Dashboard keine Kachel gibt. Abgesichert ist das mehrfach und unabhängig voneinander: jede Kennzahl hat ihre eigene DuckDB-Datei, read-only geöffnet, eine Blocklist fängt alles ab, was nicht SELECT ist, und Diagramme entstehen deklarativ über ggsql. Code vom Modell wird nirgends ausgeführt. Datenbankfehler gehen bewusst zurück an das Modell, damit es sich selbst korrigieren kann, während der Nutzer nur eine verständliche Meldung sieht.
Technische Umsetzung
Die App ist mit box modularisiert. Ein eigenes Skript harmonisiert die Zeitreihen
vorab auf einen festen Gebietsstand, rechnet Bezugsgrößen und Basisjahre vor und schreibt
Parquet raus, das duckplyr zur Laufzeit lazy liest. Wo DuckDB nicht mitspielt, wird
bewusst materialisiert, und diese Stellen sind im Code markiert.
PDF-Render, Sammel-Excel und die Antworten des Assistenten laufen als ExtendedTask
über mirai im Hintergrund. Der Bericht entsteht mit Quarto und Typst, dadurch
braucht das Image kein TeX. Farben, Schriften und Logo stehen in einer brand.yml je
Kunde, aus der sich Dashboard, Widgets, PDF und Chat-Diagramme ableiten.
Die API läuft mit plumber2 auf einem eigenen Server und meldet gegen denselben
Cognito-User-Pool an wie das Dashboard. Ein einmal gerendertes Widget kommt in unter 10 ms von der
Platte, ohne dass R beteiligt ist. Die Signatur der Embed-URL deckt jeden Parameter ab: Wer sie
kopiert, bekommt genau dieses eine Widget. Bei 2.500 Flächen ist Schluss, eine bundesweite
Gemeindekarte lehnt die API ab.
Der MCP-Server ist ein schlanker TypeScript-Dienst, der nichts rechnet und nichts speichert. Was er beiträgt, sind die Leseregeln, etwa dass ein Rang nur neben seinem Vergleichsraum etwas bedeutet. Am aufwendigsten war der Login: Cognito kennt keine Dynamic Client Registration und keine Redirects auf wechselnde Ports, wie Claude Code sie pro Session öffnet. Der Server tritt deshalb gegenüber den Clients selbst als OAuth-Server auf.
Betrieb und Weiterentwicklung
Das Projekt läuft seit Juli 2024 und wird weiter ausgebaut, zuletzt um API, Widgets, MCP-Server und öffentliche Instanzen. Auf größere Erweiterungen folgen ruhigere Phasen, in denen ich die Anwendung nur pflege.
Betrieb, Datenaktualisierung und Datenbank liegen bei mir. Ein Push baut die Images, schiebt sie in eine private Registry in der EU und rollt sie auf Servern in Deutschland aus. Das Dashboard läuft über ShinyProxy mit einem Container pro Session, API und MCP-Server auf einer eigenen Maschine. Neben dem Dashboard hätte die API auf Port 8443 ausweichen müssen, und den lassen manche Firmennetze nicht nach außen. Ein Widget wäre dort schlicht leer geblieben.
Öffentliche Instanzen starten mit allen Funktionen aus. Eine vergessene Einstellung zeigt dann zu wenig, statt den KI-Assistenten auf einer öffentlichen Seite laufen zu lassen. Gespeicherte Analysen werden nie hart gelöscht, nur inaktiv gesetzt, damit ein Fehlgriff reparierbar bleibt.