Back to Changelog
v1.4.1

June 24, 2024

All about Images!

Image resizing and optimization, ThumbHash, and <BaseHubImage />, this changelog is all about images.


You can now request resized images from our GraphQL API.

query Example {
  homepage {
    heroImage {
      url(width: 500, quality: 70)
    }
  }
}

Or via URL:

https://assets.basehub.com/2fa958b2/mBV9NVWPK632ZKmv9lffA/image.png?width=500

Photo by Patrick Konior on Unsplash.

There are actually a bunch of options to use. We use Cloudflare to handle this, and you can check their docs to see all of the options you have available.

<BaseHubImage /> Component for Next.js

A thin wrapper on top of Next.js’ <Image /> Component. Really, it’s literally just this:

import Image, { ImageProps } from 'next/image'

const basehubImageLoader = () => {...}

export const BaseHubImage = (props: ImageProps) => {
  return <Image {...props} loader={basehubImageLoader} />;
};

And you can use it like this:

import BaseHubImage from "basehub/next-image"

const Home = async () => {
  return (
    <BaseHubImage
      src="https://assets.basehub.com/2fa958b2/mBV9NVWPK632ZKmv9lffA/image.png"
      width={846}
      height={564}
    />
  )
}

export default Home

We built this because most developers don’t want to query our GraphQL API to get images in different sizes and formats and whatnot: they want their framework to do that work. So, <BaseHubImage /> is the same as Next.js’ but uses BaseHub’s Image Pipeline directly instead of using Next.js as the middleman.

Although this is not something you should worry much about, if you plan on having many, many images, Next.js’ own image optimization might get resource intensive—and we’re already doing that optimization for you.

ThumbHash and Blur Data URL

ThumbHash, created by Evan Wallace, is a library for creating “a very compact representation of an image placeholder”. Well, you can now get a thumbhash for every image you upload into BaseHub.

query Example {
  blogPosts {
    items {
      coverImage {
        url
        thumbhash
        blurDataURL
      }
    }
  }
}

Keep in mind, in order to render the thumbhash in the browser, you’ll need to decode it using the thumbhash package, or a library like unlazy.

To save you from the hassle of decoding the thumbhash, you can also get the blurDataURL directly from our GraphQL API, which will be ready for use as an <img>’s src.

When to use one vs the other? thumbhash is more lightweight (~30 bytes) than blurDataURL (~400 bytes), so if you want to save some KB (say you’re loading hundreds of images), then you might prefer to use thumbhash. Else, you’ll probably be better off with blurDataURL.

Moreover, when using thumbhash, you’ll need to decode the string yourself in the client side, which might not be what you want. Typical use cases for using the raw thumbhash are when rendering hundreds of images in the same view, such as on an image gallery.

Putting it all together, your list of blog posts can render like this:

import { Pump } from "basehub/react-pump"
import { BaseHubImage } from "basehub/next-image"

const BlogPage = async () => {
  return (
    <Pump
      queries={[
        {
          blogPosts: {
            items: {
              _id: true,
              coverImage: {
                url: true,
                blurDataURL: true,
                alt: true,
              },
            },
          },
        },
      ]}
    >
      {async ([data]) => {
        "use server"

        return (
          <div>
            {data.blogPosts.items.map((post) => {
              return (
                <div key={post._id}>
                  <BaseHubImage
                    src={post.coverImage.url}
                    placeholder="blur"
                    blurDataURL={post.coverImage.blurDataURL} 
                    alt={post.coverImage.alt ?? ""}
                    width={624}
                    height={220}
                  />
                </div>
              )
            })}
          </div>
        )
      }}
    </Pump>
  )
}

export default BlogPage

This example is compatible with Next.js’ recommendation for placeholders.