Ihr Dashboard auswerfen
Die Veröffentlichung bei Vibedasher ist der normale Abschluss des Kreislaufs: Das ist es, was ein Dashboard gehostet, verwaltet und an Daten angebunden hält, die jemand betreut. Eject ist die andere Tür, und sie steht absichtlich offen. Das Dashboard ist reines React und SQL, und Sie können jederzeit den ganzen Baum nehmen und ihn in Ihrer eigenen App, auf Ihrem eigenen Hosting, unter Ihrem eigenen Build laufen lassen.
Das ist kein Export eines Bildes oder eines JSON-Blobs, den Sie nachbauen müssten. Es ist der
laufende Quellcode: Komponenten, Seiten, Diagramme, Stores, Hooks, eine package.json, die aus
den echten Imports des Baums neu erzeugt wurde, eine Tailwind-Konfiguration, ein CSS-Einstieg,
eine tsconfig.json, eine Vite-Konfiguration, eine index.html und eine main.tsx, die alles
mountet. npm install && npm run dev liefert es als eigene React-App aus.
Eject ist das Gegenteil von Einbetten. Einbetten legt unser gerendertes Dashboard in ein Iframe auf Ihrer Seite. Auswerfen übergibt Ihnen den Quellcode und nimmt uns vollständig aus dem Render-Pfad — wir behalten nur die Daten-Engine darunter. Wenn die Frage lautet „gehört mir dieser Code", ist Eject die Antwort. Wenn Sie noch zwischen beiden wählen, stellt Einbetten oder auswerfen sie nebeneinander.
Die drei Aufrufe
eject_viz(viz_id, out_dir=...)— der ganze Baum plus ein Verdrahtungsmanifest: der Abfragevertrag, die Theme-Tokens, der Einstiegspunkt und seine Prop-Reihenfolge, die Dateiliste, die Region und die Datenspur.eject_viz_files(viz_id, paths=[...])— Dateiinhalte auf Anfrage. Das ist die Folgeaktion, wenn eine Antwort seitenweise kam, und es ist auch die günstige Art, eine einzelne Datei zu lesen.eject_instructions()— die Verdrahtungsreferenz, zurückgegeben als strukturierte Daten statt als Prosa, die Sie parsen müssten. Alles auf dieser Seite ist eine Lesung davon; rufen Sie es auf, wenn Sie das maschinenlesbare Original wollen.
Übergeben Sie out_dir und wissen Sie, auf welchem Transport Sie sind
Ein echtes Dashboard hat die Größenordnung von vierzig und ein paar Dateien und einer halben
Million Zeichen. Mit out_dir auf einen absoluten Pfad gesetzt, wird der Baum direkt auf
die Festplatte geschrieben, und die Antwort bleibt klein, egal wie groß der Baum ist.
Über den stdio-Transport — den Standardstart, bei dem Ihr MCP-Client den Server als lokalen
Unterprozess unter Ihrem eigenen Benutzer startet — ist dieser Pfad Ihre eigene Festplatte, und
genau das macht das Schreiben dorthin legitim. Über den HTTP-Transport wäre es die
Festplatte des Servers, also wird out_dir dort abgelehnt, statt Dateien irgendwohin zu
schreiben, wo Sie sie nicht lesen können, und dabei Erfolg zu melden. Paging ist der einzige
Weg über HTTP.
Ohne out_dir werden Dateien bis zu einem Zeichenbudget in die Antwort gepackt, und der Rest
kommt als delivery.pendingPaths zurück. Diese Liste ist der Vertrag: Eine Antwort mit
nicht-leerem pendingPaths ist eine Seite, kein Baum. Rufen Sie eject_viz_files damit
weiter auf, bis es leer zurückkommt.
Lesen Sie manifest.dataLane, bevor Sie irgendeine Datenverdrahtung schreiben
Das ist die erste Entscheidung und die, die Sie danach nicht mehr ändern können, denn sie entscheidet, wer das Dashboard lesen darf.
Spur A — dataLane.id == "wasm": es rendert schon echte Daten
Für eine Visualisierung, die öffentlich und veröffentlicht ist, gibt Eject einen kleinen
Runner (vibedasherWasm.ts) aus, und der Baum rendert echte Zeilen bei npm run dev ohne
jegliches Zugangsdatum: kein API-Schlüssel, kein Embed-Token, kein eigenes Backend, und es
funktioniert von jedem Origin, einschließlich localhost und eines einfachen statischen
Dateiservers.
Der Mechanismus: Ein anonymes GET für den Wasm-Plan der Visualisierung liefert einen
vorsignierten Parquet-Auszug pro Datensatz; der Runner registriert jeden unter seinem SQL-Alias
in DuckDB-WASM und führt das SQL jedes Diagramms im Browser des Besuchers aus. Seine einzige
Abhängigkeit, @duckdb/duckdb-wasm, liegt auf npm. main.tsx wartet das Aufwärmen des Runners
ab, bevor es mountet, sodass eine fehlerhafte Konfiguration ein gezeichnetes Panel ist statt
eines Rasters leerer Kacheln.
Hier ist nichts zu verdrahten. Legen Sie kein Zugangsdatum obendrauf — das kauft Ihnen einen kaputten Bootstrap für nichts.
Was diese Spur nicht ist: Sie liefert den veröffentlichten Auszug, keine lebende Abfrage, also bedeutet das Aktualisieren des Gezeigten erneutes Veröffentlichen. Und sie existiert nur, solange die Visualisierung öffentlich und veröffentlicht bleibt.
Was jeder Besucher erhält, klar gesagt. Der Auszug hat als Schlüssel Datensatz und
Snapshot, nie eine Abfrage — dasselbe SELECT mit und ohne WHERE gibt die identische Datei
zurück. Er enthält also jede Zeile jedes Datensatzes, den das Dashboard liest, und es ist eine
Datei, dieselbe, für alle. Ein Filter, den Sie auf der Seite hinzufügen, ändert, was gezeichnet
wird, nie, was ausgeliefert wurde, und die Bytes stehen so oder so im Netzwerk-Tab. Das liegt in
der Natur der Sache, wenn man die Daten in den Browser legt. Wenn Betrachter unterschiedliche
Zeilen sehen müssen, nehmen Sie Spur B.
Spur B — dataLane.id == "token": jede andere Visualisierung
Es gibt keine Spur ohne Zugangsdaten, und Eject hat keine ausgegeben. Der Wasm-Plan-Endpunkt
wird von derselben Prüfung auf öffentlich-und-veröffentlicht bewacht wie der übrige anonyme
Bereich, also hilft es nicht, ihn per Hand anzusprechen. npm run dev mountet dennoch und
zeichnet ein Panel, das den Endpunkt nennt, den es braucht — es scheitert nicht stillschweigend
und es setzt keine Scheindaten ein.
Zwei Verdrahtungen funktionieren, und beide legen das Zugangsdatum auf einen Server, den Sie kontrollieren:
- Ihre App liefert eine Embed-Token-Route. Same-Origin, antwortet mit
application/json{"token": "..."}, erzeugt mit dem API-Schlüssel, den sie serverseitig hält. Richten Sie die Embed-Token-URL des Baums darauf aus und konstruieren Sie den Client mit dem Token. - Sie fragen in vertrauenswürdigem Servercode ab mit
new Vibedasher({ apiKey })und geben das Ergebnis nach unten weiter, oder Sie proxyen{ sql, params }durch Ihre eigene Route.
Legen Sie niemals einen API-Schlüssel in Browser-Code. Er trägt volle Kontoautorität und hat keine Scopes. Ein gescopetes Embed-Token ist das clientseitige Zugangsdatum; ein API-Schlüssel ist es nicht.
Diese beiden sind auch die einzigen Formen, die einem Betrachter weniger Zeilen zeigen
können als einem anderen. Ein Embed-Token kann filters tragen, die die Plattform an jede
Abfrage anhängt, die sie autorisiert — serverseitig, vor jedem Join, jeder Aggregation und
jedem LIMIT, wo die Seite sie nicht aufweiten kann. In vertrauenswürdigem Servercode
verengen Sie das SQL selbst.
Wenn Eject die Spur token mit dem Grund no-wasm-extract für eine Visualisierung meldet, die
doch öffentlich und veröffentlicht ist, hat der Datensatz einfach noch keinen Auszug. Darum zu
bitten ist das Einzige, was ihn erzeugt — siehe
Die Wasm-Abfragespur.
Erneutes Veröffentlichen backt keinen Auszug, also läuft „veröffentlichen und erneut auswerfen"
für immer im Kreis.
Den Client installieren
npm i @vibedasher/client
pip install vibedasher
Das npm-Paket heißt @vibedasher/client. Es gibt kein @vibedasher/sdk und wird es nie
geben. Installieren Sie die echten Pakete, statt sie einzuverleiben.
Styling, Typprüfung und der App Router
Styling besteht aus drei Teilen, und Sie brauchen alle drei. tailwind.config.js
(Dark Mode über eine Selektor-Strategie, die an ein Attribut gekoppelt ist, das der Baum auf
seine eigene Wurzel setzt, sodass der Dark Mode des Dashboards unabhängig von dem Ihrer App
abgegrenzt ist, plus eine Safelist für Klassen, die zur Laufzeit zusammengesetzt und damit für
Tailwinds Scanner unsichtbar sind); styles/dashboard.css (der Tailwind-Einstieg und ein
:root-Block mit Design-Tokens als Build-Zeit-Standards); und themeStyles.ts (dieselben
Tokens als String, den die App zur Laufzeit pro Theme injiziert). Das CSS gibt Ihnen einen
gethemten ersten Anstrich; themeStyles.ts gibt Ihnen lebendes Umschalten zwischen hell und
dunkel. Wenn Ihre App schon Tailwind mit klassenbasiertem Dark Mode verwendet, führen Sie die
Konfigurationen nicht zusammen — eine Tailwind-Konfiguration unterstützt eine
Dark-Mode-Einstellung. Auf Tailwind v4 verweisen Sie mit @config auf die mitgelieferte
Konfiguration.
Typprüfung. npm run typecheck (tsc --noEmit) soll auf einem frisch ausgeworfenen Baum
null Fehler melden, und zwei Gates halten das bei jedem Lauf unserer Testsuite — eines prüft die
Typen eines vollständig generierten Ejects, das andere installiert, prüft die Typen und baut
einen handgeschriebenen. Zwei Bedingungen begrenzen diese Aussage, und keine davon ist eine
Absicherung. Sie gilt unter der mitgelieferten tsconfig.json, die strict: false absichtlich
setzt, weil die generierten Diagramm-Effekte gegen lose typisierte Abfragezeilen geschrieben
sind; strict einzuschalten wird Fehler erzeugen, die dann Ihre sind. Und sie gilt für einen Baum,
dessen Branch-Dateien kürzlich geschrieben wurden — ein Dashboard, das lange genug zurückliegt,
trägt eingefrorene Dateien einer älteren Form, von denen zwei Stellen bekannt dafür sind, tsc
scheitern zu lassen, während sie korrekt bauen und laufen, da Vite ohne Typprüfung transpiliert.
Die Behebung ist erneut zu veröffentlichen, was die Branch-Dateien aus der aktuellen Form neu
schreibt.
Next.js App Router. Jedes Modul ist standardmäßig eine Server-Komponente. App.tsx und die
stores/-Module tragen schon 'use client' im Eject — die Stores greifen auf Modulebene auf
localStorage zu und würden auf dem Server abstürzen. App.tsx zu markieren legt ihren ganzen
Import-Graphen in das Client-Bundle, sodass nichts weiter die Direktive braucht, es sei denn,
Sie importieren ein Diagramm, eine Komponente oder einen Store direkt aus einer
Server-Komponente.
Was Eject Ihnen nicht übergibt
- Alles in
manifest.internalDescriptors— Plattform-Metadaten, schon ausfilesausgeschlossen. Kopieren Sie es nicht. - Alles in
manifest.hostOnlyImports— aus dem eigenen Bundle unseres Renderers ausgeliefert, in keinem Registry, absichtlich abwesend. Ersetzen Sie diese, bevor Sie bauen. - Die Datenplattform. Eject nimmt uns aus dem Render-Pfad, nicht aus dem Datenpfad. Die Verbindungen, Datensätze, Aktualisierungen, dbt-Projekte, Governance und Query-Engine darunter bleiben dort, wo sie betreut werden — das ist die Hälfte der Aufteilung, die Sie nicht besitzen wollten. Die Spur ohne Zugangsdaten ist die einzige Ausnahme, und nur, weil sie einen veröffentlichten Auszug liest statt live abzufragen.