frontend-ux
Installation
SKILL.md
frontend-ux
Production UX patterns for dApp frontends. Covers the full user journey from wallet connection through transaction confirmation, with error handling, gas estimation, approval flows, mobile support, and a production QA checklist. Built on wagmi v2, viem, and RainbowKit.
What You Probably Got Wrong
Most dApp frontends ship with broken UX because developers treat wallet connection as a button click and transactions as a loading spinner. Both are state machines with multiple failure modes that users encounter constantly.
- Wallet connection is a four-state machine, not a button -- The states are
disconnected,connecting,connected, andwrong-network. Showing a single "Connect Wallet" button that flips to "Connected" misses theconnectingspinner (important on mobile where WalletConnect takes seconds), thewrong-networkprompt (users will be on mainnet when your dApp is on Base), and auto-reconnection on page reload (flash of disconnected state). - Transactions have four states, not a loading spinner -- The states are
idle,awaiting-signature(wallet popup open),pending(tx submitted, waiting for block inclusion), andconfirmed-or-failed. Each state needs distinct UI. Users sitting at "Loading..." don't know if they need to open their wallet, wait for the chain, or if something failed. - User rejection (code 4001) is NOT an error -- When a user clicks "Reject" in their wallet, most dApps show a red error toast. This is wrong. The user intentionally cancelled. Silently reset back to the idle state. Reserve error toasts for actual failures.
- Users don't know what gas is -- Showing "Gas: 21000 gwei" means nothing to 99% of users. Convert gas cost to USD using a price feed. Show "Network fee: ~$0.42" instead. If you must show technical details, put them behind an expandable "Details" section.
- Mobile dApp UX is fundamentally different -- On desktop, browser wallets inject providers. On mobile, the user's wallet IS the browser (MetaMask Mobile, Coinbase Wallet app). Connection happens via deep links and WalletConnect v2. If you haven't tested your dApp inside MetaMask Mobile's in-app browser, your mobile UX is broken.
- Infinite approvals are a security risk users don't understand -- Defaulting to
type(uint256).maxapproval is convenient but means a compromised spender contract can drain all tokens forever. Offer exact-amount approval as the default with infinite as an opt-in, or use Permit2 for single-transaction approve-and-transfer. - Block explorer links should open in a new tab with the correct chain -- Hardcoding
etherscan.iobreaks on L2s. Use the chain's configuredblockExplorersfrom wagmi to construct the correct URL.