Artwork, traits and metadata

The artwork is the image that makes each NFT visually unique, and along with the metadata contributes towards the NFT's rarity.

When it comes to the type of "generative" NFTs that we will be creating, the artwork is created using different layers that can be combined in different ways to create unique artworks.

NFT traits are the various building blocks that form the final image of an NFT when each trait is layered on top of each other. For example, a simple collection might have a "body" trait group with three possible traits: "skinny", "fat", and "muscular" - each trait representing a corresponding image.

With this one trait group, we can generate 3 different artworks. Adding a second trait group with two traits ("head": "big" and "small") will mean that there are 6 possible combinations of artwork that can be generated.

The metadata attributes field must define the traits used in the NFT's artwork to allow marketplaces and other tools (like rarity calculators) to display and use the traits on their platforms.

For example:

{
    ...
    attributes: [{
        "trait_type": "Body",
        "value": "Skinny"
    }, {
        "trait_type": "Head",
        "value": "Big"
    }]
}

Preparing the artwork and traits

For a large NFT drop, we're going to be dealing with a lot of trait groups and the key here is to be organised. As the developer who will ultimately be generating the individual images for each NFT and corresponding metadata it's important to guide the design team into how best to deliver the artwork and trait groups.

Traits groups and trait names

It's important to create a single source of truth for all trait groups and trait names to be defined. I've found that creating a spreadsheet specific for this purpose is best, which is why I've included this Project Planner spreadsheet as a valuable resource to accompany this book. The client can easily fill this out - and any inconsistencies that might appear in the spreadsheet or the photoshop file are irrelevant, since it will be understood that this spreadsheet is where rarity and trait names will be taken from.

Custom rules for trait matching

It's common for there to be certain rules that will need to be followed - for example, to only include certain traits when another appears or vice versa. Again - here the key is organisation - use the Project Planner spreadsheet as the source of truth.

Photoshop file

Photoshop is a great tool for preparing NFT artwork, becuase of its ability to organise artwork into layers and groups. Here are some instructions to pass on to the design team:

  • Create a group for every trait group
  • Order the groups in the order that they should be layered
  • Label each trait in each trait group
  • Name each trait the same as in the rarity table
  • Order each trait layer alphabetically
  • Include "empty" traits as an empty layer (tip: these still can be called something in the spreadsheet. e.g.: use "Bald" not "Empty" or "None" - since that's what will appear on the NFT)

Generating the artwork and metadata

The Hashlips library is the de facto tool for generative artwork and metadata. I've created a fork of the library with a few additional tools that fit in well with the processes defined in this book.

Pull in the library from https://github.com/michaelstivala/hashlips.

How Hashlips works

The hashlips library expects your layers to be organised in a folder structure that corresponds to how the layers are organised in photoshop: folders for each trait group, with each trait named correctly. Each trait can have an optional "rarity" percentage (denoted by adding a # sign followed by the rarity percentage) which will be used when generating the artwork.

The folder structure looks a little like this:

- Background
--- Blue.png
--- Black.png
- Body
--- Skinny#25.png
--- Fat#75.png
- Hair
--- Long#10.png
--- Short#90.png
Layer configurations

We'll need to configure hashlips to generate our layers in the correct order. In the src/config.js file you'll notice a layerConfigurations variable that for our example can be filled quite simply like below.

const layerConfigurations: [{
    growEditionSizeTo: 50,
    { name: 'Background' },
    { name: 'Body' },
    { name: 'Hair' }
}]

Notice that the name parameter must match the folder name of the trait group exactly.

Ignoring layers for uniqueness

A common usecase is to ignore the background layer when deciding whether an artwork is unique. There is an easy way to configure this by passing in the bypassDNA option.

const layerConfigurations: [{
    growEditionSizeTo: 50,
    { name: 'Background', options: { bypassDNA: true } },
    { name: 'Body' },
    { name: 'Hair' }
}]
Implementing custom rules for trait matching

Hashlips allows us to pass in multiple configurations here, and we can leverage this to implement our custom rules for trait matching. For instance, given that we have two body traits: "Female" and "Male". The "Female" characters can have certain female hair styles, and the same goes for the "Male" characters.

We can accomplish this in hashlips by using a little trick that allows us to specify a layer name that is different from the folder name.

const layerConfigurations: [{
    growEditionSizeTo: 25,
    { name: 'Background', options: { bypassDNA: true } },
    { name: 'Male Body', options: { displayName: 'Body' } },
    { name: 'Male Hair', options: { displayName: 'Hair' } }
}, {
    growEditionSizeTo: 25,
    { name: 'Background', options: { bypassDNA: true } },
    { name: 'Female Body', options: { displayName: 'Body' } },
    { name: 'Female Hair', options: { displayName: 'Hair' } }
}]

This allows us to organise our trait groups into different folders depending on the trait matching rules that we're trying to achieve.

Exporting the layers from photoshop

Photoshop has a function to automatically export every layer, which is just what we need.

  • File -> Export -> Layers to Files
  • Choose a folder to export the images to
  • Set the prefix to none
  • Set the file type to PNG-24
  • Ensure "Transparency" is ticked
  • Ensure "Interlaced" and "Trim Layers" are unticked
  • Click Run!

This might take a while, but at the end of it all you'll have a folder with every layer exported as a PNG.

Organising the exported images

We first need to organise the exported layers into a structure that corresponds to how the layers were organised in photoshop: folders for each trait group, with each trait named correctly.

While there are a lot of images to deal with, this process shouldn't take too long. Photoshop will have prefixed images exported from the same group in the same way, so it will be easy to drag traits into folders.

Bulk renaming images

Once all traits are in their right folders, we need to ensure that the traits are named exactly like they are named in the trait groups and trait names spreadsheet - since these names will appear in the generated metadata. I find it easiest to use a bulk-renaming tool to remove all the prefixes from the filenames, and to do any additional clean up necessary (like replacing hyphens with spaces). On mac, the NameChanger app is an easy to use tool to help with this.

NameChanger app

Custom rules and trait matching

This is where the corresponding spreadsheet will come in handy. Our job is to organise the traits in a way that will allow us to configure hashlips in a way that implements the custom rules for trait matching.

Adding rarity information

With all traits named correctly and in their corresponding trait group folder, we need to add in the rarity information from our spreadsheet.

Storing all these assets

We can use the https://nft.storage service that uses IPFS under the hood to upload our artwork and metadata.

It's likely that you'll need to tweak the generated metadata for your project - there's a helper script in LuzzuLips that will help you do that.

Finally, LuzzuLips has a utility to upload the images and metadata when they are ready by running the npm run upload command.

results matching ""

    No results matching ""