feat: section indexes, so the routes can be found
deploy / build (push) Successful in 7m33s
deploy / deploy-web (push) Successful in 5s
deploy / deploy-api (push) Successful in 15s

Every route added lately was reachable only by already knowing an address — a
block hash, a preimage, an SS58 string, a spec_version. Fine for a link somebody
sent you, useless for discovering the pages exist. A kind with nothing after it
is now the index of that kind, and a nav under the chain chips names them.

Not the same page three times. Blocks is the record behind the live ticker,
paged by height. Accounts ranks by tokens earned over the whole indexed record,
which is a different question from the standings' blocks-per-window and here a
different answer: difficulty rose 346-fold inside mainnet's first day, so an
early block cost a three-hundredth of a current one. Runtimes is the only list
with no other home — a block does not name its runtime and neither do the
standings.

No `/:chain/miner`: the standings already are the index of miners, and a second
page of the same rows under another address would be two answers to one
question. That path redirects there, along with anything else that resolves to
the front page without being spelled like it, so the address bar and the section
nav agree about where the reader is.

Two things caught by looking at the rendered pages:

The block index's gaps came from `observed_at` and read *three milliseconds*
between blocks on a chain targeting twelve seconds — exactly the trap CLAUDE.md
records, since a gap fill writes a whole batch within one second. They come from
`authored_at` now, the chain's own clock.

The first page of that index came from the live ticker, which is ordered
oldest-first because that is the order it is pushed in, so page one climbed and
every page after it descended. The index sends a cursor for its first page too.

Accounts shows the address beside any node name: one node legitimately reports
for several payout addresses, and the first cut had two rows reading
`pearl-prover` with nothing to tell them apart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
2026-09-09 18:07:11 +03:00
co-authored by Claude Opus 5
parent 289a80a7eb
commit efbe901646
16 changed files with 1082 additions and 31 deletions
+61
View File
@@ -0,0 +1,61 @@
/**
* The site's sections.
*
* Every route this site has was reachable only by already knowing an address —
* a block hash, a preimage, an SS58 string, a spec_version. That is fine for a
* link somebody sent you and useless for finding out the pages exist at all.
* This is the answer to "what else is here".
*
* The standings are the first entry because they are the front page, and there
* is no "Miners" beside them for the same reason: the standings already are the
* index of miners, and a second page listing the same rows under a different
* address would be two answers to one question.
*/
import { Link } from 'react-router-dom'
import type { Window as WindowName } from '../api/generated/Window'
import { href, type Route, SECTIONS } from '../lib/routes'
export function SectionNav({
chain,
route,
window: windowName,
}: {
chain: string | null
route: Route
/** Carried into the standings link so leaving a section and coming back does
* not silently reset the span someone chose. */
window: WindowName
}) {
if (!chain) return null
// The standings are current when nothing else is: no panel open, no index.
const onStandings =
route.index === null &&
route.block === null &&
route.miner === null &&
route.account === null &&
route.runtime === null
return (
<nav className="sections" aria-label="Section">
<Link
to={href({ chain, window: windowName })}
className="section-link"
aria-current={onStandings ? 'page' : undefined}
>
Standings
</Link>
{SECTIONS.map((s) => (
<Link
key={s.id}
to={href({ chain, index: s.id })}
className="section-link"
aria-current={route.index === s.id ? 'page' : undefined}
>
{s.label}
</Link>
))}
</nav>
)
}