Blockchain Explorer: Build Your Own Chain Explorer
A blockchain explorer is the window into on-chain activity. Whether you are building for a public chain, a testnet, or a private enterprise blockchain, having a fast and intuitive explorer is essential for developers and users to verify transactions, track assets, and audit smart contracts. A blockchain explorer template provides a complete frontend for any EVM-compatible chain.
Core Explorer Features
A production blockchain explorer built with the Blockchain Explorer template includes:
- Block Explorer: View recent blocks with timestamps, gas usage, and transaction counts
- Transaction Details: Full transaction data including inputs, logs, and status
- Address View: Token balances, transaction history, and contract interactions
- Token Tracker: ERC-20 and ERC-721 token transfers and holders
- Smart Contract Reader: Read contract state and decode function calls
- Search: Search by block number, transaction hash, address, or token
Setting Up the Explorer Template
git clone https://github.com/breafio/blockchain-explorer.git my-explorer
cd my-explorer
pnpm install
cp .env.example .env.localAPI Layer
The explorer needs efficient blockchain data indexing:
// lib/explorer/api.ts
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({
chain: mainnet,
transport: http(process.env.RPC_URL || 'https://eth-mainnet.g.alchemy.com/v2/demo'),
})
export interface BlockData {
number: bigint
hash: string
timestamp: bigint
transactions: string[]
gasUsed: bigint
gasLimit: bigint
miner: string
size: bigint
}
export async function getBlock(blockNumber: bigint): Promise<BlockData> {
const block = await client.getBlock({ blockNumber, includeTransactions: false })
return {
number: block.number!,
hash: block.hash!,
timestamp: block.timestamp,
transactions: block.transactions as string[],
gasUsed: block.gasUsed,
gasLimit: block.gasLimit,
miner: block.miner,
size: block.size,
}
}
export async function getLatestBlocks(count: number = 25): Promise<BlockData[]> {
const latestBlock = await client.getBlockNumber()
const blocks: BlockData[] = []
for (let i = 0; i < count; i++) {
const block = await getBlock(latestBlock - BigInt(i))
blocks.push(block)
}
return blocks
}Transaction Details
Displaying transaction data requires decoding input data and parsing logs:
import { createPublicClient, http, decodeFunctionData, formatEther } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({ chain: mainnet, transport: http() })
export interface TransactionData {
hash: string
from: string
to: string | null
value: bigint
gasPrice: bigint
gas: bigint
input: string
status: 'success' | 'reverted'
timestamp: bigint
blockNumber: bigint
logs: Log[]
}
export async function getTransaction(txHash: string): Promise<TransactionData | null> {
const tx = await client.getTransaction({ hash: txHash as string })
const receipt = await client.getTransactionReceipt({ hash: txHash as string })
const block = await client.getBlock({ blockNumber: tx.blockNumber! })
if (!tx) return null
return {
hash: tx.hash,
from: tx.from,
to: tx.to,
value: tx.value,
gasPrice: tx.gasPrice!,
gas: tx.gas,
input: tx.input,
status: receipt.status === 'success' ? 'success' : 'reverted',
timestamp: block.timestamp,
blockNumber: tx.blockNumber!,
logs: receipt.logs,
}
}Search Functionality
A smart search that detects the type of query:
'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
export function ExplorerSearch() {
const [query, setQuery] = useState('')
const router = useRouter()
const handleSearch = (e: React.FormEvent) => {
e.preventDefault()
const q = query.trim()
if (/^d+$/.test(q)) {
router.push(`/explorer/block/${q}`)
} else if (q.length === 66 && q.startsWith('0x')) {
// Could be a transaction or address
router.push(`/explorer/search?q=${q}`)
} else if (q.length === 42 && q.startsWith('0x')) {
router.push(`/explorer/address/${q}`)
} else {
router.push(`/explorer/search?q=${encodeURIComponent(q)}`)
}
}
return (
<form onSubmit={handleSearch} className="relative">
<Search className="absolute left-4 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
<input
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Search by block, tx, address, or token..."
className="w-full rounded-xl border border-gray-200 bg-white py-3 pl-11 pr-4 text-sm shadow-sm"
/>
</form>
)
}The Bottom Line
A blockchain explorer is essential infrastructure for any EVM-based chain. The Blockchain Explorer template provides a complete, customizable frontend with block viewing, transaction details, address tracking, token analytics, and smart search — all powered by Viem and ready to deploy against any EVM RPC endpoint.
Related Template
Try this production-ready starter kit to build your project faster.
Latest Blocks
| Block | Hash | Age | Txns | Gas Used | Miner | Reward |
|---|---|---|---|---|---|---|
| 19,842,501 | 0x7F3a...b9E2 | 12s ago | 245 | 62.4% | 0x4F2a...cB91 | 0.124 ETH |
| 19,842,500 | 0x8A1b...dE34 | 24s ago | 189 | 48.2% | 0x8A1b...dE34 | 0.118 ETH |
| 19,842,499 | 0x3C7d...fA12 | 36s ago | 312 | 78.5% | 0x3C7d...fA12 | 0.142 ETH |
| 19,842,498 | 0x9E5f...bC78 | 48s ago | 156 | 35.1% | 0x9E5f...bC78 | 0.095 ETH |
| 19,842,497 | 0x2B8a...dE90 | 1m ago | 278 | 71.3% | 0x2B8a...dE90 | 0.135 ETH |
| 19,842,496 | 0x5D3f...gH12 | 1m 12s ago | 201 | 55.8% | 0x5D3f...gH12 | 0.108 ETH |
| 19,842,495 | 0x7A4b...iJ34 | 1m 24s ago | 167 | 42.6% | 0x7A4b...iJ34 | 0.102 ETH |
| 19,842,494 | 0x1C2d...kL56 | 1m 36s ago | 345 | 82.1% | 0x1C2d...kL56 | 0.158 ETH |
Blockchain Explorer
Explore any EVM chain
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits