Full Stack Web3
Full Stack Web3 — Ship your first complete voting dApp (ChainElect) backed by Supabase.
Start with a naive React and MetaMask prototype, watch it fail in production, and rewrite it. We'll solve real-world problems: scaling reads, caching IPFS, and indexing events.
ChainElect — Socio3 Classic → Evolution
Start with the naive React+MetaMask+direct-contract architecture. Watch it break at scale. Evolve it through backend introduction, Redis caching, and The Graph indexing until it becomes production-grade.
My First Social dApp
The starting architecture: React calls contracts directly, MetaMask is the only auth, Firebase stores metadata. Works at 20 users. Setting up the narrative before the pain.
My first thought: I only need the blockchain
The naive starting point — React calling contracts directly, MetaMask as the only backend, and why it actually works at small scale.
Connecting MetaMask to React — the real way
Network validation, chain switching, event listeners, and disconnection handling. The production-grade wallet connection pattern.
Reading and writing to contracts from React
The complete flow for reads (view calls), writes (signed transactions), pending states, receipts, and error handling.
The First Pain: Fetching
getAllVoters() worked at 30 voters. At 1,000 it froze the browser. RPC rate limits, eth_getLogs block ceilings, and why event-driven loading is the correct pattern.
Why fetching from blockchain hurt — the getAllVoters() disaster
What happens when direct contract reads scale from 10 items to 1,000. RPC timeouts, silent failures, and the moment you realize blockchain is not a database.
The hidden limits of eth_getLogs
Why event log queries break at scale. Block range limits, RPC node restrictions, and the silent empty array bug.
Event-driven data loading — the correct pattern
Using contract events as the source of truth: historical replays, real-time WebSocket subscriptions, and the bridge to off-chain indexing.
Why Backend Suddenly Appeared
The Pinata API key was in the browser JS bundle. Someone DM'd me the key. This is the story of why every serious Web3 dApp needs a backend — and what the backend's actual job is.
Where does blockchain data actually live?
The 3-layer hybrid architecture. Frontend, backend, and blockchain — what runs where, and why beginners think the blockchain does everything.
The day I realized the frontend is not enough
Why frontend code is a public document, how API key exposure happens in production, and the four operations that require a backend.
Building the Express proxy layer for IPFS uploads
The complete Node.js/Express backend that proxies IPFS uploads, validates sessions, and keeps API keys server-side only.
Why Redis Suddenly Appeared
IPFS gateways took 3–5 seconds per image. The admin panel took 8.3 seconds to load. 60% drop-off. This is why Redis appeared — and why cache invalidation in Web3 is uniquely elegant.
Why we added Redis — IPFS was too slow
How direct IPFS gateway loads were killing UX, how Redis dropped load times from 4s to 80ms, and the Web3-specific cache invalidation insight.
Setting up Redis caching in Next.js
How to initialize Upstash Redis, set up a Next.js API route to cache slow IPFS requests, and build a resilient fallback handler.
Cache invalidation in Web3 — when does truth change?
Immutable content-addressed caching vs mutable on-chain state. TTL-based vs event-driven invalidation. The hybrid cache strategy for a voting dApp.
Why Indexing Appeared
The PM asked for a leaderboard sorted by votes. There is no ORDER BY in Solidity. This is why The Graph was invented — and how to deploy a subgraph that replaces all direct contract reads.
Why blockchain needs indexers — the sort/filter problem
The EVM has no query engine. No sorting, filtering, or aggregation. Why fetching everything to sort in JS doesn't scale — and how indexers pre-process events.
How The Graph works internally
Subgraphs, indexing nodes, AssemblyScript handlers, and how The Graph processes every blockchain event into a queryable GraphQL database.
Writing and deploying your first subgraph
Step-by-step: define entities, write AssemblyScript event handlers, deploy to Subgraph Studio, and query the leaderboard with GraphQL.
