thunderlizard nft collection

This summer, I had an incredible experience working at Floodgate, a venture capital firm specializing in pre-seed and seed-stage startups. Thank you to Tyler Whittle, Brooke Martin, and Ann Miura-Ko for believing in my capabilities before I was even aware of them. Before this summer, I had limited knowledge about the crypto & web3 space, and it’s amazing to see how much I’ve learned in just ten weeks.

I created a transfer-restricted generative NFT collection that would serve as an access token for the Outliers. In this article, I’ll reflect on the process of creating a generative non-fungible token art collection, from designing the pixel art to creating a ReactJS web app to minting an NFT on the Ethereum blockchain.

my role
Web Developer
Product Designer
NFT Artist
timeline
July 2022 - August 2022
toolbox
ReactJS
HTML/CSS/Js
Python
Figma
PixilArt
Solidity

1. design the generative pixel art layers

How to generate a collection with custom rarities
For the collection, I wanted to have each thunderlizard avatar be unique and have a set of traits with custom rarities.
Thunderlizard NFT split by layer
Composite traits
Final NFT Example
Stacking traits to generate the final thunderlizard
Respective asset folders for each trait category

I started off thinking about the different PNG layers that I wanted to layer on top of each other and came up with 7 categories: background, body, elements, eyes, hats, roar, and spikes. Each trait category has a different number of trait images.

Using pixilart, I created a new 650x650px canvas and started with the Background category since this would be the first layer for other traits to be layered on top of. Each trait image must be the same size of 650x650px regardless of which parts are transparent.

Layering each png file for each trait category

Some key factors:

  1. Excluding the background trait, each trait image in the categories must have a transparent background in order to be layered on top of each other.
  2. The trait images, each its own layer, should be stacked in order.
  3. Each trait image is drawn where the position of the trait would fit in with respect to the other traits.

I ended up with 65 different layers of traits: 16 background options, 9 body color options, 4 element options, 12 eye options, 6 hat options, and 14 roar options (excluding the one spike option that is layered on each thunderlizard avatar).

One mistake I made was not naming the trait images appropriately, which resulted in me having to go back to rename each trait in the metadata.

In total, I could create a total of 580,608 distinct avatars with the various trait layers.

2. generate collection using python

Using this GitHub repository library, I added my respective thunderlizard assets categorized by trait with each subfolder. In the config.py file, I edited the code for my trait categories to be stacked in order.
# CONFIG is an array of objects where each object represents a layer
# THESE LAYERS MUST BE ORDERED.
CONFIG = [
{
‘id’: 1,
‘name’: ‘background’,
‘directory’: ‘BACKGROUND’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 2,
‘name’: ‘body’,
‘directory’: ‘BODY’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 3,
‘name’:‘spikes’,
‘directory’: ‘SPIKES’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 4,
‘name’: ‘roar’,
‘directory’:‘ROAR’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 5,
‘name’: ‘eyes’,
‘directory’: ‘EYES’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 6,
‘name’: ‘hats’,
‘directory’: ‘HATS’,
‘required’: True,
‘rarity_weights’: None,
},
{
‘id’: 7,
‘name’: ‘elements’,
‘directory’: ‘ELEMENTS’,
‘required’: True,
‘rarity_weights’: None,
},
]
Composite traits

I set each trait’s rarity_weight value to None so each trait would have a uniform probability of being selected for an element. For example, since I created 9 body colors, each body color had a 1/9 chance to be selected when constructing a thunderlizard. . Then, I ran nft.py to generate my collection in the command line that successfully exported to the OUTPUTS folder.

Screenshot of PNGs on Preview
Image generation program and successfully generating the images!

3. storing your nft

There are two options when creating art for an NFT: storing it fully on-chain in the smart contract, or point a smart contract to the IPFS address. I chose the latter for ease of use as it was my first time creating an NFT.
3a. uploading via NFTUp
IPFS URL storing the png images generated

Once the images were generated in the OUTPUTS folder, I used NFTUp to store the png images generated which then gave me an IPFS Image URL in the format “ipfs:// …”.

Since we haven’t generated the metadata for each png image, this will not be the IPFS URL that is used to set your BASE URI in your smart contract.

Going back to the GitHub repository, I modified the metadata.py file to include the IPFS URL containing just the png images.

3b. creating the metadata

In order for NFT marketplaces like OpenSea and Rarible to pull in data to render an image, we need to provide asset metadata by setting the BASE URI in the smart contract. Here’s the OpenSea documentation to read more about why the metadata is necessary.

