Explorer
The Explorer is a block explorer in the usual shape: one search box, a chain, and pages for an address, a transaction and a block, with every hash, address and block number on them linked to its own page. Under the hood the page calls the docs worker and the worker calls the library through withProvider(), so what you see is exactly what a script gets: the normalized shapes, the provider that answered, and its typed errors. No second code path that happens to look similar.
Pages
| Page | Reads | Tool equivalent |
|---|---|---|
/explorer | the chain's tip: height, stats, the latest blocks and transactions, refreshed every fifteen seconds | none, see below |
/explorer/address/:chain/:id | getBalance, then tabs for getTxHistory, getUtxos, getTokenBalances, getTokenTransfers and getContractInfo | explorers_balance, explorers_tx_history, explorers_utxos, explorers_tokens, explorers_token_transfers, explorers_contract |
/explorer/tx/:chain/:hash | getTxDetail, token transfers, OP_RETURN payloads and inscriptions included | explorers_tx_detail |
/explorer/block/:chain/:number | getBlockInfo, with previous and next | explorers_block |
/explorer/gas | getGasData on every chain with a provider that quotes fees | explorers_gas |
/explorer/providers | which providers the worker holds a key for | explorers_providers |
The search box classifies what you typed the way classifyInput does in the library: 64 hex characters is a transaction on Ethereum, the Bitcoin family, TRON, Cardano and Decred, a base58 string of the right length is a transaction on Solana and Sui, digits are a block, everything else is an address, and a .eth name resolves on the address page. Arweave ids and addresses share a shape, so the address page offers the transaction reading as a link.
Every page is a deep link. An address page keeps its tab and page number in the query, so /explorer/address/ethereum/vitalik.eth?tab=tokens opens on the holdings. Tabs a chain can't serve aren't shown: no token tab on Bitcoin, no contract tab on Solana, no unspent outputs on Ethereum. History and transfers get a pager on every chain, Solana, TON, TRON and Sui included. The providers that walk a cursor give up at page 41, a thousand rows in, and they say so. Page one again would be a lie.
The live feed
The library reads one address, one hash or one block at a time. It has no "latest blocks" read, and a block explorer without one is a search box. So the hub asks the chain's public explorer API directly, through the library's own getJSON, for the few list endpoints the providers don't wrap: Blockscout's /api/v2/stats, /api/v2/blocks and /api/v2/transactions on the ten EVM chains it serves, Mempool's /api/v1/blocks, /api/mempool and /api/mempool/recent on Bitcoin, Litecoin and Pepecoin, and the Arweave gateway's /info, /block/current and GraphQL index. The block page lists a block's transactions the same way. Everything else on the site runs the library. The ten other chains have no keyless feed, and the hub says so instead of pretending. When the library grows a tip read, docs/server/utils/tip.ts goes away, and good riddance.
Caching and manners
Answers are cached on the worker, in KV in production: two minutes for a balance and for unspent outputs, five for history and transfers, ten for holdings, an hour for a transaction or a block, a day for contract metadata, thirty seconds for gas and for the feed. A thrown failure is never cached, so a typo or an outage doesn't stick. One visitor gets thirty new explorer requests a minute. Cache hits are free. On IPv6 the visitor is the whole /64, so hopping through 2^64 fresh addresses buys nothing. The public explorers rate limit by address and the whole site runs on one, so the cache isn't optional.
Inputs are capped before they reach the library: an address, a name or a hash is at most 128 characters of letters, digits, dots, dashes, underscores and colons, a page is at most 25 rows, a block number at most two billion. raw never leaves the worker, a contract's ABI and source get measured rather than shipped, and token holdings and unspent outputs stop at fifty rows with the total alongside. The worker isn't a proxy to arbitrary URLs and takes no baseUrl.
Where a key matters
The worker holds keys as Cloudflare secrets, never in the page. Without ETHERSCAN_API_KEY every EVM read goes through Blockscout, which serves the same eight operations. Without SOLSCAN_API_KEY or HELIUS_API_KEY Solana answers 503, without TRONSCAN_API_KEY TRON does, without BLOCKBERRY_API_KEY Sui does. The Providers page says which keys the worker has. Never a key, just configured or not.
The landing
The panels on the home page start from answers recorded through the library and labelled recorded. As the page walks through three addresses on three chains, each one gets swapped for the worker's live answer and relabelled live. The recorded answers live in docs/app/utils/landing-fixtures.ts and are regenerated with pnpm fixtures. Never by hand. Hand edited fixtures drift and nobody notices until a reader does.