[{"data":1,"prerenderedAt":1328},["ShallowReactive",2],{"blog-de-invalid-input-syntax-for-type-uuid":3,"blog-index-de":798},{"id":4,"title":5,"body":6,"category":755,"cover":756,"coverAlt":757,"description":758,"draft":759,"extension":760,"faq":761,"image":777,"keywords":778,"meta":787,"navigation":788,"ogTitle":5,"path":789,"published":790,"seo":791,"stem":792,"tldr":793,"updated":790,"__hash__":797},"blog_de\u002Fblog\u002Finvalid-input-syntax-for-type-uuid.md","Supabase \"invalid input syntax for type uuid\": was im Zitat steht",{"type":7,"value":8,"toc":743},"minimark",[9,13,24,31,37,42,49,83,86,190,194,197,328,331,335,341,386,397,403,406,457,461,469,477,487,508,514,517,522,526,529,542,558,563,567,570,607,615,619,622,631,651,660,678,682,736],[10,11,12],"p",{},"Du öffnest das Dashboard deiner App, und die Liste der Projekte bleibt einen\nMoment leer und füllt sich dann. Oder sie bleibt leer. So oder so steht in der\nBrowserkonsole eine rote Zeile, und die Anfrage dahinter hat so geantwortet:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","{\n  \"code\": \"22P02\",\n  \"details\": null,\n  \"hint\": null,\n  \"message\": \"invalid input syntax for type uuid: \\\"undefined\\\"\"\n}\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,30],{},"Supabase \"invalid input syntax for type uuid\" heißt: Postgres hat einen Wert\nbekommen, der keine uuid ist, für eine Spalte, die nur uuids enthält, und hat\ndie ganze Anfrage abgelehnt. Der Teil in Anführungszeichen ist das, was deine App\ngeschickt hat. Hier ist das das Wort ",[21,28,29],{},"undefined",": Die Abfrage lief, bevor es die\nID gab, die sie brauchte.",[10,32,33,34,36],{},"Die schnellen Lösungen, die für diesen Fehler kursieren, lauten: die Spalte auf\n",[21,35,19],{}," umstellen oder den Wert casten. Beide lassen die Meldung verschwinden.\nKeine von beiden gibt der Abfrage ihre ID, also fragt die Seite weiter nach dem\nFalschen und sagt es dir nicht mehr.",[38,39,41],"h2",{"id":40},"was-bedeutet-invalid-input-syntax-for-type-uuid","Was bedeutet \"invalid input syntax for type uuid\"?",[10,43,44,45,48],{},"Ein Wert auf dem Weg in eine ",[21,46,47],{},"uuid","-Spalte war nicht so geschrieben, wie man eine\nuuid schreibt, also hat Postgres angehalten, bevor es irgendetwas ausgeführt hat.\nKeine Zeile wurde gelesen und keine geändert.",[10,50,51,52,55,56,59,60,63,64,67,68,71,72,75,76,82],{},"Eine uuid ist eine ID in einer festen Form: 32 Zeichen von ",[21,53,54],{},"0"," bis ",[21,57,58],{},"9"," und ",[21,61,62],{},"a"," bis\n",[21,65,66],{},"f",", geschrieben in Gruppen von 8, 4, 4, 4 und 12, zum Beispiel\n",[21,69,70],{},"3f2b8c1e-9a4d-4e7b-b1c2-5d6e7f8a9b0c",". Supabase gibt jedem angemeldeten Nutzer\nso eine ID, und eine Spalte, die festhält, welche Zeile wem gehört, etwa\n",[21,73,74],{},"user_id",", enthält dieselbe Art von Wert. Postgres'\n",[62,77,81],{"href":78,"rel":79},"https:\u002F\u002Fgithub.com\u002Fpostgres\u002Fpostgres\u002Fblob\u002Fmaster\u002Fsrc\u002Fbackend\u002Futils\u002Fadt\u002Fuuid.c",[80],"nofollow","Leser für diesen Typ","\nakzeptiert \"a series of 32 hexadecimal digits with an optional dash after each\ngroup of 4 hexadecimal digits, and optionally surrounded by {}\". Alles andere\nendet mit dieser Meldung, und die Eingabe wird zitiert.",[10,84,85],{},"Stell dir die Spalte als Sortiermaschine vor, die nur eine Art Etikett lesen kann:\neinen Code in diesen fünf Gruppen. Deine App hat ein Paket aufs Band gelegt, auf\ndem ein Wort steht, wo der Code hingehört. Die Maschine hat das Band angehalten\nund dir das Wort vorgelesen.",[87,88,89,105],"table",{},[90,91,92],"thead",{},[93,94,95,99,102],"tr",{},[96,97,98],"th",{},"Feld",[96,100,101],{},"Beispiel",[96,103,104],{},"Was es dir sagt",[106,107,108,133,148,167],"tbody",{},[93,109,110,115,120],{},[111,112,113],"td",{},[21,114,21],{},[111,116,117],{},[21,118,119],{},"22P02",[111,121,122,123,128,129,132],{},"Postgres' Code für diesen Fehler, in ",[62,124,127],{"href":125,"rel":126},"https:\u002F\u002Fgithub.com\u002Fpostgres\u002Fpostgres\u002Fblob\u002Fmaster\u002Fsrc\u002Fbackend\u002Futils\u002Ferrcodes.txt",[80],"seiner Liste der Codes"," ",[21,130,131],{},"invalid_text_representation"," genannt",[93,134,135,140,145],{},[111,136,137],{},[21,138,139],{},"message",[111,141,142],{},[21,143,144],{},"invalid input syntax for type uuid: \"undefined\"",[111,146,147],{},"Den Typ, den Postgres erwartet hat, und den genauen Wert, den es bekommen hat",[93,149,150,159,164],{},[111,151,152,155,156],{},[21,153,154],{},"details",", ",[21,157,158],{},"hint",[111,160,161],{},[21,162,163],{},"null",[111,165,166],{},"Mehr sagt Postgres zu diesem Fehler nicht",[93,168,169,172,177],{},[111,170,171],{},"HTTP-Status",[111,173,174],{},[21,175,176],{},"400 Bad Request",[111,178,179,180,183,184,189],{},"So antwortet PostgREST, der Teil von Supabase, der ",[21,181,182],{},"supabase.from(...)","-Aufrufe in SQL übersetzt, auf jeden Code ohne eigenen Status (",[62,185,188],{"href":186,"rel":187},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FError.hs",[80],"sein Code",")",[38,191,193],{"id":192},"lies-was-in-den-anführungszeichen-steht","Lies, was in den Anführungszeichen steht",[10,195,196],{},"Der zitierte Wert ist die nützliche Hälfte der Meldung. Er ist genau das, was in\nder Datenbank angekommen ist, und jede Form, die er annimmt, zeigt auf eine andere\nStelle deiner App.",[87,198,199,212],{},[90,200,201],{},[93,202,203,206,209],{},[96,204,205],{},"In den Anführungszeichen",[96,207,208],{},"Was deine App geschickt hat",[96,210,211],{},"Wo du suchen solltest",[106,213,214,227,244,272,292,309],{},[93,215,216,221,224],{},[111,217,218],{},[21,219,220],{},"\"undefined\"",[111,222,223],{},"eine Variable, die noch keinen Wert hatte",[111,225,226],{},"eine Abfrage, die lief, bevor der Nutzer oder die ID der Seite geladen war; die nächsten zwei Abschnitte",[93,228,229,234,237],{},[111,230,231],{},[21,232,233],{},"\"\"",[111,235,236],{},"einen leeren String",[111,238,239,240,243],{},"ein Wert, der im Zustand deiner App mit ",[21,241,242],{},"''"," beginnt, oder ein leer gelassenes Formularfeld",[93,245,246,251,260],{},[111,247,248],{},[21,249,250],{},"\"null\"",[111,252,253,255,256,259],{},[21,254,163],{},", an ",[21,257,258],{},".eq()"," übergeben",[111,261,262,264,265,267,268,271],{},[21,263,258],{}," schreibt auch ",[21,266,163],{}," als Wort. Um Zeilen zu finden, in denen die Spalte leer ist, sagt die Dokumentation von supabase-js \"use ",[21,269,270],{},".is()"," instead\"",[93,273,274,279,282],{},[111,275,276],{},[21,277,278],{},"\"[object Object]\"",[111,280,281],{},"ein ganzes Objekt, wo seine ID hingehörte",[111,283,284,287,288,291],{},[21,285,286],{},"user"," statt ",[21,289,290],{},"user.id"," übergeben. Diesen Text schreibt JavaScript für jedes Objekt, das in einen String verwandelt wird",[93,293,294,299,302],{},[111,295,296],{},[21,297,298],{},"\"user_…\"",[111,300,301],{},"eine ID von einem anderen Anmeldedienst als dem von Supabase",[111,303,304,305,308],{},"Die IDs von Clerk beginnen mit ",[21,306,307],{},"user_"," und sind keine uuids. Der Abschnitt übers Umstellen der Spalte behandelt diesen Fall",[93,310,311,314,317],{},[111,312,313],{},"eine Zahl oder ein Name",[111,315,316],{},"einen Teil der Seitenadresse",[111,318,319,320,323,324,327],{},"eine URL wie ",[21,321,322],{},"\u002Fprojects\u002F42"," oder ",[21,325,326],{},"\u002Fprojects\u002Fmy-first-app",", als ID gelesen",[10,329,330],{},"Kommt der Fehler bei jedem Besuch, such nach einem Namen, unter dem nichts steht.\nKommt er nur beim ersten Aufbau der Seite, such nach einem Wert, der noch nicht\ngeladen war.",[38,332,334],{"id":333},"warum-schickt-supabase-js-das-wort-undefined","Warum schickt supabase-js das Wort undefined?",[10,336,337,338,340],{},"Weil es jeden Filter als Text in die Adresse der Anfrage schreibt und JavaScript\neinen fehlenden Wert als das Wort ",[21,339,29],{}," schreibt.",[10,342,343,344,347,348,351,352,357,358,361,362,365,366,369,370,375,376,378,379,382,383,385],{},"Ein Aufruf wie ",[21,345,346],{},".eq('user_id', user?.id)"," wird zu ",[21,349,350],{},"?user_id=eq."," und dahinter\ndem Wert. Der\n",[62,353,356],{"href":354,"rel":355},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fsupabase-js\u002Fblob\u002Fmaster\u002Fpackages\u002Fcore\u002Fpostgrest-js\u002Fsrc\u002FPostgrestFilterBuilder.ts",[80],"Quellcode der Bibliothek","\nbaut das aus einer Vorlage, ",[21,359,360],{},"`eq.${value}`",", und ein Kommentar weiter unten in\nderselben Datei sagt, was das mit einem fehlenden Wert macht: Er würde \"show up\nas ",[21,363,364],{},"?column=eq.undefined","\". PostgREST liest alles nach ",[21,367,368],{},"eq."," als reinen Text, und\n",[62,371,374],{"href":372,"rel":373},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FApiRequest\u002FQueryParams.hs",[80],"sein Parser","\nbehandelt ",[21,377,163],{}," nur nach ",[21,380,381],{},"is."," als Schlüsselwort. Postgres bekommt die neun\nBuchstaben von ",[21,384,29],{}," und versucht, sie als uuid zu lesen.",[10,387,388,391,392,396],{},[21,389,390],{},".rpc()"," geht den umgekehrten Weg. Seine Argumente reisen als JSON, und JSON lässt\neinen undefined-Wert ganz weg. Ein Funktionsaufruf verliert also das Argument,\nstatt das Wort zu schicken, und Supabase antwortet mit\n",[62,393,395],{"href":394},"\u002Fblog\u002Fsupabase-function-not-found","Could not find the function",".",[398,399],"diagram",{"alt":400,"caption":401,"src":402},"Eine Filterkarte mit user_id und einem bernsteinfarbenen Kästchen, in dem undefined steht. Ein Pfeil führt zu einem Anfragestreifen, der auf eq.undefined endet, dann zum Wort in Anführungszeichen auf einem Anhänger über einem Codefeld aus fünf Kästchen, in das es nicht passt, und hinunter zu einer Plakette mit 22P02 und 400.","supabase-js setzt den Wert des Filters als Text in die Anfrage. Ein fehlender Wert kommt als das Wort undefined an, und die uuid-Spalte lehnt ihn ab.","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fundefined-becomes-a-word-1600x560.png",[10,404,405],{},"In einer React-App suchst du den fehlenden Wert an drei Stellen:",[407,408,409,431,451],"ul",{},[410,411,412,416,417,420,421,423,424,427,428,430],"li",{},[413,414,415],"strong",{},"Der Nutzer ist noch nicht geladen."," Supabase liest die angemeldete Sitzung\nasynchron (",[21,418,419],{},"await supabase.auth.getSession()","). Beim ersten Aufbau deiner Seite\nist ein ",[21,422,286],{}," im Zustand also noch leer und ",[21,425,426],{},"user?.id"," ist ",[21,429,29],{},". Eine\nAbfrage, die bei diesem ersten Aufbau startet, schickt genau das.",[410,432,433,436,437,440,441,444,445,448,449,396],{},[413,434,435],{},"Die ID hat einen anderen Namen."," Eine Route wie ",[21,438,439],{},"\u002Fprojects\u002F:projectId"," legt\nden Wert unter ",[21,442,443],{},"projectId"," ab, und eine Seite, die ",[21,446,447],{},"id"," liest, bekommt bei jedem\nBesuch ",[21,450,29],{},[410,452,453,456],{},[413,454,455],{},"Die ID kommt aus Daten, die noch unterwegs sind."," Eine ID aus dem Ergebnis\neiner anderen Abfrage, gelesen, bevor diese Abfrage geantwortet hat.",[38,458,460],{"id":459},"halte-die-abfrage-zurück-bis-es-die-id-gibt","Halte die Abfrage zurück, bis es die ID gibt",[10,462,463,464,59,466,468],{},"Prüf vor dem Aufruf, ob die ID da ist, und lass die Seite ihren Ladezustand\nzeigen, bis sie ankommt. Für ",[21,465,220],{},[21,467,233],{}," ist das die ganze Lösung.",[14,470,475],{"className":471,"code":473,"language":474,"meta":23},[472],"language-js","useEffect(() => {\n  if (!user?.id) return\n\n  supabase\n    .from('projects')\n    .select('*')\n    .eq('user_id', user.id)\n    .then(({ data, error }) => {\n      if (!error) setProjects(data)\n    })\n}, [user?.id])\n","js",[21,476,473],{"__ignoreMap":23},[10,478,479,480,483,484,486],{},"Das ",[21,481,482],{},"return"," schickt nichts, solange die ID fehlt, und ",[21,485,426],{}," in der Liste am\nEnde lässt den Effect erneut laufen, sobald die ID auftaucht. An der\nSortiermaschine heißt das: warten, bis der Code auf dem Etikett steht, bevor das\nPaket aufs Band kommt.",[10,488,489,490,493,494,497,498,503,504,507],{},"Wenn deine App mit TanStack Query lädt (dem ",[21,491,492],{},"useQuery","-Hook), ist die Option\n",[21,495,496],{},"enabled"," derselbe Riegel.\n",[62,499,502],{"href":500,"rel":501},"https:\u002F\u002Ftanstack.com\u002Fquery\u002Flatest\u002Fdocs\u002Fframework\u002Freact\u002Fguides\u002Fdependent-queries",[80],"Seine Anleitung zu abhängigen Abfragen","\nsetzt ",[21,505,506],{},"enabled: !!userId"," mit dem Hinweis \"The query will not execute until the\nuserId exists\".",[14,509,512],{"className":510,"code":511,"language":474,"meta":23},[472],"const { data: projects } = useQuery({\n  queryKey: ['projects', user?.id],\n  queryFn: async () => {\n    const { data, error } = await supabase\n      .from('projects')\n      .select('*')\n      .eq('user_id', user.id)\n    if (error) throw error\n    return data\n  },\n  enabled: !!user?.id,\n})\n",[21,513,511],{"__ignoreMap":23},[10,515,516],{},"Wenn du per Prompt baust, bitte in einem Satz darum. Lass ihn auf Englisch, denn\nin dieser Sprache denken diese Werkzeuge: \"Don't run the projects query until\nuser.id exists, and show the loading state until then.\"",[398,518],{"alt":519,"caption":520,"src":521},"Zwei Reihen mit je zwei nummerierten Aufbauten einer Seite. In der oberen Reihe hat der erste Aufbau eine leere ID, und seine Anfrage endet an einer bernsteinfarbenen 22P02-Plakette; der zweite hat die ID und endet mit einem Haken. In der unteren Reihe, markiert mit if (!id) return, hält der erste Aufbau an einem Pausenzeichen und schickt nichts, und erst der zweite schickt eine Anfrage, die mit einem Haken endet.","Ohne die Prüfung schickt der erste Aufbau eine Anfrage ohne ID. Mit ihr wartet der erste Aufbau, und die einzige Anfrage ist die, die funktioniert.","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fthe-guard-holds-the-query-1600x640.png",[38,523,525],{"id":524},"solltest-du-die-spalte-auf-text-umstellen","Solltest du die Spalte auf text umstellen?",[10,527,528],{},"Nein, außer die gespeicherten IDs sind gar keine uuids. Die Spalte umzustellen\noder sie in einer Abfrage nach text zu casten, entfernt die Prüfung, die den\nFehler ausgelöst hat, und lässt die fehlende ID, wo sie war.",[10,530,531,532,535,536,538,539,541],{},"Verfolg dieselbe Anfrage nach der Änderung. ",[21,533,534],{},"user_id=eq.undefined"," ist jetzt eine\ngültige Frage, also vergleicht Postgres das Wort ",[21,537,29],{}," mit jeder ID in der\nSpalte, findet keinen Treffer und gibt eine leere Liste zurück. Deine Seite zeigt\n\"Noch keine Projekte\" jemandem, der zehn hat, und in der Konsole steht nichts, was\nes erklärt. Beim Schreiben geht es weiter: Die Zeile wird mit ",[21,540,29],{}," an der\nStelle gespeichert, wo die ID ihres Besitzers hingehört, und eine Abfrage für den\nechten Besitzer findet sie nie. An der Sortiermaschine heißt das: den\nEtikettenleser abstecken. Das Paket läuft durch, passt zu keiner Adresse und wird\nnie zugestellt.",[10,543,544,545,547,548,553,554,557],{},"Der eine Fall, in dem die Spalte das Richtige zum Ändern ist, ist die Zeile\n",[21,546,298],{}," in der Tabelle oben. Die IDs von Clerk sind Text, und\n",[62,549,552],{"href":550,"rel":551},"https:\u002F\u002Fclerk.com\u002Fdocs\u002Fguides\u002Fdevelopment\u002Fintegrations\u002Fdatabases\u002Fsupabase",[80],"Clerks eigene Anleitung zu Supabase","\nlegt die Spalte als ",[21,555,556],{},"user_id text not null default auth.jwt()->>'sub'"," an. Das ist\nein anderes Problem: Die Tabelle wurde für die IDs von Supabase gebaut und bekommt\ndie eines anderen Dienstes.",[398,559],{"alt":560,"caption":561,"src":562},"Dieselbe Anfrage, user_id=eq.undefined, an zwei Spalten. Die mit uuid markierte Spalte lehnt sie mit einer bernsteinfarbenen Plakette ab, auf der 22P02 und 400 steht. Die mit text markierte Spalte vergleicht das Wort mit jeder Zeile, findet keine und gibt eine leere Liste zurück, ein gestricheltes bernsteinfarbenes Kästchen neben einem schlichten 200.","Eine uuid-Spalte lehnt das Wort ab und sagt es. Eine text-Spalte nimmt es an, findet keine Zeile und gibt deiner Seite eine leere Liste ohne Fehler.","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fa-text-column-hides-it-1600x660.png",[38,564,566],{"id":565},"hält-die-id-in-deinem-filter-fremde-zeilen-draußen","Hält die ID in deinem Filter fremde Zeilen draußen?",[10,568,569],{},"Nein. Der Filter entscheidet, nach welchen Zeilen deine Seite fragt. Welche\nZeilen ein Besucher lesen darf, entscheidet Row Level Security, die Regeln pro\nZeile, die Supabase bei jeder Anfrage mit deinem öffentlichen Schlüssel prüft, und\njeder kann deine Anfrage mit einer anderen ID oder ganz ohne erneut schicken.",[10,571,572,573,576,577,581,582,584,585,588,589,592,593,596,597,601,602,606],{},"Eine Methode von supabase-js zeigt den Unterschied. ",[21,574,575],{},".match()"," nimmt mehrere\nSpalten auf einmal, und\n",[62,578,580],{"href":354,"rel":579},[80],"ihr Quellcode","\nlässt jede Spalte weg, deren Wert ",[21,583,29],{}," ist, bevor die Anfrage gebaut wird.\nDafür war der Kommentar über ",[21,586,587],{},"eq.undefined"," da. Ein\n",[21,590,591],{},".match({ user_id: user?.id })",", bevor der Nutzer geladen ist, schickt also gar\nkeinen Filter, löst keinen Fehler aus und liefert jede Zeile, die die Regeln der\nTabelle diesem Besucher zu lesen erlauben. Häng ",[21,594,595],{},".single()"," an diesen Aufruf, und\ner scheitert anders, mit\n",[62,598,600],{"href":599},"\u002Fblog\u002Fsupabase-single-row-error","JSON object requested, multiple (or no) rows returned",",\nweil mehr als eine Zeile zurückkam. Mit eingeschalteten Regeln sind diese Zeilen\nimmer noch nur die des Besuchers. Mit ausgeschalteten sind es die ganze Tabelle,\nund\n",[62,603,605],{"href":604},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","die Regeln für jede Tabelle einschalten","\nbeschreibt den Schalter und die erste Regel.",[10,608,609,610,614],{},"Ob eine Tabelle einem Fremden Zeilen gibt, siehst du von außen. Unser\n",[62,611,613],{"href":612},"\u002Fsecurity-scanner","kostenloser Scan"," liest deine Live-App mit demselben\nöffentlichen Schlüssel, den ein Besucher bekommt, meldet, welche Tabellen mit\nZeilen antworten, und braucht kein Konto.",[38,616,618],{"id":617},"bevor-du-eine-spalte-änderst-die-deine-app-liest","Bevor du eine Spalte änderst, die deine App liest",[10,620,621],{},"Behalte eine Kopie der Datenbank von vor der Änderung eines Spaltentyps, und\nerfahre es, wenn eine Tabelle anfängt, Fremden zu antworten.",[10,623,624],{},[413,625,626,630],{},[62,627,629],{"href":628},"\u002Fsupabase-backups","Reeve Care"," bewahrt eine Kopie deiner Supabase-Datenbank auf:",[407,632,633,636,639,642,645,648],{},[410,634,635],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[410,637,638],{},"jede Tabelle mit ihren Zeilen, wie sie waren, bevor du den Typ einer Spalte geändert hast",[410,640,641],{},"jede Kopie wird geprüft, bevor sie zählt, indem die Zeilen in jeder Tabelle gezählt werden",[410,643,644],{},"auch deine hochgeladenen Dateien, sobald du eine Storage-Zugangsberechtigung verbindest",[410,646,647],{},"Wiederherstellung mit einem Klick, vorher wird eine Sicherheitskopie des aktuellen Stands angelegt",[410,649,650],{},"alles, was Monitor macht",[10,652,653],{},[413,654,655,659],{},[62,656,658],{"href":657},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft weiter von außen:",[407,661,662,665,668,675],{},[410,663,664],{},"ob deine App erreichbar ist, jede Minute geprüft",[410,666,667],{},"der vollständige Sicherheitscheck jede Stunde, für bis zu drei Apps",[410,669,670,671,674],{},"eine Nachricht, wenn sich ein Ergebnis ",[413,672,673],{},"ändert",", sodass eine Tabelle, die nach einem Deploy Fremden antwortet, dich erreicht, ohne dass du nachsehen musst",[410,676,677],{},"ein monatlicher Bericht in klarer Sprache über das, was er gesehen hat",[38,679,681],{"id":680},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[683,684,685],"key-takeaways",{},[407,686,687,690,705,713,721,730],{},[410,688,689],{},"Lies den Wert in den Anführungszeichen. Er ist genau das, was deine App geschickt hat.",[410,691,692,693,323,695,697,698,323,701,704],{},"Bei ",[21,694,220],{},[21,696,233],{}," halte die Abfrage zurück, bis es die ID gibt: ",[21,699,700],{},"if (!user?.id) return",[21,702,703],{},"enabled: !!user?.id"," in TanStack Query.",[410,706,692,707,709,710,396],{},[21,708,250],{}," findest du leere Werte mit ",[21,711,712],{},".is('column', null)",[410,714,692,715,717,718,720],{},[21,716,278],{}," übergib die ",[21,719,447],{}," des Objekts.",[410,722,723,724,726,727,729],{},"Lass die Spalte eine ",[21,725,47],{}," und stell sie nur auf ",[21,728,19],{}," um, wenn die IDs von einem Dienst kommen, der keine uuids vergibt, etwa Clerk.",[410,731,732,733,735],{},"Liefert ein ",[21,734,575],{},"-Aufruf mit fehlendem Wert Zeilen anderer Leute, schalte Row Level Security für diese Tabelle ein.",[10,737,738,739,742],{},"Fang mit den Anführungszeichen an, denn der Wert darin zeigt auf die Stelle\ndeiner App, die ihn geschickt hat. Ändert die Lösung, die man dir vorschlägt, den\nTyp einer Spalte,\n",[62,740,741],{"href":628},"behalte eine Kopie der Datenbank"," von vor der Änderung.",{"title":23,"searchDepth":744,"depth":744,"links":745},3,[746,748,749,750,751,752,753,754],{"id":40,"depth":747,"text":41},2,{"id":192,"depth":747,"text":193},{"id":333,"depth":747,"text":334},{"id":459,"depth":747,"text":460},{"id":524,"depth":747,"text":525},{"id":565,"depth":747,"text":566},{"id":617,"depth":747,"text":618},{"id":680,"depth":747,"text":681},"Sicherheitsgrundlagen","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcover-1200x630.png","Ein Paketetikett mit einem Codefeld aus fünf Kästchen, davor ein Anhänger mit undefined in Bernstein, zu lang, um hineinzupassen.","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.",false,"md",[762,765,768,771,774],{"q":763,"a":764},"Was bedeutet invalid input syntax for type uuid?","Postgres sollte einen Wert als uuid lesen, und der Wert ist nicht wie eine uuid geschrieben. Also hat es die Anfrage abgelehnt, bevor irgendetwas gelesen oder geändert wurde. Der Code ist 22P02, eine Supabase-App bekommt ihn als HTTP 400, und der Text in Anführungszeichen am Ende der Meldung ist genau das, was deine App geschickt hat.",{"q":766,"a":767},"Warum ist meine ID undefined?","Weil die Abfrage lief, bevor es den Wert gab, oder weil sie einen Namen liest, unter dem nichts steht. Beim ersten Aufbau einer Seite ist der angemeldete Nutzer womöglich noch nicht gelesen, also ist user?.id undefined, und eine Route, die den Wert projectId nennt, liefert einer Seite, die id liest, jedes Mal undefined. supabase-js schreibt den fehlenden Wert als das Wort undefined in die Anfrage.",{"q":769,"a":770},"Soll ich die Spalte auf text umstellen oder den Wert casten?","Nicht, um diesen Fehler zu beheben. Eine text-Spalte nimmt das Wort undefined an, vergleicht es mit jeder ID, findet keine, und deine Seite zeigt eine leere Liste ganz ohne Fehler. Stell die Spalte nur um, wenn die gespeicherten IDs gar keine uuids sind, etwa Nutzer-IDs von Clerk, die Clerks eigene Supabase-Anleitung in einer text-Spalte ablegt.",{"q":772,"a":773},"Warum passiert das nur beim ersten Laden?","Weil beim nächsten Aufbau die ID da ist und dieselbe Abfrage funktioniert. Die Seite füllt sich vielleicht einen Moment später und sieht gut aus, während jeder Besuch trotzdem eine fehlgeschlagene Anfrage mit undefined darin schickt. Halte die Abfrage zurück, bis die ID existiert, und diese Anfrage wird nie geschickt.",{"q":775,"a":776},"Wie verhindere ich, dass die Abfrage zu früh läuft?","Steig vor dem Aufruf aus, solange die ID fehlt, zum Beispiel mit if (!user?.id) return oben im Effect, und trag user?.id als Abhängigkeit des Effects ein, damit er wieder läuft, sobald die ID auftaucht. Mit TanStack Query setzt du enabled: !!user?.id. Zeig in der Zwischenzeit deinen Ladezustand.","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",[779,780,781,782,783,784,785,786],"invalid input syntax for type uuid","invalid input syntax for type uuid undefined","supabase uuid fehler","postgres 22p02","supabase ungültige uuid","supabase id undefined","invalid input syntax for type uuid null","supabase eq undefined",{},true,"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","2026-10-25",{"title":5,"description":758},"blog\u002Finvalid-input-syntax-for-type-uuid",[794,795,796],"Supabase \"invalid input syntax for type uuid\" (Postgres-Code 22P02, HTTP 400 in deiner App) heißt: Eine uuid-Spalte hat einen Wert bekommen, der keine uuid ist. Der Text in Anführungszeichen ist genau das, was deine App geschickt hat.","\"undefined\" in den Anführungszeichen heißt: Die Abfrage lief, bevor es die ID gab, denn supabase-js schreibt einen fehlenden Wert als genau dieses Wort in die Anfrage. Halte die Abfrage zurück, bis die ID da ist.","Lass die Spalte eine uuid. Wer sie auf text umstellt, macht aus einem lauten Fehler eine Seite, die still nichts anzeigt.","3uQkN4i5zI41sM0NibptOWBbT-untlVOF5yj_IiRr34",[799,805,811,817,823,829,835,841,847,853,859,866,872,878,884,890,891,897,903,908,914,920,926,932,938,944,949,955,961,967,973,979,985,991,997,1003,1009,1015,1021,1027,1033,1039,1045,1051,1057,1063,1068,1074,1080,1086,1092,1098,1104,1110,1116,1122,1128,1134,1140,1146,1152,1158,1163,1169,1175,1181,1187,1193,1199,1205,1211,1217,1223,1229,1235,1241,1247,1253,1259,1265,1271,1277,1283,1289,1294,1300,1306,1312,1317,1323],{"path":800,"title":801,"description":802,"published":803,"category":755,"image":804,"draft":759},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":806,"title":807,"description":808,"published":809,"category":755,"image":810,"draft":759},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":812,"title":813,"description":814,"published":815,"category":755,"image":816,"draft":759},"\u002Fblog\u002Fviolates-foreign-key-constraint","Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":818,"title":819,"description":820,"published":821,"category":755,"image":822,"draft":759},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":824,"title":825,"description":826,"published":827,"category":755,"image":828,"draft":759},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":830,"title":831,"description":832,"published":833,"category":755,"image":834,"draft":759},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":836,"title":837,"description":838,"published":839,"category":755,"image":840,"draft":759},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":842,"title":843,"description":844,"published":845,"category":755,"image":846,"draft":759},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":848,"title":849,"description":850,"published":851,"category":755,"image":852,"draft":759},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" bei einem neuen Link","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":854,"title":855,"description":856,"published":857,"category":755,"image":858,"draft":759},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":860,"title":861,"description":862,"published":863,"category":864,"image":865,"draft":759},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":867,"title":868,"description":869,"published":870,"category":755,"image":871,"draft":759},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":873,"title":874,"description":875,"published":876,"category":755,"image":877,"draft":759},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":879,"title":880,"description":881,"published":882,"category":755,"image":883,"draft":759},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":885,"title":886,"description":887,"published":888,"category":755,"image":889,"draft":759},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":789,"title":5,"description":758,"published":790,"category":755,"image":777,"draft":759},{"path":892,"title":893,"description":894,"published":895,"category":755,"image":896,"draft":759},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":898,"title":899,"description":900,"published":901,"category":755,"image":902,"draft":759},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":394,"title":904,"description":905,"published":906,"category":755,"image":907,"draft":759},"Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":909,"title":910,"description":911,"published":912,"category":755,"image":913,"draft":759},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":915,"title":916,"description":917,"published":918,"category":755,"image":919,"draft":759},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":921,"title":922,"description":923,"published":924,"category":755,"image":925,"draft":759},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":927,"title":928,"description":929,"published":930,"category":755,"image":931,"draft":759},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":933,"title":934,"description":935,"published":936,"category":755,"image":937,"draft":759},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": die drei Dinge, die es bedeutet","Supabase \"Bucket not found\" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":939,"title":940,"description":941,"published":942,"category":755,"image":943,"draft":759},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":599,"title":945,"description":946,"published":947,"category":755,"image":948,"draft":759},"Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":950,"title":951,"description":952,"published":953,"category":755,"image":954,"draft":759},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":956,"title":957,"description":958,"published":959,"category":755,"image":960,"draft":759},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":962,"title":963,"description":964,"published":965,"category":755,"image":966,"draft":759},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":968,"title":969,"description":970,"published":971,"category":755,"image":972,"draft":759},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":974,"title":975,"description":976,"published":977,"category":755,"image":978,"draft":759},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":980,"title":981,"description":982,"published":983,"category":755,"image":984,"draft":759},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":986,"title":987,"description":988,"published":989,"category":755,"image":990,"draft":759},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":992,"title":993,"description":994,"published":995,"category":755,"image":996,"draft":759},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":998,"title":999,"description":1000,"published":1001,"category":755,"image":1002,"draft":759},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":1004,"title":1005,"description":1006,"published":1007,"category":755,"image":1008,"draft":759},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","API-Schlüssel verstecken: ab in eine Supabase Edge Function","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":1010,"title":1011,"description":1012,"published":1013,"category":755,"image":1014,"draft":759},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":1016,"title":1017,"description":1018,"published":1019,"category":755,"image":1020,"draft":759},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":1022,"title":1023,"description":1024,"published":1025,"category":755,"image":1026,"draft":759},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":1028,"title":1029,"description":1030,"published":1031,"category":755,"image":1032,"draft":759},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":1034,"title":1035,"description":1036,"published":1037,"category":755,"image":1038,"draft":759},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":1040,"title":1041,"description":1042,"published":1043,"category":755,"image":1044,"draft":759},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":1046,"title":1047,"description":1048,"published":1049,"category":864,"image":1050,"draft":759},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":1052,"title":1053,"description":1054,"published":1055,"category":864,"image":1056,"draft":759},"\u002Fblog\u002Fsupabase-backup-github-action","Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":1058,"title":1059,"description":1060,"published":1061,"category":864,"image":1062,"draft":759},"\u002Fblog\u002Fdownload-your-supabase-backup","Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":1064,"title":1065,"description":1066,"published":1061,"category":755,"image":1067,"draft":759},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":1069,"title":1070,"description":1071,"published":1072,"category":755,"image":1073,"draft":759},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":1075,"title":1076,"description":1077,"published":1078,"category":755,"image":1079,"draft":759},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":1081,"title":1082,"description":1083,"published":1084,"category":864,"image":1085,"draft":759},"\u002Fblog\u002Fsupabase-backup-auth-users","Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":1087,"title":1088,"description":1089,"published":1090,"category":755,"image":1091,"draft":759},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":1093,"title":1094,"description":1095,"published":1096,"category":755,"image":1097,"draft":759},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":1099,"title":1100,"description":1101,"published":1102,"category":755,"image":1103,"draft":759},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1105,"title":1106,"description":1107,"published":1108,"category":755,"image":1109,"draft":759},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1111,"title":1112,"description":1113,"published":1114,"category":755,"image":1115,"draft":759},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1117,"title":1118,"description":1119,"published":1120,"category":755,"image":1121,"draft":759},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1123,"title":1124,"description":1125,"published":1126,"category":755,"image":1127,"draft":759},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1129,"title":1130,"description":1131,"published":1132,"category":755,"image":1133,"draft":759},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":1135,"title":1136,"description":1137,"published":1138,"category":864,"image":1139,"draft":759},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1141,"title":1142,"description":1143,"published":1144,"category":864,"image":1145,"draft":759},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1147,"title":1148,"description":1149,"published":1150,"category":864,"image":1151,"draft":759},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1153,"title":1154,"description":1155,"published":1156,"category":755,"image":1157,"draft":759},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":604,"title":1159,"description":1160,"published":1161,"category":755,"image":1162,"draft":759},"Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1164,"title":1165,"description":1166,"published":1167,"category":755,"image":1168,"draft":759},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1170,"title":1171,"description":1172,"published":1173,"category":755,"image":1174,"draft":759},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1176,"title":1177,"description":1178,"published":1179,"category":755,"image":1180,"draft":759},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1182,"title":1183,"description":1184,"published":1185,"category":755,"image":1186,"draft":759},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1188,"title":1189,"description":1190,"published":1191,"category":755,"image":1192,"draft":759},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1194,"title":1195,"description":1196,"published":1197,"category":755,"image":1198,"draft":759},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1200,"title":1201,"description":1202,"published":1203,"category":755,"image":1204,"draft":759},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1206,"title":1207,"description":1208,"published":1209,"category":755,"image":1210,"draft":759},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1212,"title":1213,"description":1214,"published":1215,"category":864,"image":1216,"draft":759},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1218,"title":1219,"description":1220,"published":1221,"category":755,"image":1222,"draft":759},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1224,"title":1225,"description":1226,"published":1227,"category":864,"image":1228,"draft":759},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1230,"title":1231,"description":1232,"published":1233,"category":755,"image":1234,"draft":759},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1236,"title":1237,"description":1238,"published":1239,"category":755,"image":1240,"draft":759},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1242,"title":1243,"description":1244,"published":1245,"category":755,"image":1246,"draft":759},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1248,"title":1249,"description":1250,"published":1251,"category":755,"image":1252,"draft":759},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1254,"title":1255,"description":1256,"published":1257,"category":864,"image":1258,"draft":759},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1260,"title":1261,"description":1262,"published":1263,"category":864,"image":1264,"draft":759},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1266,"title":1267,"description":1268,"published":1269,"category":755,"image":1270,"draft":759},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1272,"title":1273,"description":1274,"published":1275,"category":755,"image":1276,"draft":759},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1278,"title":1279,"description":1280,"published":1281,"category":864,"image":1282,"draft":759},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1284,"title":1285,"description":1286,"published":1287,"category":755,"image":1288,"draft":759},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1290,"title":1291,"description":1292,"published":1287,"category":755,"image":1293,"draft":759},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1295,"title":1296,"description":1297,"published":1298,"category":755,"image":1299,"draft":759},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1301,"title":1302,"description":1303,"published":1304,"category":864,"image":1305,"draft":759},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1307,"title":1308,"description":1309,"published":1310,"category":755,"image":1311,"draft":759},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1313,"title":1314,"description":1315,"published":1310,"category":864,"image":1316,"draft":759},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1318,"title":1319,"description":1320,"published":1321,"category":864,"image":1322,"draft":759},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1324,"title":1325,"description":1326,"published":1321,"category":755,"image":1327,"draft":759},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213638720]