Steven
Steven8 Min. Lesezeit

Das Dashboard rund um ein einziges Wellen-Diagramm neu gestalten

GeekBye v1.8.2 verwandelte das Dashboard von einer Aufnahme-Fernbedienung in eine schreibgeschützte Analytics-Ansicht — eine Statistik-Leiste und ein 7-Tage-Wellen-Diagramm. Beide prägenden Elemente waren zweite Entwürfe, ausgeliefert binnen zwanzig Minuten nach ihren ersten Entwürfen, am selben Nachmittag.

Technik
Design
Dashboard
GeekBye-Releases
Das Dashboard rund um ein einziges Wellen-Diagramm neu gestalten

Manche Releases fügen ein Feature hinzu. GeekBye v1.8.2 entfernte vor allem eines — und die Entfernung ist die Geschichte. An einem einzigen Nachmittag im Februar 2026 verwandelten achtzehn Commits die Dashboard-Startseite von einer Aufnahme-Fernbedienung in eine schreibgeschützte Analytics-Ansicht: vier Statistiken und ein Aktivitätsdiagramm. Unterwegs lieferte sie ein Balkendiagramm, das zweiundzwanzig Minuten lebte, ein Raster aus Statistik-Karten, das zwanzig lebte, und eine selbstgebaute SVG-Welle, die beide ersetzte. Die ganze Suche ist in den Zeitstempeln der Commits konserviert, was die beste Art von Design-Dokumentation ist, die es gibt.

Das Dashboard war keine Fernbedienung mehr

Vor diesem Release war die Dashboard-Startseite ein Bedienfeld. Sie führte mit einer Hero-Karte — ein großes Aufnahme-Widget mit einem LIVE-Badge, Pause-/Fortsetzen-/Stopp-Buttons, Verlaufs-Klecksen und einem useSessionState-Hook, der alles mit dem Recorder verdrahtete. Das Dashboard versuchte, zwei Dinge auf einmal zu sein: der Ort, an dem du deine Meetings ansiehst, und der Ort, an dem du den Recorder steuerst. Zwei Produkte, ein Bildschirm, in stiller Konkurrenz.

v1.8.2 entschied sich. Sie löschte die Hero-Karte und die useSessionState-Verdrahtung — samt eines Effekts, der dich in dem Moment, in dem eine Session endete, automatisch auf die Detailseite eines Meetings navigierte, genau die Art von „hilfreichem" Sprung, der Leute mitten im Fluss überrascht. Den Recorder zu starten und zu verbergen wanderte hinaus auf einen schlichten Navbar-Schalter (ein umgewidmeter Button, der beim Wechsel vom Session-Controller zum Ein/Aus-Schalter rund hundert Zeilen verlor), gestützt auf einen neuen navbar:hide-IPC-Handler. Was übrig blieb, war ein Dashboard, das eine Sache tut: dir zeigen, was du aufgenommen hast. Schreibgeschützt. Ruhig.

In diesem Übergang steckt ein kleiner, sehr menschlicher Bug, den man erwähnen sollte, weil er genau die Sorte ist, die ein Redesign leise einführt und ein gutes Auge in derselben Stunde fängt. Die zwei neuen Seitenleisten-Buttons — Starten und Verbergen — kamen mit demselben generischen Raster-Icon heraus, also waren sie visuell identisch. Zwölf Minuten später gab ein Nachzügler Starten ein Play-Icon, gab Verbergen ein durchgestrichenes Augen-Icon und färbte Verbergen bernsteinfarben, sodass „die App verschwinden lassen" sich als bewusste Handlung liest statt als neutraler Zwilling von „Starten". Icons sind Text. Zwei Buttons, die gleich aussehen, sagen dasselbe, und diese beiden meinten nicht dasselbe.

Das Balkendiagramm, das zweiundzwanzig Minuten lebte

Hier ist der Teil, den ich liebe, und er ist vollständig aus dem Git-Log ablesbar. Um 16:29:34 landete der erste Entwurf des Redesigns: ein 7-Tage-Aktivitätsdiagramm, gezeichnet als Balken — animierte Säulen, eine Mindesthöhe, damit winzige Tage sichtbar blieben, ein 2 Pixel hoher gedämpfter Stummel für Null-Tage. Vernünftig. Konventionell. Die Art Diagramm, zu der man ohne Nachdenken greift.

