In today’s session, we’ll build a foundational decentralized application (DApp) using React. One of the most powerful aspects of blockchain development is that many applications only require frontend expertise—because the blockchain itself can act as the backend. With built-in capabilities for reading and writing data, blockchain eliminates the need for traditional server-side infrastructure.
This shift opens the door for frontend developers to dive directly into Web3, leveraging familiar tools while interacting with decentralized networks. Let’s explore how to create a functional DApp step by step.
Understanding Blockchain Node Services
To interact with a blockchain, your application must communicate with a blockchain node—a server that maintains a copy of the ledger and validates transactions. There are two primary operations:
- Read: Fetch data like account balances or transaction history.
- Write: Send transactions, such as transferring tokens or interacting with smart contracts.
These interactions happen via the JSON-RPC protocol, which is why nodes are often referred to as RPC nodes.
Blockchain, at its core, is a distributed ledger that records asset ownership across countless computers (nodes). Cryptographic mechanisms ensure this ledger is tamper-proof and publicly verifiable.
Running your own node means downloading the entire blockchain history—over 500GB for Bitcoin and more than 1TB for Ethereum. This demands significant storage, bandwidth, and maintenance. For most developers, it’s far more practical to use third-party node service providers.
👉 Discover how easy it is to connect to blockchain networks with powerful developer tools.
Popular services like Alchemy, Infura, and QuickNode offer reliable, scalable access to Ethereum and other chains. In this tutorial, we’ll use Alchemy, one of the most trusted platforms for Web3 development.
Today’s Goal: Build a Basic DApp Interface
Have you ever used Uniswap on a testnet? When you open the app, you’re prompted to connect your wallet. Once connected, the interface displays:
- Your wallet address
- The current network (e.g., Ethereum Mainnet or Sepolia)
- Your account balance
- A network switcher to change chains
Our goal today is to implement all these core features in a minimal DApp. By the end, you’ll have a working prototype that demonstrates essential Web3 frontend patterns.
Setup: Create Your Alchemy App
Before coding begins, head to the Alchemy Dashboard and create a new app. Since we're building on a testnet:
- Select Ethereum as the chain
- Choose Sepolia as the network
- Name your app anything you like
After creation, click “View Keys” to reveal your API Key. Save this—you’ll need it shortly.
Next, initialize a new frontend project. We’ll use Next.js with pnpm:
pnpm create next-app dapp-tutorialYou can choose your preferred package manager and styling setup. Navigate into the project directory to begin installing dependencies.
Introducing WAGMI: Web3 Made Simple
We’ll use wagmi, a powerful React Hooks library for Web3 development. It abstracts away the complexity of lower-level libraries like ethers.js or viem, letting you focus on building UIs instead of managing JSON-RPC calls.
Install wagmi and viem:
pnpm i wagmi viemFun fact: “WAGMI” stands for We All Gonna Make It—a popular phrase in early NFT communities, now turned into a Web3 cultural meme.
At the time of writing, we’re using:
Note: wagmi updates frequently, so interface differences may appear in future versions.
Connect Wallet & Display Balance
Start by wrapping your app with WagmiConfig and setting up basic hooks for connection management.
"use client";
import {
WagmiConfig,
createConfig,
useAccount,
useConnect,
useDisconnect,
} from "wagmi";
import { createPublicClient, http } from "viem";
import { mainnet } from "wagmi/chains";
import { InjectedConnector } from "wagmi/connectors/injected";
const config = createConfig({
autoConnect: true,
publicClient: createPublicClient({
chain: mainnet,
transport: http(),
}),
});
function Profile() {
const { address, isConnected } = useAccount();
const { connect } = useConnect({
connector: new InjectedConnector(),
});
const { disconnect } = useDisconnect();
if (isConnected)
return (
<div>
Connected to {address}
<button onClick={() => disconnect()}>Disconnect</button>
</div>
);
return <button onClick={() => connect()}>Connect Wallet</button>;
}
export default function App() {
return (
<WagmiConfig config={config}>
<Profile />
</WagmiConfig>
);
}Run pnpm run dev, open your browser, and click “Connect Wallet.” MetaMask (or another injected wallet) will prompt you to approve the connection.
Once connected, your address appears with a disconnect button—mission accomplished!
Now let’s display the user’s ETH balance using useBalance:
import { useBalance } from "wagmi";
function Profile() {
const { address, isConnected } = useAccount();
const { connect } = useConnect({ connector: new InjectedConnector() });
const { disconnect } = useDisconnect();
const { data: balance } = useBalance({ address });
if (isConnected)
return (
<div>
Connected to {address}
<div>Balance: {balance?.formatted} ETH</div>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
);
return <button onClick={() => connect()}>Connect Wallet</button>;
}You might notice the balance shows zero. That’s because we’re connected to mainnet, but our test funds are on Sepolia.
Display and Switch Networks
Let’s fix that by configuring support for multiple chains—specifically Ethereum Mainnet and Sepolia.
Update your config to use Alchemy as the provider:
import { alchemyProvider } from "wagmi/providers/alchemy";
import { publicProvider } from "wagmi/providers/public";
import { configureChains, createConfig } from "wagmi";
import { mainnet, sepolia } from "wagmi/chains";
const { chains, publicClient } = configureChains(
[mainnet, sepolia],
[
alchemyProvider({ apiKey: process.env.NEXT_PUBLIC_ALCHEMY_KEY }),
publicProvider(),
]
);
const config = createConfig({
autoConnect: true,
publicClient,
});Create a .env.local file in your project root and add your Alchemy API key:
NEXT_PUBLIC_ALCHEMY_KEY=your_api_key_hereNow use useNetwork and useSwitchNetwork to display the current chain and enable switching:
import { useNetwork, useSwitchNetwork } from "wagmi";
function Profile() {
const { address, isConnected } = useAccount();
const { connect } = useConnect({ connector: new InjectedConnector() });
const { disconnect } = useDisconnect();
const { chain } = useNetwork();
const { switchNetwork, chains: availableChains } = useSwitchNetwork();
const { data: balance } = useBalance({ address });
if (isConnected)
return (
<div>
Connected to {address}
<div>Balance: {balance?.formatted} ETH</div>
<div>Connected to {chain?.name}</div>
<div>
{availableChains.map((x) => (
<button
key={x.id}
onClick={() => switchNetwork?.(x.id)}
disabled={x.id === chain?.id}
>
{x.name} {x.id === chain?.id && "(current)"}
</button>
))}
</div>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
);
return <button onClick={() => connect()}>Connect Wallet</button>;
}Now users can switch between networks directly from your DApp!
👉 Supercharge your DApp development with seamless blockchain integration.
FAQ
Q: Why should I use Alchemy instead of running my own node?
A: Running a full node requires massive storage and bandwidth. Alchemy provides high-availability RPC endpoints without infrastructure overhead—ideal for developers focused on building.
Q: Can I use this setup with other blockchains?
A: Yes! wagmi supports multiple EVM-compatible chains like Polygon, Optimism, and Arbitrum. Just import the relevant chain object and add it to configureChains.
Q: What happens if a user rejects a network switch?
A: The useSwitchNetwork hook returns an error field you can monitor to detect rejections or failed switches and display appropriate feedback.
Q: Is WAGMI production-ready?
A: Absolutely. wagmi v1 is stable and widely used in production DApps across DeFi, NFTs, and Web3 platforms.
Q: How do I handle wallet disconnection gracefully?
A: The useAccount hook automatically updates isConnected when disconnected. Always conditionally render UI based on this state.
Q: Can I customize the wallet connection modal?
A: Yes—while InjectedConnector works for MetaMask, you can integrate wagmi/connectors like WalletConnect for broader wallet support.
Final Thoughts
Today, we built a functional DApp with core Web3 features:
- Wallet connection
- Balance display
- Network detection and switching
- Secure API integration via Alchemy
This foundation sets the stage for more advanced functionality—token swaps, NFT minting, and smart contract interactions—all within a clean, responsive frontend.
With tools like wagmi and services like Alchemy streamlining development, there's never been a better time to enter Web3.
👉 Start building your next Web3 project with confidence using robust developer resources.