Create a Simple Dapp: A Step-by-Step Guide for Beginners

·

Building a decentralized application (dapp) is an exciting entry point into the world of blockchain development. This guide walks you through creating a simple JavaScript dapp and integrating it with MetaMask, one of the most widely used cryptocurrency wallets. You’ll learn how to detect the MetaMask provider, identify the user’s network, and securely access their Ethereum accounts—all using modern web tools like Vite and vanilla JavaScript.

Whether you're new to blockchain or expanding your developer toolkit, this hands-on tutorial delivers foundational knowledge that prepares you for more advanced dapp development.

👉 Get started with blockchain development using trusted tools and resources


Prerequisites

Before diving into the code, ensure your development environment meets the following requirements:

These tools provide a stable foundation for building and testing your dapp locally.


Step 1: Set Up the Project

We’ll use Vite, a fast build tool for modern web projects, to scaffold our dapp.

Run the following command in your terminal:

npm create vite@latest simple-dapp -- --template vanilla

This creates a new project named simple-dapp using the plain JavaScript template. Next, navigate into the project directory:

cd simple-dapp

Install the required dependencies:

npm install

Now you’re ready to build the structure of your dapp.


Step 2: Create the Dapp Structure

Inside your project folder, create a main.js file. This will serve as the main entry point for your JavaScript logic.

Add the following content to main.js:

import "./style.css";

document.querySelector("#app").innerHTML = `
  <button class="enableEthereumButton">Enable Ethereum</button>
  <div class="showAccount"></div>
`;

This code injects a button for connecting to MetaMask and a placeholder to display the connected Ethereum account.

Next, update index.html to include your script:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Simple Dapp</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

Note: We assume main.js is located in a src directory. If not, adjust the path accordingly.


Step 3: Detect MetaMask

To interact with MetaMask, your dapp must first detect whether the wallet is available in the user’s browser.

⚠️ Note: The @metamask/detect-provider package is deprecated and used here only for educational simplicity. For production apps, use EIP-6963 to support wallet interoperability.

Install the detection module:

npm i @metamask/detect-provider

Create a src/detect.js file:

mkdir src && touch src/detect.js

Add this code to detect MetaMask:

import detectEthereumProvider from "@metamask/detect-provider";

async function setup() {
  const provider = await detectEthereumProvider();

  if (provider && provider === window.ethereum) {
    console.log("MetaMask is available!");
    startApp(provider);
  } else {
    console.log("Please install MetaMask!");
  }
}

function startApp(provider) {
  if (provider !== window.ethereum) {
    console.error("Do you have multiple wallets installed?");
  }
}

window.addEventListener("load", setup);

This script checks for MetaMask on page load and initializes your app if detected.

👉 Discover how modern dapps connect securely to wallets like MetaMask


Step 4: Detect the User’s Network

Your dapp should always know which Ethereum network the user is on—whether it’s Mainnet, Goerli, or a local testnet.

Update src/detect.js with network detection logic:

const chainId = await window.ethereum.request({ method: "eth_chainId" });

window.ethereum.on("chainChanged", handleChainChanged);

function handleChainChanged(chainId) {
  // Best practice: reload the page to reset state when network changes
  window.location.reload();
}

This uses the eth_chainId RPC method and listens for the chainChanged event. If the user switches networks in MetaMask, the page reloads to prevent state mismatches.


Step 5: Access User Accounts

To perform actions like sending transactions or reading balances, your dapp needs permission to access the user’s accounts.

Add account access functionality to detect.js:

const ethereumButton = document.querySelector(".enableEthereumButton");
const showAccount = document.querySelector(".showAccount");

ethereumButton.addEventListener("click", () => {
  getAccount();
});

async function getAccount() {
  const accounts = await window.ethereum
    .request({ method: "eth_requestAccounts" })
    .catch((err) => {
      if (err.code === 4001) {
        // User rejected request
        console.log("Please connect to MetaMask.");
      } else {
        console.error(err);
      }
    });

  if (accounts) {
    const account = accounts[0];
    showAccount.innerHTML = account;
  }
}

Important: Only call eth_requestAccounts in response to direct user interaction (like a button click) to avoid spamming prompts.

Update index.html to reflect these elements:

<div id="app">
  <button class="enableEthereumButton">Enable Ethereum</button>
  <div class="showAccount"></div>
</div>
<script type="module" src="/src/detect.js"></script>

Start your development server:

npm run dev

Visit the local URL in your browser, click Enable Ethereum, and approve the connection in MetaMask. Your public address will appear on the page.


Core Keywords for SEO

This guide targets developers searching for practical blockchain integration. Key SEO keywords include:

These terms are naturally integrated throughout the content to align with search intent while maintaining readability.


Frequently Asked Questions

How do I check if MetaMask is installed?

You can detect MetaMask by checking if window.ethereum exists in the browser. Use detectEthereumProvider() for more accurate results, though it's deprecated for production use.

Why should I use EIP-6963 instead of window.ethereum?

EIP-6963 enables wallet interoperability, allowing your dapp to detect and support multiple wallets (like MetaMask, WalletConnect, etc.) without conflicts. It's the recommended standard for live applications.

What is eth_requestAccounts used for?

The eth_requestAccounts RPC method prompts the user to connect their MetaMask accounts to your dapp. It returns an array of Ethereum addresses upon approval.

Can I build a dapp without Node.js?

While possible, using Node.js with tools like Vite simplifies dependency management, bundling, and local development—making it ideal for modern dapp creation.

Why does my dapp need to reload when the network changes?

Reloading ensures your dapp synchronizes with the correct blockchain network. Failing to do so may result in incorrect data or failed transactions.

Is this tutorial suitable for production apps?

This tutorial uses legacy patterns for educational clarity. For production, adopt EIP-6963 and proper state management frameworks like React or Vue.


Next Steps

After mastering this basic setup, consider advancing to a React-based dapp with local state management. Frameworks like React improve scalability and user experience, especially when handling complex blockchain interactions.

You now have a working foundation for building decentralized applications. With tools like MetaMask and modern JavaScript workflows, you're well-equipped to explore deeper aspects of Web3 development.

👉 Explore advanced dapp development techniques and ecosystem tools