Digital assets on a given smart contract are typically represented solely by a unique identifier (e.g., the token_id in ERC721), so metadata allows these assets to have additional properties, such as a name, description, and image. [OpenSea Documentation]
Modified metadata.py file
CSV file of the metadata

Going back to the terminal and running the metadata.py file, I ended up with a CSV file and JSON folder containing the metadata needed to link to the base URI for the smart contract.

4. connecting to a smart contract with an IPFS address

I was fortunate enough to have the help of the lead engineer at Standard Crypto, Gavi Galloway, to develop the smart contract which can be seen on Etherscan here. The main feature we wanted to have in the smart contract was having a whitelist MINTER role to mint the NFT and require approval to transfer the NFT.

I uploaded the folder containing the CSV file, JSON file, and the images titled [edition 2022 cohort] to NFTUp to get an IPFS URL. This was different from the first folder we uploaded to IPFS that only included the jpeg images. This is the IPFS URL that I used to set the Base URI in the smart contract since it contains the metadata. One mistake that was made was not having a backslash after setBaseURI(ipfs:// …. /) to hash each index.
The URIs to access each image are in the format BASE_URI + TOKEN_ID where TOKEN_ID starts at index 0 and increments indefinitely.
Uploading the metadata and the images to NFTUp to generate an IPFS URL

Some resources to allow the code to be compatible with IPFS and displayable on OpenSea):

5. coding the front-end web app to mint the NFT

The section in the buildspace tutorial that was most helpful

Now that we have the smart contract ready, I needed an actual web platform that an Outlier could access to mint an NFT.

I used this buildspace tutorial to help me through this process and cloned this GitHub repository to get started. This was also my first time coding in React! Here’s my Github repository :)

Personally, the design engineering process is easiest when I design a landing page prototype in Figma first. This makes coding the front end in ReactJS 10x easier when it comes to design decisions in code.

After going through multiple iterations, I landed on some key features to include in the front end:

  • Status update div box that describes what is currently going on in the back end (e.g. if your wallet is connected, if there was an error minting, currently minting, etc.)
  • Once the NFT has successfully been minted, the Outlier will be able to see their asset on both Etherscan and OpenSea
  • A “connect wallet” button that will display a MetaMask wallet
  • Having both “connect wallet” and “mint nft” not show up at the same time, but once the wallet is connected, the button swaps out for the “mint nft” button
  • A GIF of some example thunderlizard avatars and a blurb of what the collection is for


Figma screenshot of prototype
Designing the landing page on Figma
Screenshot of example code to build out webpage
ReactJS code for the front end

With this deployed React project, I built the front-end components based on the Figma design and followed the tutorial to connect the smart contract with the web app. Some important things I learned:

  1. ABI files: this is really important for the web app to understand how to communicate with the smart contract.
  2. If you’re redeploying a contract, the contract address on the front end App.js needs to be updated, as well as the ABI file.

This is a good tutorial for deploying your React app to host on GitHub pages!

Going back to our smart contract, since I want to have a whitelist of addresses for our Outliers, I have to provide a “minter role” to each address on the “write contract” section on Etherscan.
Once a wallet address has been granted the minter role, they would be able to mint the NFT straight from the website and have it displayed on OpenSea!

conclusion: so what's next?

Screenshot of Figma prototype of minting webpage for Outliers NFT
A Figma mockup of what this may look like

So what’s next? If I could continue this project further and have more time to look into solving this problem, I would really like to explore how I could develop a website that allows the user to choose custom traits on the thunderlizard. By providing the respective trait layers, I would use the frontend ReactJS code to stack the images, instead of going through the process with the Python code, and mint their own custom thunderlizard.

I also want to explore NFTs that aren’t explicitly images/jpeg art but have high functionality coded in the smart contract for dynamic representation. This article by John Palmer is really interesting explaining how NFTs were popularized through media and images that render via a static URL but could do a lot more as proven ownership of a digital asset.
Overall, this project widened my knowledge in the crypto and web3 space in a short amount of time and has placed me in a position to design and develop more projects in this space. As someone really early in their web3 career, I learned a lot about the importance of design and user experience in web3. I would also like to see more design with the user in mind in order to cultivate trust of a new landscape and educate more non-technical users to bridge the knowledge gap. I’ve always been a “do by learning” type of builder, and I experienced Floodgate’s mantra of “Your First True Believers” firsthand through this summer internship. Through their mentorship and guidance this past summer, I feel a lot more confident calling myself an engineer focused on design technologies :)