Um 16:51:21 — zweiundzwanzig Minuten später — wurde es gelöscht. Der Ersatz-Commit sagt genau, was er tat: „replace bar chart with smooth wave area chart for 7-day activity" (das Balkendiagramm durch ein glattes Wellen-Flächendiagramm für die 7-Tage-Aktivität ersetzen). Und um 16:52:21, eine Minute danach, entfernte ein weiterer Commit die abgerundete Karte und den Rahmen um die Welle, „for cleaner look" (für ein sauberes Aussehen).

Warum? Die Commits sagen nur, was sich änderte, das Warum ist also eine Lesart — aber die Form der Daten macht es offensichtlich. Dies ist ein Tool, bei dem ein typischer Nutzer an einem beliebigen Tag null, ein oder zwei Meetings hat. Sieben Balken, die meisten 2 Pixel hoch, sehen aus wie ein fast leerer Parkplatz. Dieselben sieben Zahlen, gezeichnet als durchgehende gefüllte Fläche, sehen aus wie ein Trend — eine sanfte Welle, die dort ansteigt, wo die Woche voll war. Nichts wurde gefälscht; die y-Werte sind identisch. Das Redesign wählte einfach die Kodierung, die spärliche, ehrliche Daten als Form lesbar macht statt als Abwesenheit.

Die Statistiken bekamen dieselbe Behandlung auf derselben Uhr. Der erste Entwurf (16:29) setzte vier Zahlen in ein 2×4-Raster aus Karten. Um 16:49 kollabierte das Raster zu einer einzigen Inline-Statistik-Leiste — eine einzelne umrandete Zeile mit haarfeinen Trennern, kleinerer Schrift, ein Container statt vier. Fünf Kästen auf dem Bildschirm (vier Karten plus eine Diagramm-Karte) wurden zwei (eine Leiste und eine Welle). Der nächste PR fügte einen weiteren ehrlichen Kniff hinzu: aus dem Label „Total Time" wurde „Time in Meetings" (Zeit in Meetings), weil Gesamt-von-was eine berechtigte Frage war, die niemand stellen müssen sollte.

Zwanzig Minuten, vom ersten Entwurf bis zur finalen Fassung, alles innerhalb eines einzigen Pull Requests. Wären die in einen einzigen Commit „redesign dashboard" gequetscht worden, wäre die Suche unsichtbar. Weil sie es nicht wurden, kann man einem Designer beim Konvergieren in Echtzeit zusehen.

Die Welle, mechanisch

Hier gibt es keine Diagramm-Bibliothek. Die Welle ist ein Inline-SVG, in JSX gebaut, und sie ist einen Blick wert, weil sie ein kleines, ehrliches Rezept ist, das du für jedes Sparkline stehlen kannst.

Die Glättung ist der Trick. Für jedes Paar benachbarter Punkte nutzt der Path ein cubic-bezier-Segment, dessen zwei Kontrollpunkte auf der horizontalen Mitte zwischen ihnen sitzen — cpx = (prev.x + curr.x) / 2 — wobei die Kontrollpunkte auf der jeweils eigenen Höhe jedes Endes gehalten werden. Das ist die klassische Flachtangenten-Glättung: die Kurve gleitet durch jeden Datenpunkt, ohne je über den höchsten oder unter den niedrigsten Wert hinauszuschießen, was ein naiver Catmull-Rom-Spline täte. Für ein Diagramm über Meeting-Zahlen ist „nie eine Ausbuchtung zeichnen, die einen Wert impliziert, den es nicht gab" keine Nettigkeit; es ist Korrektheit. Die gefüllte Fläche ist dieselbe Kurve, unten geschlossen und mit einem vertikalen Verlauf bemalt (Cyan, das von 30% zu fast nichts ausblendet), und die Linie zeichnet sich mit einer framer-motion-pathLength-Animation selbst ein, von links nach rechts.

