Building a Full Stack NFT minting Dapp using Hardhat, ethers.js, Next.js, and TailwindCSS
By: Abhinav Pathak
Tags: Web3, Smart Contracts, Programming, Blockchain, Nft

Prerequisites

To be successful in this guide, you must have the following:

Node.js installed on your machine

Metamask wallet extension installed as a browser extension

Resources

Solidity docs

Solidity by example: An introduction to Solidity with simple examples

Buildspace: A startup that helps people learn to build crypto-related projects.

About the project

In this post, we will build a full-stack NFT minting dapp using Solidity, Hardhat, ethers.js, Next.js, and TailwindCSS.

To view the final source code for this project, visit this repo

To view the deployed site visit this website

Project setup

To get started we need to create a hardhat project. To do so, open your terminal. Create or change into a new empty directory and run the following command:

npm install ethers hardhat @nomiclabs/hardhat-waffle \

ethereum-waffle chai @nomiclabs/hardhat-ethers \

@openzeppelin/contracts dotenv

This will install the dependencies for setting up a hardhat project and some other dependencies for the project.

Next, initialize a new Hardhat development environment from the root of your project. To do so, run the following command in your terminal:

npx hardhat

The output will be similar to what is shown below. Select Create a basic sample project to create a new hardhat project in your directory.

What do you want to do? …

Create a basic sample project

Create an advanced sample project

. . .

Now you should see the following files and folders created for you in your root directory:

hardhat.config.js — The entirety of your Hardhat setup (i.e. your config, plugins, and custom tasks) is contained in this file.

scripts — A folder containing a script named sample-script.js that will deploy your smart contract when executed.

test — A folder containing an example testing script.

contracts — A folder holding an example Solidity smart contract.

Now, we need to create a new Next.js project for the frontend of the dapp. To do so, run the following command in your terminal:

npx create-next-app -e with-tailwindcss client

This will create a new Next project using tailwindcss for styling in a folder ‘client’.

After this install dependencies for the frontend inside the client folder. To do this run the following command in your terminal:

cd client npm install axios ethers react-loader-spinner

Creating an Ethereum API key using Alchemy

Alchemy is a blockchain developer platform focused on making blockchain development easy. They’ve built a suite of developer tools, enhanced APIs, and superior node infrastructure to make building and running blockchain applications seamless.

To create an API key follow the video below. Things to note:

Select the network as rinkeby.

Copy the HTTP key after the creation of the app on alchemy.

Next, create a .env file to store your Alchemy key and your Account Private Key

ALCHEMY_RINKEBY_URL = "ALCHEMY_HTTP_API_KEY"

ACCOUNT_KEY = "YOUR_ACCOUNT_PRIVATE_KEY

Important: Do not push the .env file to GitHub as it contains your private data.

Updating hardhat.config.js

After this, update the configuration at hardhat.config.js with the following:

require('@nomiclabs/hardhat-waffle')

require('dotenv').config() module.exports = {

solidity: '0.8.3',

networks: {

rinkeby: {

url: process.env.ALCHEMY_RINKEBY_URL,

accounts: [process.env.ACCOUNT_KEY],

},

},

}

Creating Smart Contract logic

Next, we’ll create our smart contracts! We’ll create an NFT contract for the creation of NFT assets. Create a new file in the contracts directory named EternalNFT.sol . Here, add the following code:

In this contract, we are inheriting from the ERC721ERC721URIStorage.sol and Counters.sol implemented by OpenZeppelin

For the Base64 library that is inherited by the contract, create a libraries folder inside the contracts folder. Inside the libraries, folder create a Base64.sol file add the following code:

Testing the Smart Contracts

Now the smart contract code and environment are complete and we can try testing it out.

To do so, we can create a local test to run through much of the functionality, like checking for name, symbol, and address of token, minting a token, etc.

To create the test, open test/sample-test.js and update it with the following code:

To run the test, run the following command from your terminal at the root of your project:

npx hardhat test

Deploying the contracts to the Rinkeby Network

When we created the project, Hardhat created an example deployment script at scripts/sample-script.js .

To make the purpose of this script more clear, delete scripts/sample-script.js and create scripts/deploy.js .

To deploy the contracts add the following code inside depoly.js :

const main = async () => {

const nftContractFactory = await ethers.getContractFactory('EternalNFT')

const nftContract = await nftContractFactory.deploy()

await nftContract.deployed()

console.log('Contract deployed to:', nftContract.address)

} const runMain = async () => {

try {

await main()

process.exit(0)

} catch (error) {

console.log(error)

process.exit(1)

}

} runMain()

To deploy the contract to the rinkeby network run the following command in your terminal:

npx hardhat run scripts/deploy.js --network rinkeby

This will deploy the contract to the rinkeby network and output the address at which the contract is deployed in the terminal.

Building the frontend

Now that the smart contract is working and ready to go, we can start building out the UI.

First, we need to connect the frontend to the smart contract, so it can interact with the data from the blockchain using the functions in the smart contracts.

For this we need to do the following:

Create a utils folder inside the client folder and copy and paste the artifacts/contracts/EternalNFT.sol/EternalNFT.json file inside the utils folder.

folder inside the folder and copy and paste the file inside the folder. Create a config.js file inside the client folder and add the following code inside it.

export const nftContractAddress = "DEPLOYED_CONTRACT_ADDRES"

Replace the DEPLOYED_CONTRACT_ADDRES with the deployed contract address from the terminal when deploying the smart contract.

Next, to set up the frontend go to client/pages/index.js and update it with the following code:

Let’s discuss the code we have added to the index.js file

The code contains the following functions:

checkIfWalletIsConnected : This function checks if the wallet is connected to the dapp when it loads.

: This function checks if the wallet is connected to the dapp when it loads. connectWallet : This function connects the wallet to the dapp when the user clicks the Connect Wallet button in the frontend.

: This function connects the wallet to the dapp when the user clicks the button in the frontend. checkCorrectNetwork : This function checks if the wallet is connected to the rinkeby network. If not the frontend asks the user to connect to the rinkeby network and reload the page.

: This function checks if the wallet is connected to the network. If not the frontend asks the user to connect to the network and reload the page. mintCharacter : This function creates the transaction to mint a new NFT when the user clicks on the Mint Character button.

: This function creates the transaction to mint a new NFT when the user clicks on the button. getMintedNFT : This function retrieves the data of the newly minted NFT to display it in the frontend.

To test the dapp in the browser, run the following command in your terminal:

cd client npm run dev

Next Steps

Congratulations! You have deployed a full-stack NFT minting dapp to ethereum.

After successfully deploying the dapp, you can host it on services like vercel or netlify.

You can find me on:

Twitter — abhinavxt.eth

GitHub — AbhinavXT

Medium — Abhinav Pathak