Source data (avatars) into the Gatsby Data Layer from a Supabase table

On yesterday's unauthorized and rum-fueled treasure hunt in the sharky waters around the Gatsby islands, we refactored the little avatar section on Prune your follows from client-side to server-side rendering!

Stream Screendump

PR: If you did (or do) watch the show, you'll see that I have sneakily done some cleaning up and solved our little environment variable problem by making sure I load them in the gatsby-config 🤦‍♀️ 🤪

The What?

Source data from the avatars table on build, so that the little avatars are present as part of the statically generated version of the marketing page.

The Why?

It gets rid of the tiny flicker of no content, and why call Supabase every time someone lands on the marketing page for Prune your follows when there is no need? You can also use your service key when sourcing, allowing you to even information from otherwise locked down table rows.

Screendump of avatars on Prune your follows

The How

  • Fetch data on avatars using the Supabase SKD this time
  • Create a Gatsby node for each avatar using createNode, createNodeId and createContentDigest.

The Code

// File: gatsby-node.js
// Note: Error handling omitted

const { createClient } = require("@supabase/supabase-js");

const supabaseUrl = process.env.GATSBY_PUBLIC_SUPABASE_URL;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_KEY;

const serviceSupabase = createClient(supabaseUrl, supabaseServiceKey);

exports.sourceNodes = async (gatsbyUtils) => {
  const { actions, createNodeId, createContentDigest, reporter } = gatsbyUtils;
  const { createNode } = actions;

  const { data } = await serviceSupabase
    .select("username, avatar_url")

  data.forEach((item) => {
      id: createNodeId(item.username),
      avatarUrl: item.avatar_url,
      username: item.username,
      internal: {
        type: "UserAvatar",
        contentDigest: createContentDigest(item),

And voila, we have avatar nodes in the data layer we may use in the Avatars component:

// File: Avatars.js
// Note: Styling omitted

import React from "react";
import { useStaticQuery, graphql } from "gatsby";

export function Avatars() {
  const data = useStaticQuery(graphql`
    query {
      allUserAvatar {
        nodes {

  return (
      { => {
        return (
          <img key={user.username} src={user.avatarUrl} alt={user.username} />

To see the entire app code, check out its GitHub repository.

All the best,
Queen Raae

Interested in more daily treasures like this one?
Sent directly to your inbox?