gm
.careers
Back to Blog

Frontend Developer in Web3: Building dApps with React & Viem

A practical guide for frontend developers entering Web3 — wallet integrations, transaction UX, modern tooling with wagmi and viem, portfolio projects, and salary expectations.

gm.careers TeamFebruary 10, 202614 min read
Share:TwitterLinkedIn

Frontend development in Web3 is not just "React but with a Connect Wallet button." The shift from building against a centralized backend to building against a decentralized blockchain introduces an entirely different set of UX challenges, technical constraints, and state management problems that traditional frontend frameworks were never designed for.

If you are a frontend developer with React and TypeScript experience, you already have the foundation. What you need is the Web3-specific layer: understanding how wallets work, how to read and write to blockchains, how to handle the inherent latency and uncertainty of on-chain transactions, and how to build interfaces that make all of this feel seamless to users who may have never interacted with a blockchain before.

This guide covers the practical skills, modern tooling stack, UX patterns, portfolio projects, and salary expectations for frontend developers entering Web3.

What Makes Web3 Frontend Different

In a traditional web application, your frontend talks to a backend API. You send a request, the backend processes it, and you get a response — usually within milliseconds. The backend handles authentication, authorization, and data persistence. The user experience is predictable.

In a dApp, your frontend talks directly to a blockchain through the user's wallet. This changes everything:

  • Authentication is wallet-based — There are no usernames and passwords. Users prove their identity by signing messages with their private key.
  • Writes are transactions — Every state change on the blockchain requires a transaction that must be signed by the user, submitted to the network, and confirmed in a block. This takes seconds to minutes, not milliseconds.
  • Reads are free but writes cost money — Reading blockchain data is free. Writing to it costs gas, which the user pays. Your UI must communicate these costs clearly.
  • State is public and verifiable — Anyone can read the blockchain state. There is no "private" data on-chain (with some exceptions around encryption and ZK).
  • Errors are different — Transaction failures, gas estimation errors, chain switching issues, and wallet connection problems are all new failure modes that do not exist in Web2.

The biggest mental shift for Web2 frontend developers is this: in Web3, the user is the server. Their wallet holds their private key, signs transactions, and pays for execution. Your frontend is a thin interface that helps them interact with smart contracts. You do not control the backend — nobody does.

The Modern Web3 Frontend Stack

The tooling landscape for Web3 frontend development has matured significantly. Here is the stack that most production dApps use in 2026:

Core Framework: React + Next.js + TypeScript

This is the same foundation you already know. Next.js with App Router is the standard for production dApps because of its routing, server-side rendering capabilities, and the broader React ecosystem. TypeScript is non-negotiable — the type safety it provides when working with smart contract ABIs and blockchain data is essential.

Blockchain Interaction: Viem

Viem is the low-level TypeScript library for interacting with Ethereum and EVM-compatible chains. It replaced ethers.js and web3.js as the standard because of its:

  • Type safety — Full TypeScript support with inferred types from contract ABIs
  • Performance — Smaller bundle size and faster execution than alternatives
  • Modular design — Import only what you need
  • Chain support — Built-in support for every major EVM chain

You use viem for encoding/decoding contract calls, formatting addresses and values, working with transaction receipts, and interacting with RPC providers directly.

React Hooks: Wagmi v2

Wagmi is the React hooks library built on top of viem. It provides hooks for everything you need in a dApp:

  • useAccount — Current connected wallet address and connection status
  • useConnect / useDisconnect — Wallet connection management
  • useBalance — Read token or ETH balances
  • useReadContract — Call view/pure functions on smart contracts
  • useWriteContract — Send transactions to smart contracts
  • useWaitForTransactionReceipt — Wait for transaction confirmation
  • useChainId / useSwitchChain — Chain management

Wagmi handles caching, deduplication, and revalidation of blockchain data automatically, similar to how TanStack Query handles API data.

Wallet Connection: RainbowKit or ConnectKit

These libraries provide pre-built UI components for wallet connection:

  • RainbowKit — The most popular option. Provides a polished modal that supports MetaMask, Coinbase Wallet, WalletConnect, and dozens of other wallets. Highly customizable.
  • ConnectKit — A lighter alternative by Family. Cleaner default design, fewer features.
  • AppKit (by WalletConnect) — The first-party solution from the WalletConnect team.

These libraries integrate directly with wagmi and handle the complex logic of detecting installed wallets, managing WalletConnect sessions, and providing a consistent UX across wallet providers.

Start with RainbowKit. It has the largest community, the most documentation, and handles edge cases (mobile wallets, hardware wallets, wallet discovery) that you would not want to build yourself. You can customize the theme to match your dApp's design system.

Data Indexing: The Graph or Custom Subgraphs

Reading data directly from the blockchain is limited — you can only call functions on smart contracts, not query historical data or aggregate across events. For complex data needs, you need an indexer:

  • The Graph — A decentralized indexing protocol. You write a subgraph that defines how to process blockchain events, and The Graph indexes them into a queryable GraphQL API.
  • Ponder — A newer, developer-friendly framework for building indexers locally. Excellent for rapid development.
  • Custom backends — Some dApps run their own indexing infrastructure using tools like Alchemy webhooks or direct event log processing.

