Build a Gallery of Your NFTs using Next.js and Alchemy

Building an NFT gallery can be useful for several reasons. First, it allows you to showcase your NFT collection and make it easily accessible to potential buyers or interested individuals.

Second, it can increase the value of your NFTs by creating a unique and appealing display.

Third, creating an NFT gallery can be an exciting and creative way to engage with the NFT community and showcase your creativity and taste.

Finally, building an NFT gallery can be a valuable learning experience and allow you to develop your skills in web development, blockchain integration, and user experience design.

Alchemy is one of the most popular blockchain services that helps developers easily connect with blockchain networks like Ethereum and create applications that utilize the features of these networks.

We will use the Alchemy SDK to interact with the Ethereum blockchain, read data and metadata of NFTs. This SDK provides a simple and easy interface for developers to access the Ethereum network.

We will use the same Next.js infrastructure that we created and developed in the previous tutorial. To add the Alchemy SDK to the project, you can run the following command in your terminal.

pnpm add alchemy-sdk

This command will install the latest version of the Alchemy SDK for use in your Next.js project.

Next, we need to create a new instance of the SDK with our desired settings permanently. To do this, create a new file with the following title and content inside the utils folder, with the name alchemy.ts.

import { Alchemy, Network } from 'alchemy-sdk'

const alchemyApikey = process.env.ALCHEMY_API_KEY

const alchemy = new Alchemy({
  apiKey: alchemyApikey,
  network: Network.ETH_MAINNET,
})

export { alchemy }

Now we need a function that retrieves all NFTs belonging to a specific wallet address and returns an array of token metadata. Create a new file named nfts.ts in the utils folder with the following content.

import { alchemy } from './alchemy'

export type Nft = {
  contractAddress: string
  tokenId: string
  name: string
  type: string
  tokenUri: string | null
  imageUrl: string | null
  updatedAt: string | null
}

const replaceIpfsUrl = (url: string) => {
  if (url.startsWith('ipfs://')) {
    return `https://cloudflare-ipfs.com/ipfs/${url.slice(7)}`
  }
  return url
}

export async function getNftsByAddress(address: string): Promise<Nft[]> {
  // Retrieve NFTs owned by the wallet address
  const nftsForOwner = await alchemy.nft.getNftsForOwner(address)

  // Retrieve metadata for each NFT using Promise.all for concurrency
  const nfts = await Promise.all(
    nftsForOwner.ownedNfts.map(async (nft) => {
      const metadata = await alchemy.nft.getNftMetadata(
        nft.contract.address,
        nft.tokenId,
        {}, // Add empty options object to get all metadata, including custom attributes
      )

      const imageUrl = metadata.rawMetadata?.image ?? null

      // Extract relevant metadata and return it as an Nft object
      return {
        contractAddress: nft.contract.address,
        tokenId: nft.tokenId,
        name: metadata.title,
        type: metadata.tokenType,
        tokenUri: metadata.tokenUri?.gateway ?? null,
        imageUrl: imageUrl ? replaceIpfsUrl(imageUrl) : null,
        updatedAt: metadata.timeLastUpdated ?? null,
      }
    }),
  )

  return nfts
}

This code provides a function called getNftsByAddress that returns a list of information about NFTs belonging to a specific wallet address.

After writing the getNftsByAddress function, to use it to build a gallery on a Next.js static site, you can use getStaticProps to get the information related to NFTs and use it in your project.

Create a new file named gallery.tsx inside the pages directory. In this file, first import the getNftsByAddress function and then use getStaticProps to fetch the necessary data for the gallery.

import { GetStaticProps } from 'next'
import Image from 'next/image'
import Layout from '../components/layout'
import { getNftsByAddress, Nft } from '../utils/nfts'

type Props = {
  nfts: Nft[]
}

const Gallery = ({ nfts }: Props) => {
  return (
    <>
      <Layout title="Gallery">
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3">
          {nfts.map((nft) => (
            <div key={`${nft.contractAddress}-${nft.tokenId}`}>
              {nft.imageUrl && (
                <div className="relative h-80">
                  <Image src={nft.imageUrl} alt={nft.name} fill />
                </div>
              )}
              <div className="mt-2">{nft.name}</div>
            </div>
          ))}
        </div>
      </Layout>
    </>
  )
}

export default Gallery

export const getStaticProps: GetStaticProps<Props> = async () => {
  const walletAddress = process.env.WALLET_ADDRESS ?? ''
  const nfts = await getNftsByAddress(walletAddress)

  return {
    props: {
      nfts,
    },
  }
}

In the above code, we used getStaticProps to fetch data related to NFTs and put them in props. Then using this props, we can create the desired gallery.

In this example, we used a div with a grid and 3-column layout to display images in different columns. Each image is in a separate div and the name of the NFT along with its image is displayed.