You’ve deployed your first smart contract. Now let’s connect it to a frontend and turn it into a real decentralized app (DApp) you can share with anyone — all on Arbitrum.
🧠 First, What Is a DApp?
A DApp = Decentralized App.
It’s just like any web app you use daily — but with one big difference:
Instead of talking to a server, it talks to a smart contract on the blockchain.
*Example DApps:
*
- Uniswap (swaps tokens)
- Aave (borrows/lends crypto)
- Lens Protocol (decentralized social media)
- DApps = Frontend (HTML/JS) + Smart Contract (Solidity)
🧱 Architecture Breakdown
🧑💻 User clicks button
⬇️
🌐 Frontend (React/Next.js/etc.)
⬇️
🔌 Web3 Provider (ethers.js / wagmi / viem)
⬇️
📜 Smart Contract (Solidity on Arbitrum)
⬇️
📦 Blockchain stores + returns data
⚙️ Let’s Build a Basic DApp UI (React + ethers.js)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; contract MessagePortal { string private message; // Event to emit when message is updated event MessageUpdated(address indexed sender, string newMessage); // Constructor to set initial message constructor(string memory _initialMessage) { message = _initialMessage; } // Read current message function getMessage() public view returns (string memory) { return message; } // Update the message function updateMessage(string memory _newMessage) public { message = _newMessage; emit MessageUpdated(msg.sender, _newMessage); } } Now we’ll build a frontend to read and update that message.
🧰 Tools You’ll Use
- Vite + React for the frontend
- ethers.js to talk to the blockchain
- MetaMask for signing
- Arbitrum Testnet
🚧 Step-by-Step: Build Your DApp Frontend
1. Create your React app
npm create vite@latest hello-dapp --template react cd hello-dapp npm install npm install ethers 2. Add the basic UI
// src/App.jsx import { useState } from 'react'; import { ethers } from 'ethers'; const CONTRACT_ADDRESS = 'YOUR_DEPLOYED_CONTRACT_ADDRESS'; const ABI = [ 'function message() view returns (string)', 'function updateMessage(string memory _newMessage) public', ]; function App() { const [msg, setMsg] = useState(''); const [newMsg, setNewMsg] = useState(''); const loadMessage = async () => { const provider = new ethers.providers.Web3Provider(window.ethereum); const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider); const current = await contract.message(); setMsg(current); }; const updateMessage = async () => { const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer); const tx = await contract.updateMessage(newMsg); await tx.wait(); loadMessage(); }; return ( <div> <h1>Arbitrum DApp</h1> <p>Current Message: {msg}</p> <input onChange={(e) => setNewMsg(e.target.value)} placeholder="New message" /> <button onClick={updateMessage}>Update</button> <button onClick={loadMessage}>Refresh</button> </div> ); } export default App; 3. Connect MetaMask to Arbitrum Goerli
- Add Arbitrum testnet if needed: Chainlist
- Grab test ETH from the faucet.
4. Run your app
npm run dev Now, your DApp:
- Reads the message from the blockchain.
- Sends a transaction to update it.
- Shows the new message on-chain.
Magic. 🔥
🛠️ What Just Happened?
- ethers.js talks to your contract.
- Web3Provider connects to MetaMask.
- signer lets users approve a blockchain transaction.
- You built a Web3 interface — fully functional on Arbitrum testnet.
🧠 Pro Tips
- Use viem or wagmi for advanced state handling.
- Add loading states for transactions.
- Show the transaction hash & link to Arbiscan.
🧪 Next Steps
Now that your frontend talks to your smart contract:
- Add token payments.
- Use a real database for metadata (like IPFS).
- Build real-world apps (chat, voting, DAOs, NFT mints).
📌 TL;DR
- DApps = frontend + smart contract.
- You built a full Web3 app using ethers.js + Arbitrum.
- Next up: storing & using blockchain data better.
Top comments (0)