Catalog
fauziyasin-s2m4qw/studio-queries

fauziyasin-s2m4qw

studio-queries

React Query conventions for data fetching in Supabase Studio. Use when writing or reviewing query hooks, mutation hooks, or query keys in apps/studio/data/. Covers queryOptions pattern, keys.ts structure, mutation hook template, and imperative fetching.

v1.0LATEST
NewUpdated Jul 19, 2026

Studio Queries & Mutations (React Query)

Follow the patterns in apps/studio/data/. Reference examples:

  • Query options: apps/studio/data/table-editor/table-editor-query.ts
  • Mutation hook: apps/studio/data/edge-functions/edge-functions-update-mutation.ts
  • Keys: apps/studio/data/edge-functions/keys.ts

Query Keys

Define a keys.ts per domain. Export *Keys helpers using array keys with as const. Never inline query keys in components.

export const edgeFunctionsKeys = {
  list: (projectRef: string | undefined) => ['projects', projectRef, 'edge-functions'] as const,
  detail: (projectRef: string | undefined, slug: string | undefined) =>
    ['projects', projectRef, 'edge-function', slug, 'detail'] as const,
}

Query Options (preferred pattern)

Use queryOptions from @tanstack/react-query. This gives type safety and works with both useQuery() and queryClient.fetchQuery().

Rules:

  • Export XVariables, XData, and XError types (prefixed with the domain name)
  • Implement a private getX(variables, signal?) function:
    • Throws if required variables are missing
    • Passes signal for cancellation
    • Calls handleError(error) on failure (which throws); returns data on success
    • Not exported — use queryClient.fetchQuery(xQueryOptions(...)) for imperative fetching
  • Export xQueryOptions() using queryOptions
  • Gate with enabled so the query doesn't run until required variables exist
  • Platform-only queries: include IS_PLATFORM from lib/constants in enabled
  • Don't add extra params to xQueryOptions — callers override by destructuring: { ...xQueryOptions(vars), enabled: true }
import { queryOptions } from '@tanstack/react-query'

import { xKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { IS_PLATFORM } from '@/lib/constants'
import { ResponseError } from '@/types'

export type XVariables = { projectRef?: string }
export type XError = ResponseError

async function getX({ projectRef }: XVariables, signal?: AbortSignal) {
  if (!projectRef) throw new Error('projectRef is required')
  const { data, error } = await get('/v1/projects/{ref}/x', {
    params: { path: { ref: projectRef } },
    signal,
  })
  if (error) handleError(error)
  return data
}

export type XData = Awaited<ReturnType<typeof getX>>

export const xQueryOptions = ({ projectRef }: XVariables) =>
  queryOptions({
    queryKey: xKeys.list(projectRef),
    queryFn: ({ signal }) => getX({ projectRef }, signal),
    enabled: IS_PLATFORM && typeof projectRef !== 'undefined',
  })

Using Query Options in Components

import { useQuery } from '@tanstack/react-query'

import { xQueryOptions } from '@/data/x/x-query'

const { data, isPending, isError } = useQuery(xQueryOptions({ projectRef: project?.ref }))

Imperative Fetching (outside React or in callbacks)

const queryClient = useQueryClient()
const { data: project } = useSelectedProjectQuery()

const handleClick = useCallback(
  async (id: number) => {
    const data = await queryClient.fetchQuery(xQueryOptions({ id, projectRef: project?.ref }))
    // use data...
  },
  [project?.ref, queryClient]
)

Mutation Hook

  • Export a Variables type with projectRef, identifiers, and payload
  • Implement a private updateX(vars) function with required variable validation and handleError
  • Wrap in useXMutation():
    • Accepts UseMutationOptions (omit mutationFn)
    • Invalidates list() + detail() keys in onSuccess with await Promise.all([...])
    • Defaults to toast.error(...) when onError isn't provided
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import toast from 'react-hot-toast'

import { xKeys } from './keys'

type XUpdateVariables = { projectRef: string; slug: string; payload: XPayload }

export const useXUpdateMutation = ({
  onSuccess,
  onError,
  ...options
}: UseMutationOptions<XData, XError, XUpdateVariables> = {}) => {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: updateX,
    async onSuccess(data, variables, context) {
      await Promise.all([
        queryClient.invalidateQueries({
          queryKey: xKeys.detail(variables.projectRef, variables.slug),
        }),
        queryClient.invalidateQueries({ queryKey: xKeys.list(variables.projectRef) }),
      ])
      await onSuccess?.(data, variables, context)
    },
    async onError(error, variables, context) {
      if (onError === undefined) toast.error(`Failed to update: ${error.message}`)
      else onError(error, variables, context)
    },
    ...options,
  })
}

Component Usage

  • Use React Query v5 flags: isPending for initial load, isFetching for background refetches
  • Render states explicitly in order: pending → error → success

Overall Score

84/100

Grade

B

Good

Grades are signals, not a certification. Always review a skill yourself before use.

Safety

92

Quality

82

Clarity

88

Completeness

78

Summary

A focused skill teaching React Query conventions (queryOptions pattern, keys.ts structure, mutation hooks, imperative fetching) for Supabase Studio's data layer. It covers type-safe query definition, hook patterns with built-in error handling and cache invalidation, and component integration, all scoped to apps/studio/data/.

Detected Capabilities

code generationcode pattern referenceTypeScript type definitionfile analysis

Trigger Keywords

Phrases that agents use to match this skill to user intent.

react query hooksquery keys patternmutation cache invalidationsupabase studio dataqueryoptions pattern

Use Cases

  • Write type-safe query hooks using queryOptions
  • Define query key hierarchies in keys.ts
  • Implement cache invalidation in mutation hooks
  • Fetch data imperatively outside React components
  • Review React Query patterns in Supabase Studio codebase

Quality Notes

  • Clear, well-structured guidance with concrete code examples for each pattern
  • Explicitly documents the private vs. exported function boundary (getX vs. xQueryOptions)
  • Type export conventions are clearly specified (XVariables, XData, XError)
  • Shows both declarative (useQuery) and imperative (queryClient.fetchQuery) usage patterns
  • Error handling pattern (handleError throwing, onError defaulting to toast) is documented
  • Cache invalidation strategy is explicit (invalidate both list and detail keys)
  • Scope is appropriately narrow (only apps/studio/data/) with clear reference examples
  • No edge case guidance for polling, refetch intervals, or stale-while-revalidate patterns
  • No guidance on query cancellation error handling or AbortSignal cleanup
  • Platform-only query gating (IS_PLATFORM) is shown but not explained in depth
Model: claude-haiku-4-5-20251001Analyzed: Jul 19, 2026

Reviews

Add this skill to your library to leave a review.

No reviews yet

Be the first to share your experience.

Use fauziyasin-s2m4qw/studio-queries in your dev environment

Command Palette

Search for a command to run...