A Web3 dApp is a web or mobile front-end that lets users act on smart contracts with their own wallets. Building one means writing and auditing the contracts, but also wiring up wallet connection, RPC access, indexing, storage and a user experience that survives gas fees, failed transactions and chain switches.
This guide walks through each layer with the decisions you will face. It focuses on the Web3-specific stack and user experience; for a broader look at dApp categories and choosing a team, see the companion guide to dApp development.
The stack at a glance
| Layer | Role | Common choices (EVM chains) |
|---|---|---|
| Smart contracts | Hold assets, enforce rules, emit events | Solidity with Foundry or Hardhat; OpenZeppelin libraries |
| Chain | Where contracts run and state lives | Ethereum mainnet, rollups (Arbitrum, Optimism/OP Stack chains, Base, ZKsync Era), or alt-L1s |
| Wallet connection | Let users connect and sign | EIP-1193 providers, EIP-6963 wallet discovery, WalletConnect, embedded wallets |
| Client libraries | Read state, build and send transactions | viem, ethers.js, wagmi (React) |
| RPC access | Read the chain and broadcast transactions | Managed node providers, self-hosted nodes, or a mix with failover |
| Indexing | Fast queries over historical events | Subgraphs, custom indexers into Postgres, event-streaming services |
| Storage | Metadata, media, documents | IPFS with pinning, Arweave, or conventional object storage |
| Backend (optional) | Notifications, search, off-chain logic, relayers | Ordinary server stack; keep it non-custodial where possible |
On Solana the shape is similar but the tooling differs: programs written in Rust (often with the Anchor framework), accounts instead of contract storage, and wallet adapters instead of EIP-1193. Pick the chain first, because it decides most of the rest.
Smart contracts: small, standard, tested
Contracts are the part you cannot easily patch, so the goal is to keep them minimal. Use audited standards wherever they exist: ERC-20 for fungible tokens, ERC-721 or ERC-1155 for NFTs, ERC-4626 for yield vaults, EIP-2981 for royalty information. Put anything that does not need trustless enforcement (profiles, search, recommendations) off-chain.
- Testing: unit tests, fuzz tests and invariant tests (for example, "total deposits always equal the sum of balances") in Foundry or Hardhat.
- Upgradeability: proxies let you fix bugs but also let an admin change rules. If you use them, put upgrades behind a multisig and a timelock, and tell users.
- Admin keys: every privileged function is an attack surface. Document them and minimize them.
- Audit: anything holding meaningful value needs an independent review before mainnet. The smart contract audit guide explains scope and what reports should contain.
Deeper coverage of contract engineering is in the guide to smart contract development.
Wallet connection and signing UX
This is where most dApps lose users. Good patterns in 2026:
- Multi-wallet support through EIP-6963 discovery (so multiple browser extensions do not fight) plus WalletConnect for mobile wallets.
- Sign-In with Ethereum (EIP-4361) for sessions, so users sign a readable message rather than an opaque blob.
- Typed data signing (EIP-712) for off-chain orders and permits, so wallets can show what the user is approving.
- Embedded and smart-account wallets for newcomers: email or passkey onboarding, with ERC-4337 smart accounts or EIP-7702 (live on Ethereum since the Pectra upgrade in 2025) enabling batched actions and sponsored gas.
- Bounded approvals. Avoid asking for unlimited token allowances; request what the action needs.
For how wallets themselves are built, see the Web3 wallet development guide.
Transaction lifecycle
Users need to see every state: awaiting signature, submitted, pending, confirmed, failed, or replaced. Simulate transactions before asking for a signature to catch reverts early, show the estimated fee in local currency, and handle dropped or sped-up transactions. On rollups, explain the difference between a fast sequencer confirmation and final settlement where it matters, such as bridging.
Reading data: RPC and indexing
Calling contracts directly over RPC is fine for current balances. It is slow and expensive for history ("all trades by this user") or aggregates ("volume this week"). That is what indexers are for: they listen to contract events and write them into a queryable database.
- Emit rich events from your contracts; your indexer can only see what you emit.
- Handle chain reorganizations: indexers must roll back data from blocks that were replaced.
- Use at least two RPC providers with failover. A single provider outage should not take your dApp down.
- Rate-limit and cache reads in your own backend rather than exposing an RPC key in the browser.
Storage and front-end hosting
Store NFT metadata and media on content-addressed storage (IPFS with reliable pinning, or Arweave for permanent storage) and reference it by content hash, so it cannot silently change. For the front-end itself, many teams host conventionally for speed and also publish to IPFS so users have a fallback. Front-end hijacking via DNS or hosting accounts has drained users in the past, so lock down domain registrars, use hardware keys for deployment accounts, and consider a content security policy.
Choosing a chain
Most consumer dApps launch on a layer-2 rollup because fees are low; Ethereum's Dencun upgrade in 2024 made rollup data far cheaper. Mainnet suits high-value, low-frequency actions. Alt-L1s like Solana suit high-throughput consumer apps with their own ecosystem. Factors that matter more than raw speed: where your users and liquidity already are, wallet support, available oracles and bridges, and the maturity of developer tooling. If you need several chains, plan for it from day one; the guide on scaling with interoperability and layer 2 covers the trade-offs.
The build process
- Specify on-chain vs. off-chain. Write down which rules must be trustless and which can live on a server. Shrink the on-chain part.
- Design contracts and events, including admin roles, upgrade policy and failure modes.
- Prototype on a testnet with a minimal front-end to validate the flow with real wallets.
- Build the indexer and backend in parallel with the contracts so the UI has real data to show.
- Harden: fuzz and invariant tests, internal review, then an external audit. Freeze contract code before the audit.
- Beta with capped value: deposit limits or allowlists on mainnet while monitoring.
- Launch with monitoring and an incident plan: on-chain alerts, a pause mechanism if appropriate, and a communication plan.
Failure modes worth designing against
- Oracle manipulation. Reading a price from a single DEX pool in the same transaction lets an attacker with a flash loan move the price and exploit you. Use robust oracle feeds or time-weighted prices, and bound how far a price can move.
- Reentrancy and unchecked external calls. Follow checks-effects-interactions, use reentrancy guards where state changes follow external calls, and be wary of token callbacks such as those in ERC-777 and ERC-1155 receivers.
- Signature replay. Off-chain signatures need nonces, expiry times and a domain separator that includes the chain ID, or they can be reused on another chain or contract.
- Stale front-end assumptions. The UI shows one price; the transaction executes at another. Enforce slippage limits and deadlines in the contract call, not just in the interface.
- Infrastructure single points. One RPC provider, one indexer, one hosting account. Each should have a fallback or at least a tested recovery plan.
Timeline and cost drivers
Reasoned ranges, assuming an experienced team and excluding token or marketing work:
| Scope | Team | Rough duration |
|---|---|---|
| Simple dApp on standard contracts (NFT mint, token claim, voting) | 1 contract dev, 1 front-end dev | 4–8 weeks plus audit |
| Marketplace or staking dApp with indexer and admin tools | 2–3 devs, designer, QA | 3–5 months plus audit |
| Novel DeFi protocol | Senior protocol engineers, front-end, security lead | 6+ months, with multiple audits |
Audit cost and lead time scale with contract complexity and lines of code, and good auditors are often booked weeks ahead. Ongoing costs include RPC and indexing services, hosting, monitoring, and gas for any transactions you sponsor.
Questions to ask a team
- Which parts of the design must be on-chain, and why?
- Who holds admin keys and upgrade rights after launch?
- Show invariant tests from a previous project.
- How does the front-end handle reverts, reorgs and RPC failures?
- Which audit firm, what scope, and how are findings tracked to resolution?
Frequently asked questions
What is the difference between a dApp and a regular web app?
A dApp's core state and rules live in smart contracts that users interact with through their own wallets. A regular web app keeps state in the operator's database and authenticates users through accounts the operator controls.
Does a dApp need a backend server?
Not strictly, but most production dApps use one for indexing, search, notifications and caching. Keep it non-custodial so users' assets do not depend on it.
Which language should smart contracts be written in?
Solidity is the default on Ethereum and EVM chains, with Vyper as an alternative. Solana programs are usually written in Rust. Choose the chain first; the language follows.
How do we let users try the dApp without buying crypto first?
Use embedded wallets with email or passkey sign-up and sponsor gas through smart accounts (ERC-4337 or EIP-7702 delegation) for the first actions. Budget for the sponsored gas and add abuse limits.
Is an audit enough to make a dApp safe?
No. Audits reduce risk but do not eliminate it. Combine them with thorough testing, minimal admin powers, value caps at launch, monitoring and a bug bounty.
Can a dApp be updated after launch?
Front-ends and backends, easily. Contracts only if you deployed them behind a proxy or designed a migration path, and either option needs transparent governance so users know who can change what.