sixty

für Apps, die auf Lovable gebaut sind

Deine App hat keinen Server. Fehler hat sie trotzdem.

Alles, was deine App tut, passiert an zwei Stellen, die ein normales Monitoring-Werkzeug nicht sehen kann: im Browser und in Supabase. Sixty misst beide aus der Seite heraus — die Abfragen und was sie zurückgeben, die Realtime-Kanäle, worauf Leute geklickt haben und ob es funktioniert hat, und wie schnell das alles war —, vergleicht jede Veröffentlichung mit der davor und übergibt die Funde dem Agenten, der den Code geschrieben hat.

Was es misst

Jede Supabase-Abfrage, die die Seite macht
Wie viele pro Interaktion laufen, wie viele Zeilen jede zurückgibt, wie groß die Antwort ist und wie lange sie gedauert hat. Hier sitzt „es ist langsam geworden“ fast immer.
Wie schnell die Seite ist, pro Route
LCP, INP, CLS und TTFB am echten p75 über alle, die sie geladen haben — kein Laborwert von einer Maschine. Nach Land aufgeschlüsselt, weil eine Seite, die bei dir in Ordnung ist, dort, wo die Latenz schlechter ist, unbenutzbar sein kann.
Worauf Leute geklickt haben, und ob es funktioniert hat
Klicks, die nichts getan haben, wiederholtes Klicken auf dasselbe Element, und Interaktionen, die die Seite hunderte Male neu zeichnen.
Auth, Storage, Edge Functions und Realtime
Eine Supabase-App besteht aus vier Diensten, nicht aus einem, und der Agent versteht, was jeder Endpunkt tut, statt nur, was er gekostet hat — eine abgelehnte Anmeldung, eine fehlende Spalte, ein zurückgewiesener Schreibvorgang und ein Kanal, der sich nicht abonnieren konnte, kommen also jeweils als das an, was sie sind, statt als anonyme fehlgeschlagene Anfrage.
Der Code, bevor er läuft
Ein Button ohne Handler, ein Effekt, dessen Abhängigkeiten garantieren, dass er ewig läuft, ein Abonnement, das nie abgebaut wird. Diese senden zur Laufzeit nichts — ein Handler, der nie angehängt wurde, kann nicht gemessen werden —, also werden sie zur Build-Zeit aus dem Quellcode gelesen und danach sortiert, wie viel Verkehr die Datei tatsächlich bedient.

Was es findet

Jedes davon wird gegen das Release davor verglichen, der Befund benennt also die Änderung und nicht den Tag.

Eine Abfrage, die angefangen hat, alles zurückzugeben

Ein Filter geht bei einer Umschreibung verloren, und eine Abfrage, die 30 Zeilen zurückgab, gibt 30.000 zurück. Gegen die Handvoll Zeilen in deinem Projekt ist sie sofort da, es sieht also nichts falsch aus, bis echte Daten dahinterstehen.

Ein N+1, das in einem Render entsteht

Ein Laden wandert in eine Liste, und aus einer Abfrage werden vierzig. Jede ist schnell, keine einzelne Anfrage sieht also falsch aus — falsch ist nur die Anzahl, und die Anzahl ist genau das, was dir nichts anderes zeigen wird, das du installieren kannst.

Nutzer, die die Zeilen anderer sehen — oder gar keine

Wenn eine Row-Level-Security-Regel fehlt oder falsch ist, wirft Postgres keinen Fehler. Es gibt Zeilen zurück, die nicht da sein sollten, oder gar keine, und die Seite rendert leer. Sixty sieht beide Hälften: die Statements, die die Datenbank unter einer Regel ablehnt, und die, die sie zulässt und die leer zurückkommen, wo früher Zeilen kamen.

Eine Seite, die nie fertig lädt

Ein Ladekreis, der zwölf Sekunden nach seinem Erscheinen immer noch da ist — meist eine Anfrage, die in einem catch gescheitert ist, oder ein Lade-Flag, das auf true gesetzt und nie zurückgesetzt wurde.

Das Schema, das unter dem Code wegdriftet

Eine Spalte, Tabelle oder Beziehung, die der Code erwartet und die Datenbank nicht mehr hat. Es scheitert zur Laufzeit, im Browser, bei dem, der diese Seite geladen hat.

Fehler, die niemand gemeldet hat

Gruppiert danach, wo im Code sie herkamen, einschließlich der React-Fehler, die nichts zum Absturz bringen — die Error Boundary fängt sie, zeigt eine leere Fläche und protokolliert.

Derselbe Realtime-Kanal, dreifach abonniert

