
Dashboard को एक ही wave chart के इर्द-गिर्द फिर से design करना
GeekBye v1.8.2 ने dashboard को recording के रिमोट कंट्रोल से बदलकर एक read-only analytics view बना दिया — एक stats strip और एक 7-दिन का wave chart। ये दोनों signature तत्व दूसरे draft थे, अपने पहले draft के 20 मिनट के भीतर, उसी दोपहर में ship हुए।
कुछ रिलीज़ एक feature जोड़ती हैं। GeekBye v1.8.2 ने ज़्यादातर एक को हटाया — और वह हटाना ही कहानी है। February 2026 की एक दोपहर में, 18 commits ने dashboard home को recording के रिमोट कंट्रोल से बदलकर एक read-only analytics view बना दिया: चार stats और एक activity chart। रास्ते में इसने एक ऐसा bar chart ship किया जो 22 मिनट जिया, stat cards का एक grid जो 20 मिनट जिया, और एक हाथ से बुनी SVG wave जिसने दोनों की जगह ले ली। पूरी खोज commit के timestamps में सहेजी हुई है, और यह इस दुनिया की सबसे बढ़िया किस्म की design documentation है।
dashboard का रिमोट होना बंद हो गया
इस रिलीज़ से पहले dashboard home एक control panel था। इसके सिरे पर एक hero card था — एक बड़ा recording widget जिसमें LIVE badge, Pause/Resume/Stop बटन, gradient के धब्बे, और इन सबको recorder से जोड़ता एक useSessionState hook था। dashboard एक साथ दो चीज़ें बनना चाह रहा था: वह जगह जहाँ आप अपनी meetings देखते हैं, और वह जगह जहाँ आप recorder को चलाते हैं। दो products, एक स्क्रीन, चुपचाप आपस में होड़ करते।
v1.8.2 ने एक को चुना। इसने hero card और useSessionState की सारी wiring हटा दी — उस effect समेत जो session ख़त्म होते ही आपको किसी meeting के detail page पर अपने-आप ले जाता था, और यह ठीक वही "मददगार" छलाँग है जो लोगों को बीच काम में चौंका देती है। recorder को शुरू और छिपाने का काम एक सादे navbar toggle पर खिसका दिया गया (एक ऐसा बटन जिसका इस्तेमाल बदला गया, जो session controller से on/off switch बनते हुए लगभग सौ lines खो बैठा), और इसके पीछे एक नया navbar:hide IPC handler है। जो बचा वह एक ऐसा dashboard है जो एक ही काम करता है: आपको दिखाता है कि आपने क्या record किया। read-only। शांत।
इस बदलाव में एक छोटा, इंसानी bug है जिसका ज़िक्र करना बनता है, क्योंकि यह ठीक उस तरह की चीज़ है जो कोई redesign चुपके से ले आती है और अच्छी नज़र उसी घंटे पकड़ लेती है। sidebar के दो नए बटन — Start और Hide — एक ही आम grid icon के साथ ship हुए, इसलिए देखने में बिल्कुल एक जैसे थे। 12 मिनट बाद एक follow-up ने Start को play icon दिया, Hide को आँख-पर-कटी-लकीर वाला icon दिया, और Hide को अंबर रंग में रंग दिया, ताकि "app को ग़ायब कर दो" एक सोचा-समझा action लगे, न कि "शुरू करो" का कोई तटस्थ जुड़वाँ। icons भी copy (शब्द) हैं। एक जैसे दिखने वाले दो बटन एक ही बात कहते हैं, और इन दोनों का मतलब एक नहीं था।
वह bar chart जो 22 मिनट जिया
यह वाला हिस्सा मुझे बहुत पसंद है, और यह पूरा का पूरा git log से पढ़ा जा सकता है। 16:29:34 पर redesign का पहला draft उतरा: bars से खिंची एक 7-दिन की activity chart — animated columns, एक न्यूनतम ऊँचाई ताकि नन्हे दिन भी दिखें, और शून्य वाले दिनों के लिए 2-pixel का धुँधला ठूँठ। वाजिब। रवायती। ऐसी chart जिसकी तरफ़ आप बिना सोचे हाथ बढ़ा देते हैं।
16:51:21 पर — 22 मिनट बाद — इसे मिटा दिया गया। बदलने वाला commit ठीक-ठीक बताता है कि उसने क्या किया: "replace bar chart with smooth wave area chart for 7-day activity"। और 16:52:21 पर, उसके एक मिनट बाद, एक और commit ने wave के इर्द-गिर्द से गोल कोनों वाला card और border उतार दिया, "for cleaner look"।
क्यों? commits सिर्फ़ यह बताते हैं कि क्या बदला, तो क्यों एक पढ़ाई है — पर data का आकार इसे साफ़ कर देता है। यह ऐसा tool है जहाँ एक आम user के किसी भी दिन शून्य, एक, या दो meetings होती हैं। सात bars, जिनमें ज़्यादातर बस 2 pixel ऊँची हों, एक क़रीब-क़रीब ख़ाली पार्किंग जैसी दिखती हैं। वही सात आँकड़े एक लगातार भरे हुए area की तरह खींचे जाएँ तो एक trend जैसे दिखते हैं — एक हल्की wave जो वहाँ उठती है जहाँ हफ़्ता व्यस्त था। कुछ भी नक़ली नहीं है; y-मान बिल्कुल वही हैं। redesign ने बस वह encoding चुनी जो sparse, ईमानदार data को अनुपस्थिति की बजाय एक आकार की तरह पढ़ने देती है।
stats को उसी घड़ी पर वैसा ही इलाज मिला। पहले draft (16:29) ने चार आँकड़े एक 2×4 card grid में रखे। 16:49 पर grid सिमटकर एक inline stats strip बन गया — एक border वाली पंक्ति जिसमें बाल जैसी बारीक विभाजक रेखाएँ, छोटा type, और चार की बजाय एक container। स्क्रीन पर पाँच डिब्बे (चार cards और एक chart card) दो बन गए (एक strip और एक wave)। अगले PR ने एक और ईमानदार छुअन जोड़ी: "Total Time" label बदलकर "Time in Meetings" हो गया, क्योंकि "किस_चीज़_ का कुल" एक जायज़ सवाल था जो किसी को पूछना ही न पड़े।
20 मिनट, पहले draft से आख़िरी तक, सब कुछ एक ही pull request के भीतर। अगर ये एक अकेले "redesign dashboard" commit में squash हो जाते, तो खोज अदृश्य हो जाती। चूँकि ऐसा नहीं हुआ, आप एक designer को real time में एक नतीजे पर पहुँचते देख सकते हैं।
wave, यंत्र-रचना के लिहाज़ से
यहाँ कोई chart library नहीं है। wave JSX में बनी एक inline SVG है, और यह एक नज़र देखने लायक़ है क्योंकि यह एक छोटी, ईमानदार recipe है जिसे आप किसी भी sparkline के लिए चुरा सकते हैं।
असली दाँव smoothing है। हर दो पड़ोसी बिंदुओं की जोड़ी के लिए path एक cubic-bezier segment इस्तेमाल करता है जिसके दोनों control points उनके बीच के क्षैतिज midpoint पर बैठते हैं — cpx = (prev.x + curr.x) / 2 — और control points हर छोर की अपनी-अपनी ऊँचाई पर टिके रहते हैं। यही classic flat-tangent smoothing है: curve हर data बिंदु से होकर बहती है, बिना कभी सबसे ऊँचे मान से ऊपर या सबसे नीचे मान से नीचे निकले — जो एक भोली Catmull-Rom spline कर बैठती। meeting-गिनती की एक chart के लिए, "ऐसा कोई उभार कभी न खींचो जो एक न-हुए मान का इशारा दे" कोई सजावट नहीं है; यही शुद्धता है। भरा हुआ area वही curve है जो नीचे की तरफ़ बंद कर दी गई और एक खड़े gradient (cyan, 30% से घटकर लगभग शून्य तक) से रँगी गई, और रेखा ख़ुद को framer-motion के pathLength animation से, बाएँ से दाएँ, खींचती चली जाती है।
SVG के नीचे data की plumbing है, और यही चुपचाप वाला नायक है। transcript repository पर एक नई getAggregateStats() method local SQLite transcript_sessions table पर तीन prepared statements चलाती है: हर-समय के कुल (गिनती, कुल अवधि, औसत अवधि), एक rolling सात-दिन की गिनती, और प्रति-दिन एक GROUP BY date(created_at) bucket। फिर — और यही वह ब्योरा है जो chart को मज़बूत बनाता है — एक छोटी JavaScript loop पिछले सात calendar दिनों पर चलती है और हर उस दिन को back-fill कर देती है जो query ने नहीं लौटाया, एक शून्य ठेलकर। इसलिए chart के हमेशा ठीक सात बिंदु होने की गारंटी है।
यही गारंटी है जो edge cases को view में जगह-जगह guards बिखेरने की बजाय ग़ायब कर देती है। ख़ाली हफ़्ता? सात शून्य, और भाजक पर एक Math.max(count, 1) जो रेखा को शून्य से भाग देने की बजाय सबसे नीचे सपाट रखता है। एक अकेला data बिंदु जो i / (n − 1) वाले x-spacing सूत्र से NaN निकलवा दे? हो ही नहीं सकता — repository कभी सात से कम नहीं निकालता। weekday labels तक हर bucket को नंगी आधी रात की बजाय T12:00:00 पर parse करते हैं, ताकि कोई YYYY-MM-DD string ऋणात्मक-UTC timezone में पिछले दिन पर न खिसक जाए। data का आकार स्रोत पर ठीक कर दो, और rendering code जान-बूझकर भोला बना रह सकता है।
यह सब machine पर ही रहता है। stats query local database पढ़ती है, एक typed transcript:get-stats IPC channel से लौटती है, और mount पर चार count-up आँकड़ों में animate होती है। इस chart को खींचने के लिए आपकी meeting history का कुछ भी laptop से बाहर नहीं जाता — और आपकी बातचीत record करने वाले tool के लिए, analytics view बनाने का यही एकमात्र स्वीकार्य तरीक़ा है।
एक और bug, क्योंकि redesigns उन्हें रौशनी में घसीट लाती हैं
उसी रिलीज़ के साथ बँधा हुआ एक fix था जिसका dashboard से कोई लेना-देना नहीं था, पर उस किस्म के क़र्ज़ से पूरा नाता था जिससे कोई redesign टकराती है। app की dark scrollbar styling एक ही class की दो आपस में लड़ती CSS definitions में बँट चुकी थी — एक पुरानी बैंगनी और एक नई सफ़ेद-पर-काला — और कौन जीतेगा यह cascade order पर निर्भर था। और बुरा यह कि सिर्फ़ वही elements style होते थे जो वह class जोड़ना याद रखते; बाक़ी सब default हल्की scrollbar पर लौट जाते, और horizontal scrollbars कभी style ही नहीं हुईं क्योंकि पुराने rules ने सिर्फ़ width सेट की थी, height कभी नहीं। fix ने दोनों definitions मिटा दीं, scrollbar को हर element पर globally style किया, और उन दस components से अब-मर चुकी वह class हटा दी जो उसे ढो रहे थे। यह दस बार दोहराया गया एक दो-line का diff है — एक ही चीज़ को दो बार style करने और दोनों को ज़िंदा रहने देने का वह बेरौनक़ कर।
इस रिलीज़ ने हमें तीन बातें सिखाईं
- focus के लिए घटाओ। dashboard कम करके बेहतर हुआ — वे recording controls गँवाकर जिनकी उसे कभी ज़रूरत ही नहीं थी, और एक साफ़ चीज़ बनकर। जो स्क्रीन viewer भी हो और रिमोट भी, वह दो अधूरे products हैं; एक चुनो और दूसरे को वहाँ खिसकाओ जहाँ वह जँचता है।
- वह encoding चुनो जिसका तुम्हारा data हक़दार है। वही आँकड़े, sparse counts bars में अनुपस्थिति की तरह पढ़े जाते हैं और area chart में एक trend की तरह। यह घुमाव-फिराव नहीं है — यह वह ईमानदार आकार चुनना है जो असली, पतले data को बोलने देता है।
- data का आकार ऊपर, स्रोत पर ही तय कर दो। सात तक back-fill करने वाली loop ही वह वजह है कि chart code में जगह-जगह null checks बिखरे नहीं हैं: divide-by-zero, single-point NaN, और missing days सब ग़ायब हो जाते हैं क्योंकि query ठीक सात buckets का वादा करती है। मज़बूत rendering एक परत नीचे से शुरू होती है।
v1 कहानी के पिछले अध्याय के लिए देखें 26 घंटों में चार रिलीज़ (v1.7.6–v1.8.1); और पूरे चाप के लिए, सॉफ़्टवेयर को परिपूर्णता तक पहुँचाकर भेजने की शारीर-रचना।