Building Your First dApp: A No-Nonsense Guide

The goal of this tutorial is to help you write and deploy your first fully fledged decentralized application on the Ethereum Blockchain without any frills, such as a beautiful and dynamic front end.

The application in question lets you submit and retrieve a number. This may sound pretty simple, but as the old Latin saying goes:

when you are steeped in little things, you shall safely attempt great things

This tutorial assumes that you’re using a computer running Mac OS. If you are not running Mac OS, almost all the packages and tools presented should be available for Windows and Linux environments. Any exceptions will be noted for your convenience.

Part 1: Getting your Tools

There are a couple of tools you’ll need to get your dApp off the ground so let’s go ahead and set them up. If you already have any of the tools already installed, go to the next step of installation instructions until you have everything you need.


brew is a package manager for Mac OS only that will help in the installation of each tool. If you are using a Linux system, you will be installing most components using your distributions package manager. If you are using Windows, the products are stored and retrieved using tar.gz and zip file formats. You can install it by following the commands here in your terminal:

/usr/bin/ruby -e "$(curl -fsSL"


or “node package manager” is a command line tool designed to let you install other command line tools.

With brew installed, getting npm installed is just one command away:

brew install npm

If you have a Windows or Linux machine installation for npm shouldn’t be too difficult either but you won’t be able to use brew.

Make sure you have npm properly installed by running the following commands in your terminal (this applies to all operating system platforms):

node -v
npm -v


Truffle is an Ethereum smart contract development environment. It lets you write test cases for contracts and makes deploying your contracts fast and easy.

It can be installed through npm like so:

npm install -g truffle


Just like its name, http-server is a tool that creates an http server on your computer. It’ll be used later in the tutorial to let you access your dApp from your computer’s directory.

It can be installed through npm like so:

npm install -g http-server


Made by the same people that made Truffle, Ganache acts as a simulated Ethereum blockchain that automatically creates accounts loaded with Ether for development purposes. It also comes with a built-in blockchain explorer so you can really see whats going on when you’re fiddling with your contract.

A glimpse of the Ganache application

Ganache can be installed below:


MetaMask is a browser plug-in that lets you interact with dApps without having to host a full Ethereum node yourself. It also makes testing dApps on different networks from your personal computer incredibly easy.

MetaMask can be installed below:

Setting up your Development Environment

With all the above tools installed you’re finally ready to get your development environment up and running for this dApp.

Your project will need two directories: one to develop, debug, and deploy your smart contract code with Truffle and another to develop your dApp UI. Although the UI for this contract is just a single file (one HTML file with some embedded JavaScript), keeping everything in separate directories ensures things stay organized as the project grows larger. It also makes working with the http-server tool you install previously a lot easier as you’ll see later.

For the sake of simplicity, make two directories with the commands below in your terminal:

mkdir show_num
mkdir show_num_ui

show_num is where we’ll use Truffle for smart contract work while show_num_ui is where we’ll put the HTML file we need.

Go ahead and navigate into your newly made show_num directory like so:

cd show_num

Truffle will set up a localized development environment within the folder like so:

truffle init

If it ran successfully, you should see something like this in your terminal:

Truffle set up your development environment properly!

Congratulations! You’ve set up your smart contract development environment. If you type ls (which lists all the files and directories within your current folder) you should see something like this:

The files and folders in your development environment

contracts is where you’ll actually be storing and writing all the code for the smart contract behind your dApp

migrations holds special configuration files that let you tell Truffle how to deploy your contract

test can hold programs for testing your contracts before deployment, whether it be through Solidity or JavaScript.

truffle.js and truffle-config.js give instructions to Truffle on where to deploy your contract, whether it be a local environment for the purposes of this tutorial or the actual mainnet. However, the files can also do a lot more to customize your environment. For the purposes of this tutorial, we only care about the location for contract deployment.

There’s one last thing we have to do before we consider the development environment complete: tell Truffle where the contract should go when you deploy it.

As mentioned previously truffle.js and truffle-config.js are the places to go to set this up properly. You’ll need to edit truffle.js for Mac; if you’re a Windows user, you’ll need to edit truffle-config.js. Go ahead and fire up your favorite text editor and open the file to edit it. If you do not have one, the option used by most developers is Sublime Text with a Solidity syntax tool. If you need the full directory of where the file is, the pwd command is your friend, it’ll tell you exactly where you are.

I’m partial to the Vim text editor so the following screenshots will all be in Vim but you can still follow along with your favorite text editor.

Your truffle.js file should look like this by default:

Default truffle.js configuration

You’ll want to focus on the part that says module.exports . Go ahead and remove that section and replace it with the following code:

