Ich habe heute eine App gebaut. Von null auf (fast) fertig, in einer einzigen Session. Eine Electron-App mit 3D-Wissensgraph, KI-Integration über drei Provider, einem globalen Quick-Capture-Hotkey und einer SQLite-Datenbank, die ohne eine einzige native Compilation auskommt. Sie heißt Codex, und sie löst ein Problem, das ich seit Jahren mit mir herumtrage.
Das klingt nach mehr, als es ist. Oder nach weniger. Je nachdem, was du von einer App erwartest.
Die Idee: Leonardo und das zweite Gehirn
Wenn du wissen willst, woher der Name kommt: Leonardo da Vinci hat zwischen 1478 und 1519 rund 1.119 Seiten mit Zeichnungen, Notizen, Erfindungen und Beobachtungen hinterlassen. Der Codex Atlanticus ist das größte Einzelwerk davon. Kein Ordnungssystem, keine Kategorien, keine App. Nur ein Mensch, der alles, was ihn interessiert, an einem Ort sammelt und verbindet. Und dieser Leonardo war immer schon eines meiner Vorbilder.
Ich mache das auch. Nur moderner und mit mehr Bugs.
Was mich an klassischen Second-Brain-Tools wie Obsidian nervt: sie sind für Markdown-Puristen gebaut. Ich will keine Vault voller .md-Dateien. Obsidian ist optimal für mein VINCI-Projekt, aber nicht für diese Idee. Ich will eine App, die mir zeigt, wie meine Gedanken zusammenhängen. Visuell. In drei Dimensionen. Und ich will, dass ein KI-Assistent mir dabei hilft, neue Einträge zu strukturieren, zu taggen und zu verbessern, ohne dass meine Daten auf irgendeinem amerikanischen Server landen. Codex verwendet zwar KI, aber es werden keine Persönlichkeitsdaten übermittelt.
Codex ist diese App.
Der Stack: Entscheidungen, die ich am Ende nicht bereut habe
Bevor irgendeine Zeile Code geschrieben war, war eine Entscheidung bereits getroffen: Lokal-first. Keine Cloud, kein Account, keine Telemetrie. Die Datenbank liegt in einem Ordner, den der User selbst festlegt. Die Datei kann jederzeit kopiert, gesichert oder auf einen anderen Rechner verschoben werden. Das ist kein Feature. Das ist die Grundlage.
Der Rest des Stacks folgt daraus:
- Electron 31 für das native Desktop-Erlebnis auf Windows und macOS
- Vite + electron-vite für einen Build-Prozess, der sich nicht anfühlt, als würde man 2016 entwickeln
- React 18 + Zustand für den Frontend-State. Kein TypeScript, bewusst. Wer sagt, dass JS nicht ausreicht, hat schlicht nie mit einem klaren Komponentenmodell gearbeitet
- sql.js für SQLite. Dazu gleich mehr, das ist die interessanteste Entscheidung des Tages
- Three.js + react-force-graph-3d für den 3D-Wissensgraph
- Claude, OpenAI und Gemini als KI-Provider, frei wählbar in den Settings
Der Tech-Stack klingt nach viel. War aber weniger die Herausforderung als die Dinge, die auf dem Papier einfach aussahen.
Das sqlite-Desaster: Warum ich better-sqlite3 aus dem Projekt geworfen habe
Ich werde direkt sein. Der erste Ansatz war better-sqlite3. Es ist schnell, es ist weit verbreitet, und es hat mir fünfzehn Minuten gekostet, bis ich verstanden habe, dass ich damit auf Windows ohne eine vollständige Python-Toolchain nicht weiterkomme. Native Node-Module werden beim npm install kompiliert. Ohne Python, Visual Studio Build Tools und die richtige Node-ABI-Version läuft da nichts.
Das ist 2026 kein akzeptables Setup für eine App, die ich an Kunden weitergeben will.
Die Lösung: sql.js. Pure JavaScript. WebAssembly. Keine native Compilation. Das Modul läuft im Electron Main Process, die Datenbank wird im Speicher gehalten und per setInterval alle 30 Sekunden auf Disk geschrieben. Nach jedem Write-Vorgang sofort. Das ist kein Kompromiss in der Performance, solange die Datenbank unter einer bestimmten Größe bleibt, und für ein persönliches Second Brain ist das kein Problem.
Zitierfähige These für den Kontext: Wer eine Electron-App für End-User baut, sollte native Node-Module als Default-Ansatz überdenken. Die Zahl der Dinge, die dabei schiefgehen können, ist höher als die Zahl der Dinge, die better-sqlite3 einem bringt.
Der Graph: Von 2D-Karikatur zu echter 3D-Force-Simulation
Das war der Teil, den ich am meisten unterschätzt habe.
Erster Ansatz: ein 2D-Canvas, auf dem ich Knoten mit simulierter Rotation gezeichnet habe. Es sah aus wie eine Weltkarte aus dem 16. Jahrhundert, aber in schlecht. Der Effekt war da, aber die Substanz fehlte.
Die Migration auf react-force-graph-3d war dann eine Entscheidung, die ich keine Stunde bereut habe. Die Library bringt eine echte Force-Simulation im dreidimensionalen Raum mit. Knoten verteilen sich nach Verbindungsgewicht, Cluster bilden sich natürlich, und man kann die Camera um das Netz herum bewegen.
Aber: die Library nutzt per Default TrackballControls. Kein autoRotate. Ich wollte, dass der Graph sich dreht, wenn niemand damit interagiert, und nach 6 Sekunden Idle wieder startet. Das geht nur mit controlType="orbit" und manuell gesetztem autoRotateSpeed. Ein Parameter in einer Prop. Eine Stunde Debugging.
Drei Verbindungsebenen sind im Graph aktiv: Tag-Verbindungen (alle Einträge mit demselben Tag über einen Tag-Hub verbunden), Auto-Erwähnungen (wenn der Name eines Eintrags im Text eines anderen vorkommt, entsteht eine direkte Kante) und manuelle Links (der User setzt sie selbst über ein Suchfeld im Drawer). Die Liniendicke und Farbe jedes Typs ist einzeln konfigurierbar.
Das andere, das mich aufgehalten hat: Bloom-Effekte auf Text. Der Bloom-Pass von Three.js ist unspezifisch. Er leuchtet alles an, was hell genug ist, also auch die Label-Texte. Das sieht aus wie eine Szene aus einem 90er-Sci-Fi-Film, bei der das Budget für das Compositing nicht gereicht hat. Lösung: Bloom-Threshold auf 0.92, und nur emissive Materialien auf den Knoten selbst bekommen das Glow. Text bleibt scharf.
Ich beobachte das seit einiger Zeit – auch in meiner Funktion als Vibe Coder und KI-Berater: die meisten technischen Probleme beim Vibe Coding entstehen nicht am Konzept, sondern an der Interaktion zwischen zwei Systemen, die sich gegenseitig nicht kennen. three.js und react-force-graph-3d sind zwei solcher Systeme.
Quick Capture: URL-Catcher, Charset-Hölle und KI-Extraktion
Der Quick Capture ist das Feature, das ich am meisten benutzen werde. Globaler Hotkey, Ctrl+Shift+Alt+C als Default, frei konfigurierbar. Ein kleines, rahmenloses Fenster erscheint. URL einfügen, Button klicken, Titel und Inhalt der Seite werden geholt.
Klingt einfach. War es nicht.
Problem 1: Das Fenster verschwand, wenn ich in den Browser wechselte, um die URL zu kopieren. Der blur-Event-Handler hat das Fenster bei Fokus-Verlust geschlossen. Fix: Handler raus, Fenster bleibt offen bis es der User schließt.
Problem 2: Umlaute. Seiten, die Latin-1 oder Windows-1252 ausliefern, wurden mit erzwungenem UTF-8 zu unlesbarem Zeichensalat. Die Lösung ist ein buffer-basiertes Fetch: den Charset aus dem HTTP-Header oder dem <meta charset>-Tag lesen, mit TextDecoder und dem richtigen Charset dekodieren, Named Entities wie Ä, ü und ß als Nachbearbeitungsschritt auflösen.
Problem 3: Der falsche Inhalt. Heuristische Selektor-Auswahl, die den „größten Textblock“ einer Seite findet, scheitert an FAQ-Seiten. Die FAQ ist oft größer als der eigentliche Artikel. Der Fix ist pragmatisch und funktioniert zuverlässig: wenn ein KI-Provider konfiguriert ist, bekommt die KI die komplette Seite und extrahiert semantisch den Hauptartikel. Das ist langsamer, aber korrekt.
Acht Module, ein Datenmodell
Codex hat im Moment acht Module: Wissen, KI-Tools, Projekte, Aufgaben, Notizen, Workflows, Custom und den Graph. Die ersten sechs sind in eigenen Tabellen gespeichert. Custom-Module landen alle in der entries-Tabelle mit einer module_id als Discriminator. Man kann beliebig viele zusätzliche Module anlegen, ihnen einen Namen und ein Icon geben, und sie erscheinen sofort in der Navigation und im Quick Capture.
Das ist das Muster, das ich für die Erweiterbarkeit brauche: kein starres Schema, kein Code-Änderung für ein neues Modul.
Der KI-Button ist in jedem Modul-Drawer kontextsensitiv. Verfügbare Aktionen: Tags vorschlagen, Zusammenfassen, Verbessern, Strukturieren, Übersetzen. Vor dem Übernehmen öffnet sich ein Preview-Dialog. Keine stillen Überschreibungen.
Customer-ready von Anfang an
Das ist die Entscheidung, die Codex von einem persönlichen Tool zu etwas macht, das ich auch an Kunden weitergeben kann: das gesamte Branding ist in den Settings überschreibbar. Akzentfarbe, Hintergrundfarbe, Schriftart, App-Name in der Sidebar. Fünf vordefinierte Schemata (Gold, Ocean Blue, Forest Green, Rose, Violet) als Ausgangspunkt.
Mein eigenes Setup: Renaissance Gold (#D4AF37) auf Obsidian Noir (#0f1011). Wer das anders haben will, braucht keine zwei Minuten in den Settings.
Modul-Namen sind ebenfalls überschreibbar. Ein Kunde, der statt „Wissen“ lieber „Wissensdatenbank“ lesen will, kann das einstellen. Module lassen sich ausblenden, wenn man sie nicht braucht.
Das ist kein Luxus. Das ist die Grundvoraussetzung für eine App, die nicht nur für mich funktioniert.
Was heute noch nicht fertig ist
Ich schreibe das als Dev-Log, also gehört Ehrlichkeit dazu.
Der App-Build fehlt noch. electron-builder ist konfiguriert, das NSIS-Installer-Setup für Windows ist vorbereitet. Den tatsächlichen Build habe ich heute nicht mehr durchgezogen. Das ist der erste Schritt nach dieser Session.
Der Onboarding-Wizard fehlt. Wer die App zum ersten Mal öffnet, sieht eine leere Oberfläche. Das ist für mich in Ordnung, weil ich weiß, was ich einstellen muss. Für einen Kunden ist das keine akzeptable First Experience.
Der Mac-Build ist ungetestet. electron-builder sollte das in Theorie unterstützen, aber ich habe auf Windows entwickelt. Das werden wir sehen.
Das Code-Signing für Windows (Azure Trusted Signing) und macOS (Apple Developer ID) ist noch nicht eingerichtet. Ohne das wird SmartScreen auf Windows und Gatekeeper auf macOS beide blockieren. Das ist für meine eigene Nutzung kein Problem, für die Weitergabe schon.
Was noch kommt
Der Summer-Launch auf GitHub ist geplant. Bis dahin kommen noch ein paar Dinge, die mir wichtig sind: Obsidian-Import (bestehende Vaults sollen eingelesen werden, Wikilinks werden in Codex-Verlinkungen umgewandelt), Datei-Anhänge per Drag & Drop (Bilder und PDFs in Einträge ziehen), und irgendwann ein MCP-Server-Interface, damit Codex als Tool-Server für andere KI-Workflows nutzbar wird.
Die Idee, die mich am meisten reizt: ein AI-Agent-Modus, bei dem Codex selbständig Querverbindungen zwischen Einträgen herstellt und Verknüpfungsvorschläge macht. Nicht als Pflichtfunktion, die sich aufdrängt, sondern als Hintergrundprozess mit Bestätigungsdialog.
Das Repo ist noch private. Im Sommer geht es auf GitHub public: Bis dahin läuft Codex bei mir lokal, täglich. Und wird weiterentwickelt.
Fragen zu Codex?
Warum Electron und nicht eine Web-App?
Weil ein globaler Hotkey, der auch dann funktioniert wenn die App minimiert ist, im Browser nicht möglich ist. Quick Capture ist das zentrale Feature, und das braucht nativen System-Zugriff.
Ist sql.js wirklich eine Alternative zu better-sqlite3?
Für personal-scale Apps: ja. Der Performance-Unterschied wird erst bei sehr großen Datenmengen spürbar. Der Vorteil, keine native Compilation zu brauchen, überwiegt für mein Anwendungsfall deutlich.
Wann geht Codex auf GitHub public?
Sommer 2026. Ich will vorher noch den App-Build, den Onboarding-Wizard und mindestens einen Mac-Build-Test abgeschlossen haben. Und ich hab noch „Feature“ Ideen.