How to deploy your own nft image onchain

Geoffrey LogoviGeoffrey Logovi
3 min read

How to Create and Deploy an NFT on Sepolia Testnet (Even a Kid Can Do It!)

Have you ever wanted to make your own digital art and show it to the world?Let's build an NFT (like a digital sticker) and put it on a blockchain — step by step!

What is an NFT?

An NFT (Non-Fungible Token) is like a special digital card. It's unique and can't be copied.People use NFTs to show ownership of things like pictures, music, or videos.

We'll create an NFT that lives completely on the blockchain — even the picture itself!

What you need

  • A computer with Node.js installed

  • A MetaMask wallet (like a digital piggy bank for your crypto)

  • Some test ETH on the Sepolia testnet (this is fake money for practice) An Alchemy or Infura account (to talk to the blockchain)A Hardhat account (a tool to help write and deploy smart contracts)

Step 1: Set Up Your Project

Open your terminal and create a folder:

Open your terminal and create a folder: mkdir 16-web3-nftopensea Then, run Hardhat setup: npx hardhat Choose Create a JavaScript project and follow the prompts.

mkdir 16-web3-nftopensea
cd 16-web3-nftopensea
npm init -y
npm install hardhat
npx hardhat

Step 2: Write the smart contract In the contracts folder, create a file called NFTOpensea.sol:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

// Uncomment this line to use console.log
// import "hardhat/console.sol";
// import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

contract NFTOpensea is ERC721URIStorage {
    uint256 private _nextTokenId;

    constructor() ERC721("NFTOpensea", "JAY") {}

    function mint() public {
        uint256 tokenId = _nextTokenId;
        _safeMint(msg.sender, tokenId);
        _nextTokenId++;
    }

    function tokenURI(uint256 tokenId) public pure override returns (string memory) {
        string memory svg = generateSVG();
        string memory json = Base64.encode(
            bytes(
                string(
                    abi.encodePacked(
                        '{"name":"Onchain NFT #',
                        Strings.toString(tokenId),
                        '", "description":"A1 J1 : An on-chain SVG NFT from JAY.", "image":"data:image/svg+xml;base64,',
                        Base64.encode(bytes(svg)),
                        '"}'
                    )
                )
            )
        );

        return string(abi.encodePacked("data:application/json;base64,", json));
    }

    function generateSVG() internal pure returns (string memory) {

        string memory IMG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">'
            '<rect width="200" height="200" fill="#fefefe"/>'
            '<circle cx="100" cy="100" r="20" fill="#ff4500"/>'
            '<text x="50%" y="50%" font-family="Arial" font-size="20" fill="#fff" text-anchor="middle" dy=".3em">JAY</text>'
            '</svg>';

        return IMG;
    }
}


Step 3: Configure Hardhat

Edit hardhat.config.ts:

import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
require('dotenv').config()

const {ALCHEMY_SEPOLIA_API_KEY_URL, ACCOUNT_PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env;

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.28",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
  networks: {
    sepolia: {
      url: ALCHEMY_SEPOLIA_API_KEY_URL,
      accounts: [`0x${ACCOUNT_PRIVATE_KEY}`],
    }
  },
  etherscan: {
    apiKey: ETHERSCAN_API_KEY,
  },
};

export default config;

Create a .env file:

ALCHEMY_SEPOLIA_API_KEY_URL = "https://eth-sepolia.g.alchemy.com/v2/xxxxxxxxxxxxxx"
ACCOUNT_PRIVATE_KEY = "8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ETHERSCAN_API_KEY="xxxxxxxxxxxxeeeeeeeeeeeeeeeeeeee55"

📤 Step 4: Deploy the Contract

In the scripts folder, create deploy.ts:

const hre = require("hardhat");

async function main() {
  const [deployer] = await hre.ethers.getSigners();
  console.log(`Deploying contracts with the account: ${deployer.address}`);

  const NEFTOpensea = await hre.ethers.getContractFactory("NFTOpensea");
  const fundManager = await NEFTOpensea.deploy();
  await fundManager.waitForDeployment();

  console.log(`NFTOpensea deployed at: ${fundManager.target}`);

}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

Deploy it:

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

Step 5: Mint an NFT

Open Hardhat console:

npx hardhat console --network sepolia

Step 6: See It on OpenSea

Visit OpenSea testnet:

https://testnets.opensea.io/assets/sepolia/0xYourContractAddress/0

If the image doesn’t load, click Refresh Metadata.


Congratulations 🎉

You just created and deployed your own NFT. It’s completely on-chain — meaning both the image and metadata live on Ethereum. You can share it, trade it, or build an entire collection haray!!!

0
Subscribe to my newsletter

Read articles from Geoffrey Logovi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Geoffrey Logovi
Geoffrey Logovi

Geoffrey (dʒɛfray or dʒɛfri) shares tech-related opportunities and ways of working with his community to inspire, educate, and raise awareness about the use of technology. Tech, community, developer relations, talks, teach, sharing, build, helps, hack, open source, event...