Overview
src/components/Navbar/Navbar.tsx renders, for every disconnected visitor on every single page of the app (the navbar is mounted once in AppShell, globally), three "live"-looking stat pills:
{isConnected && publicKey ? (
<StatPill label="Wallet" value={shortenStellarAddress(publicKey)} />
) : (
<>
<StatPill label="Online" value="213" pulse />
<StatPill label="Users" value="30,738" />
<StatPill label="TVL" value="$302M" />
</>
)}
"213", "30,738", and "$302M" are raw string literals baked directly into JSX. There is no useQuery, no fetch, no sorobanService call, no prop, nothing — these three numbers can never change, are not connected to any data source in the codebase, and will read the same on the day the app has zero users as on a day it has a million. The pulse prop on the "Online" pill renders an animated pulsing dot (StatPill, Navbar.tsx:91-101, className="animate-pulse"), a UI convention universally understood to mean "this is live/real-time data" — actively reinforcing the false impression that 213 is a real, moving online-user count. This is materially different from (and more absolute than) the app's other fabricated-stat issues: it isn't a heuristic derived from some real number, it's three constants with no data source at all, and it's the single most-seen fabricated number in the app, since it renders on literally every page for every not-yet-connected visitor — the most common state for a first-time visitor evaluating the product.
Requirements
- Replace the three hardcoded pill values with real data from an existing live source (
usePlatformStats()/sorobanService.getPlatformStats(), already used elsewhere in the app), or remove the pills entirely if no real "online users" concept exists yet.
- If "Online" (concurrent presence) has no real backing data source at all (unlike TVL/total users, which do have a real, if imperfect, code path via
getPlatformStats()), don't display a pulsing "live" indicator over a number that cannot possibly be live — either drop that specific pill or clearly relabel it as something it accurately is.
- Ensure the values actually update over time (respecting whatever
refetchInterval the underlying query already uses) rather than being computed once and frozen.
Acceptance Criteria
Additional Notes
More precise references
src/components/Navbar/Navbar.tsx:131-140 — confirmed the exact JSX and literal values ("213", "30,738", "$302M").
src/components/Navbar/Navbar.tsx:91-101 (StatPill) — confirmed the pulse prop renders <span className="h-1.5 w-1.5 shrink-0 animate-pulse rounded-full bg-...accent" />, applied only to the "Online" pill.
src/components/Navbar/Navbar.tsx:1-13 — confirmed the file's imports contain no data-fetching hook of any kind (useStellarWallet is imported only for isConnected/publicKey, not stats).
src/hooks/useSorobanQuery.ts:468-492 (usePlatformStats) — confirmed this is the existing, already-real (factory-driven) hook used elsewhere (e.g. PlatformStats.tsx, page.tsx) that could supply real totalUsers/tvl values here instead.
Additional edge cases
BASE_USERS = 30_738 and BASE_TVL_MILLIONS = 302 in src/lib/stats.ts:77-78 produce the exact same "30,738" and (once formatted) "$302M" figures as this Navbar's hardcoded literals — see the separate "dead fake stats subsystem" issue in this batch. The two files were evidently seeded from the same one-time demo numbers independently; fixing one without checking the other risks leaving a second, differently-shaped copy of the same fabricated data behind.
- Because these pills only render in the disconnected state (
!isConnected), this bug is invisible to anyone testing primarily as a connected wallet user — worth noting in the PR/test plan so reviewers deliberately check the logged-out navbar, not just the logged-in one.
Implementation sketch
const { data: stats } = usePlatformStats();
...
<StatPill label="Users" value={stats ? stats.totalUsers.toLocaleString() : "—"} />
<StatPill label="TVL" value={stats?.totalValueLocked ?? "—"} />
// "Online" pill: either removed, or wired to a real presence metric if/when one exists
Test/reproduction plan
- Mock
usePlatformStats to return { totalUsers: 42, totalValueLocked: "$1,234" }; render Navbar in the disconnected state; assert "42" and "$1,234" (not "30,738"/"$302M") appear.
- Mock a second, different
usePlatformStats result; re-render; assert the displayed text changes accordingly (proves it's live-bound, not just swapped for a different constant).
Cross-references
Overview
src/components/Navbar/Navbar.tsxrenders, for every disconnected visitor on every single page of the app (the navbar is mounted once inAppShell, globally), three "live"-looking stat pills:"213","30,738", and"$302M"are raw string literals baked directly into JSX. There is nouseQuery, nofetch, nosorobanServicecall, no prop, nothing — these three numbers can never change, are not connected to any data source in the codebase, and will read the same on the day the app has zero users as on a day it has a million. Thepulseprop on the "Online" pill renders an animated pulsing dot (StatPill,Navbar.tsx:91-101,className="animate-pulse"), a UI convention universally understood to mean "this is live/real-time data" — actively reinforcing the false impression that213is a real, moving online-user count. This is materially different from (and more absolute than) the app's other fabricated-stat issues: it isn't a heuristic derived from some real number, it's three constants with no data source at all, and it's the single most-seen fabricated number in the app, since it renders on literally every page for every not-yet-connected visitor — the most common state for a first-time visitor evaluating the product.Requirements
usePlatformStats()/sorobanService.getPlatformStats(), already used elsewhere in the app), or remove the pills entirely if no real "online users" concept exists yet.getPlatformStats()), don't display a pulsing "live" indicator over a number that cannot possibly be live — either drop that specific pill or clearly relabel it as something it accurately is.refetchIntervalthe underlying query already uses) rather than being computed once and frozen.Acceptance Criteria
Navbar's "Users" and "TVL" pills render values sourced fromusePlatformStats()(or equivalent live query), not string literals.usePlatformStatsreturn value) changes what the Navbar displays.usePlatformStatsresults across two renders and asserting the displayed text differs accordingly).Additional Notes
More precise references
src/components/Navbar/Navbar.tsx:131-140— confirmed the exact JSX and literal values ("213","30,738","$302M").src/components/Navbar/Navbar.tsx:91-101(StatPill) — confirmed thepulseprop renders<span className="h-1.5 w-1.5 shrink-0 animate-pulse rounded-full bg-...accent" />, applied only to the "Online" pill.src/components/Navbar/Navbar.tsx:1-13— confirmed the file's imports contain no data-fetching hook of any kind (useStellarWalletis imported only forisConnected/publicKey, not stats).src/hooks/useSorobanQuery.ts:468-492(usePlatformStats) — confirmed this is the existing, already-real (factory-driven) hook used elsewhere (e.g.PlatformStats.tsx,page.tsx) that could supply realtotalUsers/tvlvalues here instead.Additional edge cases
BASE_USERS = 30_738andBASE_TVL_MILLIONS = 302insrc/lib/stats.ts:77-78produce the exact same"30,738"and (once formatted)"$302M"figures as this Navbar's hardcoded literals — see the separate "dead fake stats subsystem" issue in this batch. The two files were evidently seeded from the same one-time demo numbers independently; fixing one without checking the other risks leaving a second, differently-shaped copy of the same fabricated data behind.!isConnected), this bug is invisible to anyone testing primarily as a connected wallet user — worth noting in the PR/test plan so reviewers deliberately check the logged-out navbar, not just the logged-in one.Implementation sketch
Test/reproduction plan
usePlatformStatsto return{ totalUsers: 42, totalValueLocked: "$1,234" }; renderNavbarin the disconnected state; assert"42"and"$1,234"(not"30,738"/"$302M") appear.usePlatformStatsresult; re-render; assert the displayed text changes accordingly (proves it's live-bound, not just swapped for a different constant).Cross-references
lib/stats.ts.totalUsers * 0.1) on the homepage; this is about literal, unconnected constants on the globally-mounted Navbar, a different component with a different (and more absolute) failure mode.