Prepare collection assets

A Ternoa Collection is composed of three files: a profile picture image, a banner image, and a metadata JSON file. The image files CID is nested into the metadata file and all are stored on IPFS (Interplanetary File Systems) with their dedicated hashes.

IPFS (Interplanetary File Systems) is one of the solutions we recommend to upload NFTs media and other associated metadata. Thus off-chain data are stored in a fully decentralized way and only the link to this metadata is stored on-chain as part of the NFT. This link is frequently a fingerprint called a cryptographic ID (e.g. Qmf5RHhnUjSCfCN9d1Ee6sUWxe3Eqvogw1cTsssrxAxtPn). IPFS files are accessible using those hashes.

Ternoa provides its own IPFS public nodes on different HTTP gateways based on the network environment:

Please note that an api-key is needed to store data on those gateways. Visit IPFS Keymanager to obtain your API Key. After being generated, the key may need a few minutes to become effective for use with the Ternoa client. Learn about the Ternoa IPFS client here.

Off-Chain Metadata

A collection has a unique ID. On-chain data contains this ID coupled with additional important information like ownership. However, media and metadata are stored off-chain for performance and flexibility. These data must be carefully written to guarantee compatibility across the tools and dApps of the ecosystem. Ternoa Improvement Proposals (TIPs) propose structures adopted from ERC-1155 to ensure this compatibility.

Here below is the expected format for collection:


  "name": "Name of the collection",
  "description": "Description of the collection",
  "banner_image": "Hash of the collection's banner image",
  "profile_image": "Hash of the collection's profile image"

Ternoa IPFS Client


  • Install and set up your editor of choice (for example Visual Studio Code [VSC])

  • Install Ternoa-JS

An IPFS client is available on Ternoa-JS SDK to make IPFS upload simple with only one line of code.

Place any asset you want to use at the root of your project and use this code snippet by completing PROFILE_PICTURE_FILE_NAME, BANNER_FILE_NAME, PROFILE_PICTURE_FILE_TYPE & BANNER_FILE_TYPE:

import fs from "fs";
import { TernoaIPFS, File } from "ternoa-js";

const main = async () => {
  const profilePicture = new File(
    [await fs.promises.readFile("_PROFILE_PICTURE_FILE_NAME_")],

  const bannerPicture = new File(
    [await fs.promises.readFile("_BANNER_FILE_NAME_")],
      type: "_BANNER_FILE_TYPE_",

  const ipfsClient = new TernoaIPFS(new URL("IPFS_NODE_URL"), "IPFS_API_KEY");

  const collectionMetadata = {
    name: "Collection TITLE",
    description: "Collection DESCRIPTION",

  const { Hash } = await ipfsClient.storeCollection(
  console.log("The off-chain metadata CID hash is ", Hash);

First, both image files are read from the file system and wrapped in a specific File instance imported from the Ternoa-JS library. The TernoaIPFS class is then used to create an IPFS client that connects to a specified IPFS node using a given API key. The metadata for both files is then passed to the storeCollection method of the client along with the File instance. The resulting Hash of the off-chain metadata is logged to the console.

The storeCollection method handles three IPFS uploads under the hood: a first one with the collection profile picture, a second one with the collection banner picture, and a third one with the JSON metadata file, including the picture hashes from the two first upload responses. This method also validates the metadata structure to ensure TIPs compatibility.


The next step will be the on-chain minting using the Hash previously generated. Keep it and continue on the Mint a Collection guide.


If you face any trouble, feel free to reach out to our community engineers in our Discord.

Last updated