Essential UX Patterns

Web3 introduces UX patterns that do not exist in traditional web development. Mastering these is what separates a good dApp from a frustrating one.

The Connect Wallet Flow

The wallet connection flow is the first interaction users have with your dApp. Get it wrong, and they leave.

Best practices:

  • Show value before requiring connection — Let users browse and explore your dApp without connecting. Require a wallet only when they want to take an action.
  • Support multiple wallets — Not everyone uses MetaMask. Support at least MetaMask, Coinbase Wallet, WalletConnect (for mobile), and injected wallets.
  • Handle the "no wallet" case — If a user does not have a wallet installed, guide them to install one rather than showing a cryptic error.
  • Persist connection — Use wagmi's built-in reconnection to remember the user's wallet across page reloads.
  • Show the connected state clearly — Display the connected address (truncated with ENS resolution if available), the current chain, and a disconnect option.

Transaction State Management

A blockchain transaction goes through multiple states, and your UI must communicate each one:

  1. Preparing — You are building the transaction and estimating gas
  2. Awaiting signature — The wallet is open, waiting for the user to approve
  3. Pending — The transaction has been submitted to the mempool but not yet included in a block
  4. Confirming — The transaction is in a block but may not have enough confirmations yet
  5. Confirmed — The transaction has been finalized
  6. Failed — The transaction reverted on-chain (the user still paid gas)
  7. Rejected — The user rejected the transaction in their wallet (no gas paid)

Each state should be visible to the user. A common pattern is a toast notification that tracks the transaction through its lifecycle, with a link to a block explorer (Etherscan, Basescan) for transparency.

// Simplified example using wagmi hooks
const { writeContract, data: hash, isPending } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });

// isPending = waiting for wallet signature
// isConfirming = tx submitted, waiting for block inclusion
// isSuccess = transaction confirmed

Never tell a user their transaction "succeeded" before it is actually confirmed on-chain. A submitted transaction can still fail if it reverts during execution. Wait for the receipt and check the status field.

Gas Estimation and Cost Display

Users pay gas for every on-chain transaction. Your UI should:

  • Estimate gas before the transaction — Use viem's estimateGas to show users the approximate cost in ETH/USD before they sign.
  • Show the cost in their local currency — Not everyone thinks in ETH. Convert the gas cost to USD (or their preferred currency) using a price feed.
  • Warn about high gas — If a transaction will cost more than a reasonable threshold, show a warning. Some users accidentally submit transactions during gas spikes.
  • Handle estimation failures gracefully — If gas estimation fails, it usually means the transaction would revert. Show a clear error rather than letting the user submit a doomed transaction.

Chain Switching

Your dApp may support multiple chains (Ethereum mainnet, Base, Arbitrum, Optimism). When a user is connected to the wrong chain:

  • Detect the mismatch — Compare useChainId() with your expected chain.
  • Prompt to switch — Use useSwitchChain() to request the wallet switch to the correct chain.
  • Handle rejection — If the user declines to switch, disable the relevant functionality and explain why.
  • Support chain-specific data — If your dApp works on multiple chains, show chain-specific balances, positions, and contract interactions.

Error Handling

Web3 errors are notoriously cryptic. Your job is to translate them into human-readable messages:

Raw ErrorUser-Friendly Message
INSUFFICIENT_FUNDS"You don't have enough ETH to cover gas fees"
ACTION_REJECTED"Transaction cancelled"
UNPREDICTABLE_GAS_LIMIT"This transaction would fail. Check your inputs."
CALL_EXCEPTION"The contract returned an error. [specific reason if available]"
NETWORK_ERROR"Network connection issue. Please try again."

Build a centralized error handling utility that maps common error codes and message fragments to user-friendly strings. You will encounter dozens of error patterns over time, and having them in one place makes your dApp dramatically more usable.

Portfolio Projects to Build

If you want to demonstrate Web3 frontend skills to employers, build these projects and deploy them publicly:

1. Token Dashboard

Build a dashboard that shows a connected wallet's token balances, transaction history, and portfolio value across multiple chains. This demonstrates:

  • Wallet connection with wagmi/RainbowKit
  • Reading on-chain data (ERC20 balances via useReadContract)
  • Multi-chain support
  • Data formatting (token amounts with correct decimals, USD conversion)
  • Responsive design

2. Simple DEX Interface

