James Bachini

How To Generate Artwork For NFT’s With Jang.js


This article explains how to generate artwork for NFT’s like cryptopunks where there are 10,000 profile pictures.

Most of the NFT generators you’ll find online are designed for simplicity and ease of use for non-developers. I wanted to create something which was customisable and expandable to allow for more innovative NFT collections.

Jang.js “Just Another NFT Generator” is a NodeJS script I wrote to do just that. You can use it to create your own collection of 10000 NFT profile pictures with rare traits, optimised images and complex design patterns.

  1. Jang.js Video Demonstration
  2. How to make a 10000 image NFT collection?
  3. How to draw all the different layers
  4. Customising the Jang.js script
  5. Example code for Jang.js layers
  6. Next steps towards a NFT drop

Jang.js Video Demonstration

James On YouTube

How to make a 10000 image NFT collection?

NFT collections like Crypto Punks and Bored Apes have thousands of unique artworks. Creators don’t design each one individually however. Each NFT is built up of layers and traits placed on top of each other.

For example a single NFT might have a certain background, body shape, skin tone, eye colour, mouth shape etc. By mixing these attributes it allows us to generate unique images.

How many layers do I need for 10000 NFTs?
For example if we had 10 backgrounds, 10 body shapes, 5 skin tones, 5 eye colours and 4 mouth shapes, this alone would produce the 10,000 unique images when combined together uniquely.

How to draw all the different layers

We can draw these layers using graphics software like Photoshop or Inkscape and then export the individual layers as a PNG image with a transparent background. This lets us stack images on top of each other building the profile pic with each new layer.

Drawing layers for NFTs
Creating Image Layers With Inkscape

Customising the Jang.js script

First of all you’ll need Node.js installed https://nodejs.org

Then clone the github repo at:

Open a terminal inside the directory and install dependencies with npm install

We can then open up the jang.js file in a text editor and start editing the basic details.

How To Generate Artwork For NFT's

Once that’s updated we can start building our layers.

The image layers go in to a directory called layers/ and are formatted as follows layers/TraitType/TraitName i.e. layers/Eyes/Blue.png

The traits are automatically added to the JSON metadata that will inform 3rd parties like OpenSea which NFT has which trait.

Once we have our images in place we can scroll down to where it says /* Add layers using various methods here */ to start building our NFT layers.

Example code for Jang.js layers

Basic random from array

const arr = ['Background1','Background2','Background3','Background4'];
const bkg = arr[Math.floor(Math.random()*arr.length)];
await addLayer('Backgrounds', bkg, ctx);

Generating playing cards from nftID (can be used in the smart contract too)

// Numbers
const cardNumber = n % 13 + 1;
await addLayer('Numbers', cardNumber, attributes, ctx);
// Suits
const suitRef = n % 4;
const arr = ['Spades','Hearts','Diamonds','Clubs'];
const suit = arr[suitRef];
await addLayer('Suits', suit, attributes, ctx);

Custom rarity with some randomness

let character = 'Jack';
if (Math.random() > 0.7) character = 'Jill';
if (Math.random() > 0.99) character = 'James';
await addLayer('Characters', character, ctx);

Super rare one offs

const arr = ['Human','Ape','Mutant','Punk','Loogie'];
let attr = arr[Math.floor(Math.random()*arr.length)];
const alienID = Math.floor(Math.random() * 10000);
if (nftID === alienID) attr = 'Alien';
await addLayer('AvatarType', attr, ctx);

Specific traits for specific ID’s

const arr = ['Happy','Sad'];
let mouth = arr[Math.floor(Math.random()*arr.length)];
if (nftID.includes(420)) mouth = 'Smoking';
await addLayer('Eyes', mouth, ctx);

Add Numeric Attributes With No Image Layers

const strength = Math.floor(Math.random()*99);
ctx.attributes.push({ 'trait_type': 'Strength', 'value': strength });

Add a image layer or filter but no attribute

const img = await canvas.loadImage(`${dir.input}/vignette.png`);

Next steps towards a NFT drop

You might want to leave Jang.js running overnight to build all the NFT’s. Once finished you’ll have 3 folders in output/

  • output/hdimages – Original HD images
  • output/images – Compressed images to cut down file size
  • output/metadata – JSON metadata

The next step is to upload the NFT images and metadata to IPFS. You only need one of the two directories, either hdimages or images.

To upload your NFT’s to IPFS check out https://nft.storage or https://www.pinata.cloud/

For creating the smart contract check out OpenZepellin’s ERC721 token library and documentation: https://docs.openzeppelin.com/contracts/4.x/erc721

For compiling and deploying the contract you can use https://remix.ethereum.org

The smart contract deployment is a bit outside the scope of this article but I’ll discuss it further in a future tutorial. Check here: https://jamesbachini.com/category/blockchain/smart-contracts/

Get The Blockchain Sector Newsletter, binge the YouTube channel and connect with me on Twitter

The Blockchain Sector newsletter goes out a few times a month when there is breaking news or interesting developments to discuss. All the content I produce is free, if you’d like to help please share this content on social media.

Thank you.

James Bachini

Disclaimer: Not a financial advisor, not financial advice. The content I create is to document my journey and for educational and entertainment purposes only. It is not under any circumstances investment advice. I am not an investment or trading professional and am learning myself while still making plenty of mistakes along the way. Any code published is experimental and not production ready to be used for financial transactions. Do your own research and do not play with funds you do not want to lose.