Day 5 - Using the Netlify edge function to store custom table layouts in The Wheel Screener and LEAPS Screener.

A long awaited feature now finally makes its way to The Wheel Screener and LEAPS Screener - custom table layouts stored per account using our new Netlify edge function

Written by Chris on December 5th, 2025

This post is part of the 'The 12 Days of Full Stack Dev' series, an adventure through full stack fintech app development. Join me through the first 12 days of December as we develop a variety of new features, fixes, and components within the Full Stack Craft fintech family.

For the full list of days and topics in this series, see the original post: The 12 Days of Full Stack Dev.

With the new generic Supabase table CRUD Netlify edge function now created, I can finally implement a long awaited feature for both The Wheel Screener and LEAPS Screener - custom table layouts stored per user account.

We can make some helper functions to make calls to our new Netlify edge function for saving and retrieving the dashboard configurations for each user:

import { Constants } from "../../constants/Constants"

const ENDPOINT = '/.netlify/functions/user-crud-supabase-table'

const TABLE_NAME = process.env.GATSBY_PRODUCT_NAME === Constants.PRODUCT_NAMES.WHEEL_SCREENER ?
  'wheelscreener_dashboard_configs' :
  process.env.GATSBY_PRODUCT_NAME === Constants.PRODUCT_NAMES.LEAPS_SCREENER ?
    'leapsscreener_dashboard_configs' :
    'optionscreener_dashboard_configs'

export const GetDashboardConfigs = async (token: string) => {
  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify({
      action: 'READ',
      table: TABLE_NAME
    })
  })

  if (!response.ok) {
    throw new Error(`Failed to fetch dashboard configs: ${response.status}`)
  }

  return response.json()
}

export const AddDashboardConfig = async (token: string, data: Record<string, any>) => {
  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify({
      action: 'CREATE',
      table: TABLE_NAME,
      data
    })
  })

  if (!response.ok) {
    throw new Error(`Failed to add dashboard config: ${response.status}`)
  }

  return response.json()
}

export const UpdateDashboardConfig = async (token: string, id: string, data: Record<string, any>) => {
  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify({
      action: 'UPDATE',
      table: TABLE_NAME,
      id,
      data
    })
  })

  if (!response.ok) {
    throw new Error(`Failed to update dashboard config: ${response.status}`)
  }

  return response.json()
}

export const DeleteDashboardConfig = async (token: string, id: string) => {
  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`
    },
    body: JSON.stringify({
      action: 'DELETE',
      table: TABLE_NAME,
      id
    })
  })

  if (!response.ok) {
    throw new Error(`Failed to delete dashboard config: ${response.status}`)
  }

  return response.json()
}

More posts:

footer-frame