Ein Effekt öffnet ein Abonnement und baut es nie ab, jedes Render fügt also eines hinzu. Nichts wirft und nichts ist langsam: die Person sieht einfach jede neue Nachricht dreimal ankommen, während die Verbindungszahl auf das Limit zuläuft, das die Funktion für alle abschaltet.

Ein Button, der messbar nichts tut

Geklickt, und keine Anfrage ging raus, keine Daten änderten sich, keine Seite bewegte sich — meist ein Handler, der nie verdrahtet wurde. Dazu das wiederholte Klicken danach, das ist, was Leute tun, wenn der erste Klick nichts bewirkt zu haben schien.

Ein Klick, der die Seite hunderte Male neu zeichnet

Eine Render-Schleife. Sie wirft nie einen Fehler und lässt nie eine Anfrage scheitern; sie leert den Akku dessen, der das Telefon in der Hand hält.

Sitzungen, die abgewiesen werden

Ein Anteil der Aufrufe eines Endpunkts kommt mit 401 oder 403 zurück, oder ein Token war abgelaufen, wo eines verlangt wurde. In einer App ohne Server ist das die einzige Stelle, an der eine Abweisung überhaupt sichtbar ist.

Was in deinem Verlauf landet

Kein Dashboard zum Lesen. Eine Karte pro Befund, mit den Zahlen, dem Release, das sie verändert hat, und den Belegen, die dein Coding-Agent braucht, um die Lösung zu schreiben.

Rekonstruiert. Das sind Fehler, die der Detektor aus einer veröffentlichten Supabase-App tatsächlich erzeugt — aber anders als die Node-Beispiele sind sie nicht die Ausgabe eines Skripts, das du laufen lassen kannst, also sind sie gezeichnet statt zitiert.

Zeilenselect:orders
30 Zeilen30.000 Zeilen1000×

Diese Abfrage gibt jede Bestellung der Tabelle zurück und filtert sie im Browser. Sie wurde gegen ein Projekt mit vierzig Zeilen geschrieben, wo das sofort da war.

auf /orders, seit der vorletzten Veröffentlichung

gibt nichts zurückselect:invoices
12 Zeilen0 Zeilen

Dieselbe Abfrage, die gestern Rechnungen zurückgab, gibt heute keine zurück. Nichts ist gescheitert: eine Regel hat angefangen, alles herauszufiltern, und die Seite rendert leer.

auf /invoices, seit der letzten Veröffentlichung

Wie es installiert wird

Das installierst du nicht von Hand. Füge einen Prompt in den Chat von Lovable ein, und er verdrahtet den Agenten — ein Vite-Plugin, ein init-Aufruf und eine Route, die Telemetrie weiterleitet, damit nie ein Schlüssel in deinem Bundle landet. Wenn du dich anmeldest, wird dieser Prompt mit deinem Schlüssel darin für dich geschrieben.

npm install @sixty-sh/supabase

// vite.config.ts
import drift from '@sixty-sh/supabase/vite'
export default defineConfig({ plugins: [react(), drift()] })

// src/integrations/supabase/client.ts — the file every Lovable app has
import { withSixty } from '@sixty-sh/supabase'

export const supabase = withSixty(createClient(URL, ANON_KEY), {
  key: 'sixty_pk_…',
  service: 'my-app',
  endpoint: 'https://ingest.sixty.sh',
})

Dann veröffentliche zweimal. Der Vergleich ist an Veröffentlichungen verankert und nicht an die Uhr, der erste Befund kommt also nach deiner nächsten — es gibt nichts, womit man eine einzelne Version vergleichen könnte.

Was es nicht tut

  • Befunde aus einem veröffentlichten Build zeigen auf die Abfrage und die Route, nicht auf eine Zeile deines Quellcodes. Produktions-Bundles sind minifiziert, und die Sourcemap, die das rückgängig machen würde, wird noch nicht gelesen — du bekommst also „diese Abfrage auf dieser Seite“ statt „diese Datei, Zeile 40“.
  • Der Lovable-Preview reicht nicht. Er läuft auf einem Dev-Server ohne fingerabdruckbehaftete Assets, es gibt also keine Version, an der ein Vergleich verankert werden könnte — der Vergleich braucht zwei echte Veröffentlichungen.
  • Hier wird kein Server beobachtet, weil du keinen hast. Wenn du später eigene Edge Functions hinzufügst, brauchen die den Node-Agenten, um sichtbar zu sein.

Falls du wegen einer dieser Sachen hier bist

Finde heraus, was deine letzte Änderung angerichtet hat.

Probier es aus!

Du baust etwas anderes? Sieh dir Node-Dienste oder React-Native-Apps an — diese Seiten sind anders, und was wir sehen können, auch.

Performance-Monitoring für Lovable- und Supabase-Apps — Sixty