An ERC-721 NFT collection: a tested, deployable Solidity smart contract, paired with two working frontends for minting and browsing it. Each token represents a milestone in a Web3 development journey — first smart contract, first Chainlink integration, first algorithmic trading system, and so on — minted on-chain with verifiable ownership and linked off-chain metadata.
NFT.1.mp4
| Component | Description |
|---|---|
contracts/ |
The smart contract — Solidity source, test suite, and deploy script (Foundry) |
frontend/ |
A React/TypeScript marketplace interface — browse the collection, connect a wallet, mint |
contracts/simple-frontend/ |
A single-file HTML client for lightweight testing without a build step |
The React marketplace is the primary interface. The single-file client exists for quick verification of the contract without installing a frontend toolchain.
An NFT is, at its core, a public and tamper-resistant record of ownership. The contract (NimGenesisNFT.sol) maintains that record: token #1 belongs to address 0xABC..., token #2 belongs to 0xDEF..., and so on. Minting is the act of requesting the contract add a new entry with the caller's address as owner. Once recorded, that ownership is independently verifiable by anyone, without a trusted intermediary.
Artwork and descriptive metadata are not stored on-chain — doing so is prohibitively expensive at scale. Instead, each token stores a tokenURI: a reference (typically IPFS) to a JSON file containing its name, description, and image. The blockchain guarantees who owns a token; the linked file describes what the token is. This on-chain/off-chain split is standard practice across production NFT projects.
Minting calls the contract's mint() function with the required payment (0.001 ETH) and a metadata URI. The contract validates the payment, confirms the collection has not reached its cap (100 tokens), and records the sender as owner of the next token ID.
The frontend holds no persistent state of its own. Every value displayed — ownership, supply, price — is read directly from the blockchain on load. There is no backend service and no database; the chain is the source of truth.
flowchart LR
subgraph Chain["Ethereum (Sepolia or local Anvil)"]
C["NimGenesisNFT.sol<br/>ERC-721 contract"]
end
subgraph Off["Off-chain"]
M["metadata/*.json<br/>+ artwork<br/>(IPFS once deployed)"]
end
subgraph Clients["Client applications"]
F["React marketplace<br/>(frontend/)"]
S["Single-file dApp<br/>(contracts/simple-frontend/)"]
end
W["Wallet<br/>(MetaMask)"] -- "mint(), pays ETH" --> C
C -- "tokenURI references" --> M
F -- "reads owner, supply, price<br/>via ethers.js + RPC" --> C
S -- "reads owner, supply, price<br/>via ethers.js + RPC" --> C
F -- "sends transaction" --> W
S -- "sends transaction" --> W
Each connection shown is a real on-chain read or transaction once the contract is deployed.
# 1. Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# 2. Install contract dependencies and run the test suite
cd contracts
forge install foundry-rs/forge-std --no-git
forge install OpenZeppelin/openzeppelin-contracts --no-git
forge test -vv # → 19 passed; 0 failed
# 3. Start a local blockchain (separate terminal, keep running)
anvil
# 4. Deploy
PRIVATE_KEY=<a private key printed by Anvil> \
forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast
# → note the deployed contract address
# 5. Run the marketplace frontend
cd ../frontend
npm install
npm run devOpen the local URL, enter the deployed contract address and network in the configuration bar below the navigation, load the collection, connect a wallet, and mint.
nim-genesis/
├── README.md
│
├── contracts/ Foundry project
│ ├── src/NimGenesisNFT.sol contract source
│ ├── test/NimGenesisNFT.t.sol 19 tests, including a fuzz test
│ ├── script/Deploy.s.sol deployment script
│ ├── metadata/ off-chain JSON + artwork for the 5 curated tokens
│ ├── scripts/generate-metadata.js regenerates the metadata above
│ ├── simple-frontend/index.html zero-build-step client
│ ├── foundry.toml
│ ├── .env.example
│
│
└── frontend/ React + TypeScript marketplace
├── src/
│ ├── art/MilestoneArt.tsx generated SVG artwork
│ ├── components/ Navbar, NFTCard, WalletModal, etc.
│ ├── context/Web3Context.tsx wallet and contract state
│ ├── hooks/ useWeb3Config, useCollectionData, useMint
│ ├── data/genesisData.ts curated milestone metadata
│ └── pages/ Home, Collection, NFTDetail
The following was executed directly, not assumed from a successful compile:
forge test -vv— 19 tests passing, including a 256-run fuzz test on the payment logic- Deployed to a live local Anvil chain via the production deploy script, producing a real transaction hash and contract address
- Minted from two separate test accounts using
cast send, then confirmed viacast callthatownerOf,getOwnershipDetails, andtotalSupplyreturned correct values - Executed a Node script issuing the identical ethers.js calls used by the frontend against the live chain, confirming every returned field matched expected values
npx tsc --noEmit— zero type errors across the frontend codebasenpm run build— clean production build with no warnings
MIT