module.exports = {
networks: {
development: {
host: "",
port: 8545,
network_id: "*" // Match any network id

This tells Truffle is that we want to push our contract to Ganache, our Ethereum blockchain simulator. If you’d like to make sure the information is accurate and aligns properly with your Ganache installation, or change any values, you can launch Ganache and go to the Preferences panel to see the host, port, and network ID information for yourself:

Truffle network, port number, and Network ID settings

For our purposes, the Network ID won’t be any problem as Truffle has the wildcard option set and will connect to any Network ID. If your Network ID isn’t the same as the one in the picture, you can safely ignore it. For the example above, I have it set to “8888” which isn’t the default but you can tweak it as you wish.

Part 2: Creating and Deploying your Smart Contract

With the development environment now successfully set up, we can really get into the nitty-gritty of writing the code for our contract.

Go ahead and open your text editor and make a file in the contracts directory called show_num.sol . It should be noted that all smart contracts for Ethereum end with .sol .

You might notice that there is another file already in the contracts called Migrations.sol . DO NOT REMOVE OR CHANGE THIS FILE! Truffle uses it to convert your smart contract into a more machine ready format that can be run by Web3 or Ganache.

Copy and paste the code below:

As promised, the dApp in question lets you submit and retrieve a number.

All Ethereum contracts start with pragma followed by the version of the compiler used. This prevents the file from failed to be compiled by future compilers should future compilers introduce incompatible changes.

All contracts start with the contract keyword followed by the name of the contract and enclosing curly brackets. Note how the name of the contract must match the name of file. This is a bit of a technicality with how Truffle works, but a good habit to practice nonetheless.

uint num declares an unsigned integer within the contract. function set_num(uint x) public declares a function that is publicly accessible and takes a uint as its argument. function reveal_num () public view returns (uint) declares a function that is publicly accessible and which returns a uint. The view keyword states that the function does not change the state of the contract ( it doesn’t modify any data ). This is opposed to our set_num function which does.

After saving your show_num.sol file with the code above we can finally get around to compiling and deploying the smart contract code!

Making sure that you’re still in the environment we set up with Truffle, run the command below:

truffle compile

Your terminal should say something like this:

Successful compilation of your contract

With your contract all compiled, we have to tell Truffle how to properly migrate your contract to Ganache. truffle.js already tells Truffle the where but what Truffle needs is the how. That’s where the migrations directory comes in handy.

You can go up a directory (out of contracts) like so:

cd ..

typing ls just to confirm you’re out of the contracts directory your files should now look like this:

Your development directory (again)

One of the things you should see is a new directory called build. This holds the compiled contract code as well as other necessary code for bridging our contract to our UI, making our fully fledged dApp.

For now go ahead and enter your migrations directory like so:

cd migrations

If you do an ls, you’ll notice that there’s one file already present there, 1_initial_migration.js . This goes hand-in-hand with the previous Migrations.sol file you saw in the contracts directory. Make sure you, like Migrations.sol DO NOT tamper or remove the file as this can ruin the migration process

Make a new file called 2_show_num_deploy.js and make its contents the following:

Note the "./show_num.sol" which tells Truffle to get compiled contract code for show_num . The following lines just tell Truffle to migrate the contract but just Truffle also offers a number of other ways to customize your migration to more complex needs which we won’t be exploring today for the sake of simplicity.

Go ahead and save the file. Now, launch your installation of Ganache, letting it run in the background. Run the following command:

truffle migrate

If all goes well you should see something in your terminal like the following:

Successful migration!

If you open up your Ganache instance running the background, you can tell that your contracts have been deployed because a quick glance at your accounts show that you’ve spent some Ethereum for deployment….

Note the 99.95 versus the default 100.00 ETH!

…and that you have 4 new generated blocks, which Ganache created automatically from its automining feature which only mines when it detects any intended interaction (calling/deploying a contract)

Note the new blocks!

If you want to be doubly sure that your contract has been deployed, you can click the yellow buttons to the right for each block which give you more details about each block.

Some of the blocks (1 and 3 in our case) will be labelled with a “contract creation” indicator

A contract is born

If you look at the TX HASH field in Ganache and the output from truffle migrate you’ll notice that they match up as well:

Hooray! Our smart contract now lives on our simulated Ethereum blockchain. With that out of the way, it’s time to concern ourselves with the front-end for our dApp

Part 3: Creating your Front-End

A dApp consists of smart contracts and a UI. We’ve already taken care of the smart contract part now it’s just a matter of putting a UI on top.

In order for our UI to communicate with your contract, there has to be some kind of bridge to do so. Luckily, web3 is a JavaScript API that lets you communicate with an Ethereum node, giving easy access to the Ethereum network and hence, your smart contract. Usually, you’d have to import the web3 JavaScript library into your project. That’s where the MetaMask browser plugin is so useful. MetaMask, as mentioned before, acts like a node so you don’t have to go through running your own Ethereum node just to access a dApp. MetaMask will automatically inject web3 into our page, allowing your dApp to work with any other browser that also has MetaMask installed.

However, web3 alone isn’t enough by itself. You’ll need to tell web3 where and how to talk to your contract. There are two critical pieces of information that you need to find and talk to your contract through web3 : The address of your contract and the ABI or Application Binary Interface, which encodes/decodes information to and from the Ethereum Virtual Machine.

Truffle makes it very easy to find this information. If you go to your show_num directory and go into your build directory, you’ll see a contracts directory. Go ahead and go into that directory. You should see two files, Migrations.json and show_num.json . The names correspond to each of the migrated contracts. Opening up show_num.json you should see something like this:

Part of the ABI

Right off the bat you can see an "abi" section followed by some stuff enclosed with a pair of square brackets. If you scroll or search “address” in your text editor, you’ll find the address of your contract

Address of Contract

Where this information goes is shown in the code for our UI file, show_num.html, below:

As promised, our UI is very bare bones, with a simple entry field to get a number, a button to submit it, and another button to retrieve the number.

The line web3.eth.defaultAccounts = web3.eth.accounts[0] just takes the first account that MetaMask provides as the one to use for interacting with the smart contract.

You can go ahead and make a show_num.html file and then save it in your show_num_ui folder which we made in the very beginning of the tutorial.

Particular attention should be paid to these lines:

const contract_abi = abi_from_Truffle_here....
const contract_address = "0xb421a6223b29b6791ad231bb1788ad9a38115834"

To get the contract_abi into a nice, singular, string, you can use a “minifier” like the one below:

Just copy and paste the ABI from the show_num.json file and copy the resulting output, replacing the ABI after contract_abi if needed.

To create a contract instance that you can then call functions from, you do it like so:

var contract_inst = web3.eth.contract(contract_abi).at(contract_address);

Now you can call the contract via contract_inst

Something that should be noted, especially for people (like me) who are unfamiliar with JavaScript, is that web3 forces you to use callbacks, which are functions that are executed after another function has executed. The reason for this is that JavaScript is an event-driven language, meaning that JavaScript will not wait for a function to provide a response, instead it will execute other functions while awaiting a response.

Hence, a call to the reveal_num function looks like this using web3:

contract_inst.reveal_num((err, res) => 
document.getElementById("num_out").innerText = res;

Where the call will either return some value for an error err or result res and each must be subsequently dealt with.

Testing and Playing with your dApp

Now that our UI and our smart contract are in place, it’s time to give the whole thing a spin.

First, make sure you’ve set up your MetaMask account and wallet. Clicking on MetaMask, following the provided instructions. Ensure that you properly store your password as well as the wallet passphrase. Losing the passphrase means a total inability to recover funds, should you use MetaMask to store any actual Ether. Luckily, we’ll just be using the Ether that Ganache provides us with.

After setting up MetaMask, you’ll want to connect to Ganache. MetaMask provides the option to connect to multiple testnets, “Localhost 8545” being the default Ganache port. Go ahead and click on that.

Localhost sweet Localhost

Now we’ll want to fund your account with some Ether so you can interact with your dApp. If you go back to the show_num directory where you first created and migrated your contract, run the following command:

truffle console

This lets you interact with Ganache via the command line.

To transfer Ether from Ganache to your MetaMask wallet, execute this command:

web3.eth.sendTransaction({from:web3.eth.coinbase, to: your_metamask_wallet, value: web3.toWei(10, "ether") })

Where your_metamask_wallet should be the address of your MetaMask account as a string (encapsulated in '' or ""). in web3.toWei() you can change 10 to any number of Ether and the "ether" argument denotes the denomination of Ether, so you could send smaller amounts if you’d like.

If the transaction happens properly, you’ll see the transaction hash in the terminal. You can exit the Truffle console by hitting Ctrl+C twice.

Your wallet balance should appear like this in MetaMask:

Wallet after transferring funds

And to be doubly certain, Ganache will also happily indicate that a value transfer occurred in its latest block:

Value transfer confirmed

With some Ether in your pocket, its time to launch that UI! Unfortunately, you can’t just double-click on the HTML file and start clicking away. You’ll have to access it from a server.

Now http-server comes to the rescue. Navigate to the show_num_ui directory, where you saved the show_num.html file and and run the following command:


You’ll see a prompt pop up asking if you want to grant “node” access. Go ahead and grant it. Your terminal show look like this:

Server is up and running

http-server also lets you customize which port you’d like to access it from and a bunch of other neat settings, all of which are ignored for the sake of simplicity.

If you type localhost:8080 into your browser, you’ll be greeted by something like the page below:

Click on show_num.html and you’ll be greeted by the (rather ugly but very usable) UI of our dApp!

Now for the real test. Go ahead and type a number into the field, and then hit the Send Number to Contract button. MetaMask will immediately ask your permission in using Ether to cover the action:

MetaMask prompt

Go ahead and hit Confirm. MetaMask will notify you that a transaction occurred and you can see it in Ganache as well as a new block labelled “Contract Call” will appear:

Contract Call

If you hit the Show Number button, you should see the number you assigned come appear:

Congratulations! You’ve built your first dApp!

What Next?

Now that you’ve learned the basic workflow for developing dApps, you’re free to play with JavaScript frameworks like React and Angular to make your dApp look a lot better. Solidity isn’t just restricted to setting and getting data. You can launch your own tokens and build more useful dApps.

I intentionally kept details related to Truffle and the Solidity programming language sparse but I highly encourage those still interested to consult the documentation below:

If you’re looking for inspiration, you can consult this neat website:

I hope you’ve enjoyed this tutorial. If there are any errors in explanation or code, please feel free state them in the comments where they will be fixed promptly.

Best of luck with developing your own dApps and keep up the good work!