fix(web): the standings do not belong under a node
All checks were successful
deploy / build (push) Successful in 43s
deploy / deploy-api (push) Has been skipped
deploy / deploy-web (push) Successful in 5s

Reported: the board was still rendering beneath the node route. It was a fourth
place spelling out "is this the standings?" by hand — the board's own render
condition, which I missed when extracting `isStandings` for the other three.

That predicate now has one definition and four callers: the section nav, the
window selector, the canonicalising redirect, and the board. Grepped for
survivors; there are none.

Worth recording how both node-route bugs were found, because it is the same
lesson twice in one feature: the route parsed, the page existed, every gate was
green, and only opening the page in a browser showed that the address bar threw
it away the first time and that thirty mining rows sat under it the second.

Checked: `/quantus/node/<peer>` renders one panel, no `.two-col`, no board rows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
2026-09-13 20:33:55 +03:00
parent fac73f392c
commit 3551b832a0
2 changed files with 41 additions and 38 deletions

View File

@@ -402,13 +402,16 @@ nobody: a node visible on the official telemetry site was invisible here. The
`/:chain/node` index and `/:chain/node/:peer` route have no entry condition,
and the miner panel now links to them rather than being the only way in.
**"Is this the standings?" is one function, not three.** `isStandings` in
`lib/routes.ts`. Adding the node section updated the copies in `SectionNav` and
`windowApplies` and missed the canonicalising redirect in `App`, which judged
**"Is this the standings?" is one function, not four.** `isStandings` in
`lib/routes.ts`. Adding the node section had to update the section nav, the
window selector, the canonicalising redirect and the board's own render
condition — and the first pass caught two of them. The redirect judged
`/quantus/node/<peer>` to be the standings and replaced it with
`/quantus/3600-blocks` the route parsed, the page existed, and the address bar
threw it away before it rendered. A new section still has to be added to the
predicate; it now has one place to be added to.
`/quantus/3600-blocks`, and the render condition left thirty unrelated mining
rows under the node. Both were reported rather than caught: the route parsed,
the page existed, the build was green, and only opening it showed either. A new
section still has to be added to the predicate; it now has one place to be added
to.
**Telemetry hardware is the node's word, reached by inference.** A miner is
joined to a node through the same first-reporter voting that produces its

View File

@@ -269,39 +269,39 @@ export default function App() {
)}
{route.index === 'node' && chain && <NodesIndex chain={chain} />}
{!route.account &&
!route.miner &&
!route.block &&
route.runtime === null &&
route.call === null &&
route.event === null &&
route.index === null && (
<div className="two-col">
<section className="panel">
<div className="panel-head">
<h2 className="panel-title">The Standings</h2>
<span className="eyebrow">
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
{measuredSpan(state.windowSeconds, activeWindow.blocks, interval)}
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
</span>
</div>
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
</section>
{/* The standings and the live ticker belong to the standings route and
nowhere else. A page that names one subject has that subject as its
whole subject; leaving thirty unrelated mining rows underneath is the
site failing to notice which page it is on. This was the fourth place
spelling out "is this the standings?" by hand — and the one that kept
showing the board under a node. */}
{isStandings(route) && (
<div className="two-col">
<section className="panel">
<div className="panel-head">
<h2 className="panel-title">The Standings</h2>
<span className="eyebrow">
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
{measuredSpan(state.windowSeconds, activeWindow.blocks, interval)}
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
</span>
</div>
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
</section>
<section className="panel">
<div className="panel-head">
<h2 className="panel-title">Live Blocks</h2>
<span className="eyebrow">
{state.summary?.block_interval_seconds
? `${seconds(state.summary.block_interval_seconds)} apart`
: 'measuring'}
</span>
</div>
<BlockTicker blocks={state.blocks} chain={chain} />
</section>
</div>
)}
<section className="panel">
<div className="panel-head">
<h2 className="panel-title">Live Blocks</h2>
<span className="eyebrow">
{state.summary?.block_interval_seconds
? `${seconds(state.summary.block_interval_seconds)} apart`
: 'measuring'}
</span>
</div>
<BlockTicker blocks={state.blocks} chain={chain} />
</section>
</div>
)}
<footer className="footer">
<span>