Build a frontend for a DEX (you can use Uniswap's contracts on a testnet). This demonstrates:

  • Token approval flows (approve + swap pattern)
  • Transaction state management
  • Price impact calculation and display
  • Slippage tolerance settings
  • Gas estimation

3. NFT Minting Page

Build a mint page for an NFT collection (deploy a simple ERC721 contract on a testnet). This demonstrates:

  • Mint function interaction
  • Handling mint limits and sold-out states
  • Real-time supply tracking
  • Wallet balance checks
  • Transaction confirmation with visual feedback

4. Governance Interface

Build a frontend for an on-chain governance system (you can use OpenZeppelin Governor). This demonstrates:

  • Reading complex contract state (proposal data, vote tallies, quorum)
  • Time-based UI (voting periods, execution delays)
  • Vote submission and delegation
  • Historical data display

Deploy all portfolio projects to a public URL (Vercel is free for personal projects) with the source code on GitHub. Include a README that explains the tech stack, design decisions, and known limitations. Hiring managers will look at your code quality, component architecture, and how you handle edge cases.

Salary Expectations

Frontend developers in Web3 earn a premium over their Web2 counterparts, especially those who deeply understand blockchain interactions and can build production-quality dApp interfaces.

LevelBase SalaryTotal Comp (with tokens)
Junior (0-2 years Web3)$90,000 - $140,000$110,000 - $180,000
Mid (2-4 years)$140,000 - $180,000$180,000 - $280,000
Senior (4+ years)$180,000 - $220,000$260,000 - $380,000
Lead / Staff$200,000 - $250,000$320,000 - $450,000

The salary premium over Web2 frontend roles comes from the additional complexity of blockchain integration, the smaller talent pool, and the security-sensitive nature of the work (your frontend directly interacts with contracts that hold real money).

Common Mistakes Web2 Devs Make

Treating Blockchain Data Like API Data

Blockchain data is not like REST API data. Reads are eventually consistent (block confirmations), writes are asynchronous and costly, and there is no built-in pagination or filtering. Use wagmi's caching and TanStack Query for efficient data management rather than naive fetching patterns.

Ignoring Mobile and Wallet Browser Support

A significant percentage of Web3 users access dApps through mobile wallet browsers (MetaMask Mobile, Coinbase Wallet app, Rainbow). These in-app browsers have quirks and limitations. Test your dApp in these environments, not just desktop Chrome with a browser extension.

Over-Fetching On-Chain Data

Every RPC call has a cost (either direct or through rate limits on your provider). Batch reads using multicall, cache aggressively, and use event logs for historical data rather than calling view functions repeatedly.

Not Handling Network Latency

Block times vary by chain: Ethereum is roughly 12 seconds, L2s can be 2 seconds. Your UI must gracefully handle the latency between submitting a transaction and it being confirmed. Show loading states, allow users to continue browsing while transactions confirm, and avoid blocking the entire UI on a pending transaction.

Building Without a Design System

dApps have complex UI states (connected/disconnected, right chain/wrong chain, sufficient balance/insufficient balance, transaction pending/confirmed/failed). Without a systematic approach to UI states, your code quickly becomes a mess of conditional rendering. Invest in a design system early — even if it is just a set of well-defined component variants.

Security matters on the frontend too. Never construct transactions client-side without proper validation. Do not trust client-side estimates for final values. Always show the user exactly what they are signing, and implement transaction simulation (using Tenderly or viem's simulateContract) before submitting critical transactions.

Getting Hired

Where to Look

Web3 frontend roles are listed on gm.careers, protocol career pages, and through the usual Web3 channels (Twitter, Discord, Telegram job groups). Many DeFi protocols, NFT platforms, and wallet companies are specifically looking for frontend engineers with React experience who are willing to learn the Web3 layer.

What Hiring Managers Look For

Based on conversations with dozens of Web3 hiring managers, here is what they prioritize:

  1. Strong React/TypeScript fundamentals — This is the baseline. If your React skills are not solid, Web3-specific knowledge will not compensate.
  2. Understanding of wallet interactions — Can you explain how a wallet connection works? What happens when a user signs a transaction?
  3. Transaction UX awareness — How do you handle pending states? What happens if a transaction fails?
  4. Portfolio projects — Deployed dApps with clean code and good UX matter more than years of experience.
  5. Curiosity about the space — Hiring managers can tell who is genuinely interested in Web3 versus who is just following the salary.

Interview Process

Typical stages for a Web3 frontend role:

  1. Portfolio review — They look at your deployed projects and GitHub
  2. Technical screen — React fundamentals, TypeScript, and basic Web3 concepts
  3. Take-home or live coding — Build a small dApp feature (connect wallet, read contract data, submit a transaction)
  4. System design — How would you architect a complex dApp? Discuss data fetching strategy, state management, error handling
  5. Culture fit — Alignment with the project's values and comfort with remote, async work

The Path Forward

Frontend development in Web3 rewards engineers who are comfortable with ambiguity, who care deeply about user experience, and who can bridge the gap between complex blockchain interactions and intuitive interfaces. The technology is still maturing — which means the engineers who master it now will be the senior engineers and tech leads of the Web3 ecosystem in the years ahead.

Start by building one of the portfolio projects listed above. Use wagmi, viem, and RainbowKit. Deploy it, share it, and iterate based on feedback. Then explore frontend developer roles on gm.careers, review salary benchmarks, and browse open positions to find your next opportunity.

Share:TwitterLinkedIn

Stay Updated

Weekly Web3 jobs and career insights.