Espelli la tua dashboard
Pubblicare su Vibedasher è la normale fine del ciclo: è ciò che mantiene una dashboard ospitata, governata e collegata a dati che qualcuno mantiene. L'espulsione è l'altra porta, ed è aperta di proposito. La dashboard è semplice React e SQL, e in qualsiasi momento puoi prendere l'intero albero ed eseguirlo nella tua app, sul tuo hosting, sotto la tua build.
Non è l'export di un'immagine o di un blob JSON che dovresti reimplementare. Sono i sorgenti che
girano: componenti, pagine, grafici, store, hook, un package.json ricostruito dagli import
reali dell'albero, una configurazione Tailwind, un entry CSS, un tsconfig.json, una
configurazione Vite, un index.html, e un main.tsx che monta il tutto.
npm install && npm run dev lo serve come una sua app React.
L'espulsione è l'opposto dell'incorporazione. Incorporare mette la nostra dashboard renderizzata dentro un iframe nella tua pagina. Espellere ti consegna i sorgenti e ci toglie completamente dal percorso di rendering — noi manteniamo solo il motore dati sottostante. Se la domanda è "questo codice è mio?", l'espulsione è la risposta. Se stai ancora scegliendo tra le due, Incorporare o espellere le mette a confronto.
Le tre chiamate
eject_viz(viz_id, out_dir=...)— l'intero albero più un manifest di cablaggio: il contratto di query, i token del tema, l'entry point e l'ordine delle sue prop, l'elenco dei file, la regione e la corsia dati.eject_viz_files(viz_id, paths=[...])— il contenuto dei file su richiesta. È il seguito quando una risposta è stata paginata, ed è anche il modo economico di leggere un singolo file.eject_instructions()— il riferimento di cablaggio, restituito come dati strutturati invece che come prosa da interpretare. Tutto in questa pagina è una lettura di esso; chiamalo quando vuoi l'originale leggibile dalla macchina.
Passa out_dir, e sappi su quale trasporto sei
Una dashboard reale è nell'ordine di una quarantina di file e mezzo milione di caratteri. Con
out_dir impostato su un percorso assoluto, l'albero viene scritto direttamente su disco e
la risposta resta piccola per quanto grande sia l'albero.
Sul trasporto stdio — l'avvio standard, in cui il tuo client MCP lancia il server come
sottoprocesso locale sotto il tuo utente — quel percorso è il tuo disco, ed è questo che rende
legittimo scriverci. Sul trasporto HTTP sarebbe il disco del server, quindi lì out_dir
viene rifiutato invece di scrivere file in un posto che non puoi leggere riportando
successo. Sull'HTTP la paginazione è l'unica strada.
Senza out_dir, i file vengono impacchettati nella risposta fino a un budget di caratteri e il
resto torna come delivery.pendingPaths. Quell'elenco è il contratto: una risposta con un
pendingPaths non vuoto è una pagina, non un albero. Continua a chiamare eject_viz_files con
esso finché non torna vuoto.
Leggi manifest.dataLane prima di scrivere qualsiasi cablaggio dati
È la prima decisione e quella che non puoi cambiare dopo, perché decide chi può leggere la dashboard.
Corsia A — dataLane.id == "wasm": rende già dati reali
Per una viz pubblica e pubblicata, l'espulsione emette un piccolo runner
(vibedasherWasm.ts) e l'albero rende righe reali su npm run dev senza alcuna credenziale
di alcun tipo: nessuna chiave API, nessun token di incorporazione, nessun backend tuo, e
funziona da qualsiasi origine incluso localhost e un semplice server di file statici.
Il meccanismo: una GET anonima per il piano wasm della viz restituisce un estratto Parquet
prefirmato per dataset; il runner registra ciascuno sotto il suo alias SQL in DuckDB-WASM ed
esegue l'SQL di ogni grafico nel browser del visitatore. La sua unica dipendenza,
@duckdb/duckdb-wasm, è su npm. main.tsx attende il riscaldamento del runner prima di montare,
così una configurazione rotta è un pannello disegnato invece di una griglia di tile vuoti.
Qui non c'è nulla da cablare. Non aggiungerci una credenziale sopra — ti compra un bootstrap rotto in cambio di niente.
Cosa questa corsia non è: serve l'estratto pubblicato, non una query dal vivo, quindi aggiornare ciò che mostra significa ripubblicare. Ed esiste solo finché la viz resta pubblica e pubblicata.
Cosa ottiene ogni visitatore, detto chiaramente. L'estratto ha come chiave il dataset e lo
snapshot, mai una query — lo stesso SELECT con e senza WHERE restituisce lo stesso file
identico. Quindi contiene tutte le righe di ogni dataset che la dashboard legge, ed è un unico
file, lo stesso, per tutti. Un filtro che aggiungi nella pagina cambia ciò che viene disegnato,
mai ciò che è stato consegnato, e i byte sono nel tab di rete in ogni caso. È inerente al mettere
i dati nel browser. Se i visualizzatori devono vedere righe diverse, prendi la corsia B.
Corsia B — dataLane.id == "token": qualsiasi altra viz
Non c'è alcuna corsia senza credenziali e l'espulsione non ne ha emessa una. L'endpoint del
piano wasm è protetto dallo stesso controllo pubblica-e-pubblicata del resto della superficie
anonima, quindi puntarci a mano non aiuta. npm run dev monta comunque, e disegna un pannello
che nomina l'endpoint che gli serve — non fallisce in silenzio e non sostituisce dati finti.
Due cablaggi funzionano, ed entrambi mettono la credenziale su un server che controlli tu:
- La tua app serve una route per il token di incorporazione. Same-origin, che risponde
application/json{"token": "..."}, generato con la chiave API che tiene lato server. Punta l'URL del token di incorporazione dell'albero su di essa e costruisci il client con il token. - Interroghi in codice server fidato con
new Vibedasher({ apiKey })e passi il risultato più in basso, oppure fai da proxy a{ sql, params }attraverso una tua route.
Non mettere mai una chiave API nel codice del browser. Porta l'autorità completa sull'account e non ha scope. Un token di incorporazione con scope è la credenziale lato client; una chiave API no.
Questi due sono anche le sole forme che possono mostrare a un visualizzatore meno righe che a
un altro. Un token di incorporazione può portare filters, che la piattaforma appende a ogni
query che autorizza — lato server, prima di qualsiasi join, aggregazione o LIMIT, dove la
pagina non può allargarli. In codice server fidato restringi tu stesso l'SQL.
Se l'espulsione riporta la corsia token con la ragione no-wasm-extract su una viz che è
pubblica e pubblicata, il dataset semplicemente non ha ancora un estratto. Chiederlo è la sola
cosa che lo costruisce — vedi
La corsia di query wasm.
Ripubblicare non cuoce un estratto, quindi "pubblica ed espelli di nuovo" gira all'infinito.
Installa il client
npm i @vibedasher/client
pip install vibedasher
Il pacchetto npm è @vibedasher/client. Non esiste @vibedasher/sdk e non esisterà mai.
Installa i pacchetti reali invece di copiarli dentro il tuo progetto.
Stili, typecheck e l'App Router
Gli stili sono tre pezzi e ti servono tutti e tre. tailwind.config.js (dark mode con una
strategia a selettore legata a un attributo che l'albero mette sulla propria radice, così che il
dark mode della dashboard sia delimitato indipendentemente da quello della tua app, più una
safelist per le classi assemblate a runtime e quindi invisibili allo scanner di Tailwind);
styles/dashboard.css (l'entry di Tailwind e un blocco :root di token di design come default
a tempo di build); e themeStyles.ts (gli stessi token come stringa che l'app inietta a runtime,
per tema). Il CSS ti dà un primo disegno già a tema; themeStyles.ts ti dà il passaggio dal vivo
tra chiaro e scuro. Se la tua app usa già Tailwind con un dark mode basato su classi, non unire
le configurazioni — una configurazione Tailwind supporta una sola impostazione di dark mode. Su
Tailwind v4, fai riferimento alla configurazione fornita con @config.
Typecheck. npm run typecheck (tsc --noEmit) dovrebbe riportare zero errori su un albero
appena espulso, e due gate lo garantiscono a ogni esecuzione della nostra suite di test — uno fa
il typecheck di un'espulsione generata completa, l'altro installa, fa il typecheck e costruisce
una scritta a mano. Due condizioni delimitano l'affermazione, e nessuna delle due è una riserva.
Vale sotto il tsconfig.json fornito, che imposta strict: false di proposito, perché gli
effetti grafico generati sono scritti su righe di query tipizzate in modo lasco; attivare strict
produrrà errori che saranno poi tuoi da mantenere. E vale per un albero i cui file di branch sono
stati scritti di recente — una dashboard pubblicata abbastanza tempo fa porta file congelati di
una forma più vecchia, due punti della quale è noto che falliscono tsc pur costruendo e
funzionando correttamente, dato che Vite traspila senza fare il typecheck. La soluzione è
ripubblicare, che riscrive i file di branch dalla forma attuale.
Next.js App Router. Ogni modulo è un server component per default. App.tsx e i moduli
stores/ portano già 'use client' nell'espulsione — gli store toccano localStorage a livello
di modulo e andrebbero in crash sul server. Marcare App.tsx mette tutto il suo grafo di import
nel bundle client, quindi nient'altro ha bisogno della direttiva a meno che non importi un
grafico, un componente o uno store direttamente da un server component.
Cosa l'espulsione non ti consegna
- Tutto ciò che è in
manifest.internalDescriptors— metadati di piattaforma, già esclusi dafiles. Non copiarli. - Tutto ciò che è in
manifest.hostOnlyImports— serviti dal bundle del nostro renderer, su nessun registro, deliberatamente assenti. Sostituiscili prima di costruire. - La piattaforma dati. L'espulsione ci toglie dal percorso di rendering, non dal percorso dei dati. Le connessioni, i dataset, gli aggiornamenti, i progetti dbt, la governance e il motore di query sottostanti restano dove sono mantenuti — è la metà della divisione che non stavi cercando di possedere. La corsia senza credenziali è l'unica eccezione, e solo perché legge un estratto pubblicato invece di interrogare dal vivo.