@@ -169,181 +169,187 @@ function getSourceDisplayName(source: string): string {
169169
170170// Real-time platform leaderboard component (two boxes: Top Models, Top CLI)
171171function PlatformLeaderboard ( { isDark } : { isDark : boolean } ) {
172+ // Skip query if Convex isn't ready (prevents crash on initialization)
172173 const platformStats = useQuery ( api . analytics . publicPlatformStats ) ;
173174
174175 // No spinner - Convex is real-time, data appears when ready
175- // Show the container with "No data yet" if empty
176+ // Show the container with "No data yet" if empty or query not ready
176177 const topModels = platformStats ?. topModels ?? [ ] ;
177178 const topSources = platformStats ?. topSources ?? [ ] ;
178179
180+ // Don't render anything until query is ready (prevents hydration issues)
181+ if ( platformStats === undefined ) {
182+ return null ;
183+ }
184+
179185 return (
180- < div
181- className = { `mt-10 rounded-lg border p-5 ${
182- isDark
183- ? "border-zinc-800 bg-[#161616]"
184- : "border-[#e6e4e1] bg-[#f5f3f0]"
186+ < div
187+ className = { `mt-10 rounded-lg border p-5 ${
188+ isDark
189+ ? "border-zinc-800 bg-[#161616]"
190+ : "border-[#e6e4e1] bg-[#f5f3f0]"
191+ } `}
192+ >
193+ < h3
194+ className = { `text-sm font-medium mb-5 flex items-center gap-2 ${
195+ isDark ? "text-zinc-300" : "text-[#1a1a1a]"
185196 } `}
186197 >
187- < h3
188- className = { `text-sm font-medium mb-5 flex items-center gap-2 ${
189- isDark ? "text-zinc-300" : "text-[#1a1a1a]"
190- } `}
198+ < Zap
199+ className = { `h-4 w-4 ${ isDark ? "text-zinc-500" : "text-[#8b7355]" } ` }
200+ />
201+ Platform Stats
202+ < span
203+ className = { `ml-auto text-[10px] font-normal ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
191204 >
192- < Zap
193- className = { `h-4 w-4 ${ isDark ? "text-zinc-500" : "text-[#8b7355]" } ` }
194- />
195- Platform Stats
196- < span
197- className = { `ml-auto text-[10px] font-normal ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
198- >
199- real-time
200- </ span >
201- </ h3 >
205+ real-time
206+ </ span >
207+ </ h3 >
202208
203- < div className = "grid grid-cols-1 md:grid-cols-2 gap-5" >
204- { /* Top Models */ }
205- < div
206- className = { `rounded-md border p-4 ${
207- isDark
208- ? "border-zinc-800 bg-[#0E0E0E]"
209- : "border-[#e6e4e1] bg-[#faf8f5]"
210- } `}
211- >
212- < div className = "flex items-center justify-between mb-3" >
213- < div className = "flex items-center gap-1.5" >
214- < Trophy
215- className = { `h-3 w-3 ${ isDark ? "text-amber-500" : "text-amber-600" } ` }
216- />
217- < p
218- className = { `text-[10px] uppercase tracking-wider ${
219- isDark ? "text-zinc-600" : "text-[#8b7355]"
220- } `}
221- >
222- Top Models
223- </ p >
224- </ div >
225- < span
209+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-5" >
210+ { /* Top Models */ }
211+ < div
212+ className = { `rounded-md border p-4 ${
213+ isDark
214+ ? "border-zinc-800 bg-[#0E0E0E]"
215+ : "border-[#e6e4e1] bg-[#faf8f5]"
216+ } `}
217+ >
218+ < div className = "flex items-center justify-between mb-3" >
219+ < div className = "flex items-center gap-1.5" >
220+ < Trophy
221+ className = { `h-3 w-3 ${ isDark ? "text-amber-500" : "text-amber-600" } ` }
222+ />
223+ < p
226224 className = { `text-[10px] uppercase tracking-wider ${
227225 isDark ? "text-zinc-600" : "text-[#8b7355]"
228226 } `}
229227 >
230- tokens
231- </ span >
228+ Top Models
229+ </ p >
232230 </ div >
233- < div className = "space-y-1.5" >
234- { topModels . length === 0 ? (
235- < p
236- className = { `text-xs ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
231+ < span
232+ className = { `text-[10px] uppercase tracking-wider ${
233+ isDark ? "text-zinc-600" : "text-[#8b7355]"
234+ } `}
235+ >
236+ tokens
237+ </ span >
238+ </ div >
239+ < div className = "space-y-1.5" >
240+ { topModels . length === 0 ? (
241+ < p
242+ className = { `text-xs ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
243+ >
244+ No data yet
245+ </ p >
246+ ) : (
247+ topModels . map ( ( item , index ) => (
248+ < div
249+ key = { item . model }
250+ className = "flex items-center justify-between"
237251 >
238- No data yet
239- </ p >
240- ) : (
241- topModels . map ( ( item , index ) => (
242- < div
243- key = { item . model }
244- className = "flex items-center justify-between"
252+ < span
253+ className = { `text-xs truncate max-w-[140px] ${
254+ isDark ? "text-zinc-400" : "text-[#6b6b6b]"
255+ } `}
245256 >
246257 < span
247- className = { `text-xs truncate max-w-[140px] ${
248- isDark ? "text-zinc-400" : "text-[#6b6b6b]"
258+ className = { `mr-1.5 ${
259+ index === 0
260+ ? isDark
261+ ? "text-amber-500"
262+ : "text-amber-600"
263+ : isDark
264+ ? "text-zinc-600"
265+ : "text-[#8b7355]"
249266 } `}
250267 >
251- < span
252- className = { `mr-1.5 ${
253- index === 0
254- ? isDark
255- ? "text-amber-500"
256- : "text-amber-600"
257- : isDark
258- ? "text-zinc-600"
259- : "text-[#8b7355]"
260- } `}
261- >
262- { index + 1 } .
263- </ span >
264- { item . model }
268+ { index + 1 } .
265269 </ span >
266- < span
267- className = { `text-[10px] tabular-nums ${
268- isDark ? "text-zinc-500" : "text-[#8b7355]"
269- } `}
270- >
271- { formatNumber ( item . totalTokens ) }
272- </ span >
273- </ div >
274- ) )
275- ) }
276- </ div >
270+ { item . model }
271+ </ span >
272+ < span
273+ className = { `text-[10px] tabular-nums ${
274+ isDark ? "text-zinc-500" : "text-[#8b7355]"
275+ } `}
276+ >
277+ { formatNumber ( item . totalTokens ) }
278+ </ span >
279+ </ div >
280+ ) )
281+ ) }
277282 </ div >
283+ </ div >
278284
279- { /* Top CLI (sources: opencode, claude-code, cursor, droid, codex, amp, etc.) */ }
280- < div
281- className = { `rounded-md border p-4 ${
282- isDark
283- ? "border-zinc-800 bg-[#0E0E0E]"
284- : "border-[#e6e4e1] bg-[#faf8f5]"
285- } `}
286- >
287- < div className = "flex items-center gap-1.5 mb-3" >
288- < Zap
289- className = { `h-3 w-3 ${ isDark ? "text-blue-400" : "text-[#EB5601]" } ` }
290- />
285+ { /* Top CLI (sources: opencode, claude-code, cursor, droid, codex, amp, etc.) */ }
286+ < div
287+ className = { `rounded-md border p-4 ${
288+ isDark
289+ ? "border-zinc-800 bg-[#0E0E0E]"
290+ : "border-[#e6e4e1] bg-[#faf8f5]"
291+ } `}
292+ >
293+ < div className = "flex items-center gap-1.5 mb-3" >
294+ < Zap
295+ className = { `h-3 w-3 ${ isDark ? "text-blue-400" : "text-[#EB5601]" } ` }
296+ />
297+ < p
298+ className = { `text-[10px] uppercase tracking-wider ${
299+ isDark ? "text-zinc-600" : "text-[#8b7355]"
300+ } `}
301+ >
302+ Top CLI
303+ </ p >
304+ </ div >
305+ < div className = "space-y-1.5" >
306+ { topSources . length === 0 ? (
291307 < p
292- className = { `text-[10px] uppercase tracking-wider ${
293- isDark ? "text-zinc-600" : "text-[#8b7355]"
294- } `}
308+ className = { `text-xs ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
295309 >
296- Top CLI
310+ No data yet
297311 </ p >
298- </ div >
299- < div className = "space-y-1.5" >
300- { topSources . length === 0 ? (
301- < p
302- className = { `text-xs ${ isDark ? "text-zinc-600" : "text-[#8b7355]" } ` }
312+ ) : (
313+ topSources . map ( ( item , index ) => (
314+ < div
315+ key = { item . source }
316+ className = "flex items-center justify-between"
303317 >
304- No data yet
305- </ p >
306- ) : (
307- topSources . map ( ( item , index ) => (
308- < div
309- key = { item . source }
310- className = "flex items-center justify-between"
318+ < span
319+ className = { `text-xs truncate max-w-[140px] ${
320+ isDark ? "text-zinc-400" : "text-[#6b6b6b]"
321+ } `}
311322 >
312323 < span
313- className = { `text-xs truncate max-w-[140px] ${
314- isDark ? "text-zinc-400" : "text-[#6b6b6b]"
315- } `}
316- >
317- < span
318- className = { `mr-1.5 ${
319- index === 0
320- ? isDark
321- ? "text-blue-400"
322- : "text-[#EB5601]"
323- : isDark
324- ? "text-zinc-600"
325- : "text-[#8b7355]"
326- } `}
327- >
328- { index + 1 } .
329- </ span >
330- { getSourceDisplayName ( item . source ) }
331- </ span >
332- < span
333- className = { `text-[10px] tabular-nums ${
334- isDark ? "text-zinc-500" : "text-[#8b7355]"
324+ className = { `mr-1.5 ${
325+ index === 0
326+ ? isDark
327+ ? "text-blue-400"
328+ : "text-[#EB5601]"
329+ : isDark
330+ ? "text-zinc-600"
331+ : "text-[#8b7355]"
335332 } `}
336333 >
337- { item . sessions } sessions
334+ { index + 1 } .
338335 </ span >
339- </ div >
340- ) )
341- ) }
342- </ div >
336+ { getSourceDisplayName ( item . source ) }
337+ </ span >
338+ < span
339+ className = { `text-[10px] tabular-nums ${
340+ isDark ? "text-zinc-500" : "text-[#8b7355]"
341+ } `}
342+ >
343+ { item . sessions } sessions
344+ </ span >
345+ </ div >
346+ ) )
347+ ) }
343348 </ div >
344349 </ div >
345350 </ div >
346- ) ;
351+ </ div >
352+ ) ;
347353}
348354
349355// TEMP: Stats components moved to /stats page
0 commit comments