Unter dem SVG liegt die Daten-Verrohrung, und sie ist die stille Heldin. Eine neue Methode getAggregateStats() im Transkript-Repository führt drei Prepared Statements gegen die lokale SQLite-Tabelle transcript_sessions aus: Gesamtsummen über alle Zeit (Anzahl, summierte Dauer, durchschnittliche Dauer), eine rollierende Sieben-Tage-Zählung und ein Bucket pro Tag mit GROUP BY date(created_at). Dann — und das ist das Detail, das das Diagramm robust macht — läuft eine kleine JavaScript-Schleife die letzten sieben Kalendertage ab und füllt jeden Tag, den die Query nicht zurückgab, mit einer Null auf. Das Diagramm bekommt daher garantiert exakt sieben Punkte, immer.

Diese Garantie ist es, die die Randfälle verschwinden lässt, statt über die View verstreute Wächter zu brauchen. Eine leere Woche? Sieben Nullen, und ein Math.max(count, 1) im Nenner hält die Linie unten flach, statt durch null zu teilen. Ein einzelner Datenpunkt, der die x-Abstands-Formel i / (n − 1) NaN produzieren ließe? Kann nicht passieren — das Repository liefert nie weniger als sieben. Die Wochentags-Labels parsen jeden Bucket sogar bei T12:00:00 statt bei blanker Mitternacht, damit ein YYYY-MM-DD-String in einer Zeitzone mit negativem UTC nicht auf den Vortag rutscht. Korrigiere die Form der Daten an der Quelle, und der Rendering-Code darf mit Absicht naiv sein.

Alles bleibt auf der Maschine. Die Statistik-Query liest die lokale Datenbank, kehrt über einen typisierten transcript:get-stats-IPC-Kanal zurück und animiert beim Mounten zu vier hochzählenden Zahlen. Nichts von deiner Meeting-Historie verlässt das Laptop, um dieses Diagramm zu zeichnen — was für ein Tool, das deine Gespräche aufnimmt, die einzig akzeptable Art ist, eine Analytics-Ansicht zu bauen.

Noch ein Bug, weil Redesigns sie ans Licht zerren

Im selben Release mitgebündelt war ein Fix, der nichts mit dem Dashboard zu tun hatte und alles mit der Sorte Schuld, über die ein Redesign stolpert. Das Styling der dunklen Scrollbar der App war in zwei konkurrierende CSS-Definitionen derselben Klasse abgedriftet — eine ältere, lila, und eine neuere, weiß auf dunkel — und welche gewann, hing von der Kaskadenreihenfolge ab. Schlimmer noch, nur Elemente, die daran dachten, die Klasse hinzuzufügen, wurden überhaupt gestylt; alles andere fiel auf die helle Standard-Scrollbar zurück, und horizontale Scrollbars wurden nie gestylt, weil die alten Regeln nur eine Breite setzten, nie eine Höhe. Der Fix löschte beide Definitionen, stylte die Scrollbar global auf jedem Element und entfernte die nun tote Klasse aus den zehn Komponenten, die sie mitgeschleppt hatten. Es ist ein Zwei-Zeilen-Diff, zehnmal wiederholt — die glanzlose Steuer dafür, dasselbe zweimal gestylt und beide überleben gelassen zu haben.

Drei Dinge, die uns dieses Release lehrte

  1. Subtrahiere, um zu fokussieren. Das Dashboard wurde besser, indem es weniger tat — es verlor die Aufnahmesteuerung, die es nie brauchte, und wurde eine klare Sache. Ein Bildschirm, der zugleich Betrachter und Fernbedienung ist, sind zwei halbe Produkte; wähle eines und verschiebe das andere dorthin, wo es hingehört.
  2. Wähle die Kodierung, die deine Daten verdienen. Spärliche Zählungen lesen sich als Balken wie Abwesenheit und in einem Flächendiagramm wie ein Trend, aus identischen Zahlen. Das ist keine Schönfärberei — es ist die Wahl der ehrlichen Form, die echte, dünne Daten kommunizieren lässt.
  3. Garantiere die Form der Daten stromaufwärts. Die Auffüllen-auf-sieben-Schleife ist der Grund, warum der Diagramm-Code keine verstreuten Null-Checks hat: Division durch null, Einzelpunkt-NaN und fehlende Tage verschwinden alle, weil die Query exakt sieben Buckets verspricht. Robustes Rendering beginnt eine Schicht tiefer.

Für das vorige Kapitel der v1-Geschichte, vier Releases in sechsundzwanzig Stunden (v1.7.6–v1.8.1); und für den ganzen Bogen, die Anatomie, Software bis zur Perfektion auszuliefern.