studio-best-practices

โดย supabase

แนวทางปฏิบัติที่ดีที่สุดสำหรับ React และ TypeScript สำหรับ Supabase Studio ใช้เมื่อเขียน

npx skills add https://github.com/supabase/supabase --skill studio-best-practices

Studio Best Practices

Applies to apps/studio/**/*.{ts,tsx}.

Boolean Naming

Use descriptive prefixes — derive from existing state rather than storing separately:

  • is — state/identity: isLoading, isPaused, isNewRecord
  • has — possession: hasPermission, hasData
  • can — capability: canUpdateColumns, canDelete
  • should — conditional behavior: shouldFetch, shouldRender

Extract complex conditions into named variables:

// ❌ inline multi-condition
{
  !isSchemaLocked && isTableLike(selectedTable) && canUpdateColumns && !isLoading && <Button />
}

// ✅ named variable
const canShowAddButton =
  !isSchemaLocked && isTableLike(selectedTable) && canUpdateColumns && !isLoading
{
  canShowAddButton && <Button />
}

Derive booleans — don't store them:

// ❌ stored derived state
const [isFormValid, setIsFormValid] = useState(false)
useEffect(() => {
  setIsFormValid(name.length > 0 && email.includes('@'))
}, [name, email])

// ✅ derived
const isFormValid = name.length > 0 && email.includes('@')

Component Structure

See vercel-composition-patterns skill for compound component and composition patterns.

Keep components under 200–300 lines. Split when you see:

  • Multiple distinct UI sections
  • Complex conditional rendering
  • Multiple unrelated useState calls
  • Hard to understand at a glance

Co-locate sub-components in the same directory as the parent. Avoid barrel re-export files.

Extract repeated JSX patterns into small components.

Data Fetching

All data fetching uses TanStack Query (React Query). See studio-queries skill for query/mutation patterns and studio-error-handling skill for error display conventions.

Loading / Error / Success Pattern

Top level:

const { data, error, isLoading, isError, isSuccess } = useQuery(...)

if (isLoading) return <GenericSkeletonLoader />
if (isError) return <AlertError error={error} subject="Failed to load data" />
if (isSuccess && data.length === 0) return <EmptyState />
return <DataDisplay data={data} />

Use early returns — avoid deeply nested conditionals.

Inline:

<div>
  {isLoading && <InlineLoader />}
  {isError && <InlineError error={error} />}
  {isSuccess && data.length === 0 && <EmptyState />}
  {isSuccess && data.length > 0 && <DataDisplay data={data} />}
</div>

State Management

Keep state as local as possible; lift only when needed.

Group related form state with react-hook-form rather than multiple useState calls. See studio-ui-patterns skill for form layout and component conventions.

// ❌ multiple related useState
const [name, setName] = useState('')
const [email, setEmail] = useState('')

// ✅ grouped with react-hook-form
const form = useForm<FormValues>({ defaultValues: { name: '', email: '' } })

Custom Hooks

Extract complex or reusable logic into hooks. Return objects, not arrays:

// ❌ array return (hard to extend)
return [value, toggle]

// ✅ object return
return { value, toggle, setTrue, setFalse }

Event Handlers

  • Prop callbacks: on prefix (onClose, onSave)
  • Internal handlers: handle prefix (handleSubmit, handleCancel)

Use useCallback for handlers passed to memoized children; avoid unnecessary inline arrow functions.

Conditional Rendering

// Simple show/hide
<>{isVisible && <Component />}</>

// Binary choice
<>{isLoading ? <Spinner /> : <Content />}</>

// Multiple conditions — use early returns, not nested ternaries
if (isLoading) return <Spinner />
if (isError) return <Error />
return <Content />

Performance

useMemo for genuinely expensive computations (measured, not assumed). Don't wrap everything — only optimize when you have a measured problem or are passing values to memoized children.

TypeScript

Define prop interfaces explicitly. Use discriminated unions for complex state:

type AsyncState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error }

Avoid as any / as Type casts. Validate at boundaries with zod:

// ❌ type cast
const user = apiResponse as User

// ✅ zod parse
const user = userSchema.parse(apiResponse)
// or safe:
const result = userSchema.safeParse(apiResponse)

Testing

Extract logic into .utils.ts pure functions and test exhaustively. See the studio-testing skill for the full testing strategy and decision tree.

Skills เพิ่มเติมจาก supabase

studio-e2e-tests
supabase
เขียนและรันการทดสอบ E2E ด้วย Playwright สำหรับ Supabase Studio ใช้เมื่อถูกถาม
official
vitest
supabase
เฟรมเวิร์กการทดสอบหน่วยความเร็วสูง Vitest ที่ขับเคลื่อนโดย Vite พร้อม API ที่เข้ากันได้กับ Jest ใช้เมื่อเขียนทดสอบ, สร้างม็อก, กำหนดค่าความครอบคลุม, หรือทำงานกับทดสอบ…
official
skill-creator
supabase
คู่มือที่ครอบคลุมสำหรับการสร้างสกิลแบบโมดูลาร์ที่ขยายความสามารถของ Claude ด้วยความรู้เฉพาะทางและเวิร์กโฟลว์ สกิลประกอบด้วยไฟล์ SKILL.md ที่จำเป็นพร้อม YAML frontmatter และคำแนะนำในรูปแบบ markdown รวมถึงทรัพยากรเสริมเพิ่มเติม (สคริปต์ เอกสารอ้างอิง สื่อต่างๆ) ที่จัดระเบียบตามวัตถุประสงค์และโหลดแบบค่อยเป็นค่อยไปเพื่อประหยัดบริบท ออกแบบสกิลโดยยึดตามตัวอย่างการใช้งานที่เป็นรูปธรรม ระบุสคริปต์ที่ใช้ซ้ำได้สำหรับงานที่กำหนดตายตัว ไฟล์อ้างอิงสำหรับความรู้เฉพาะโดเมน และสื่อต่างๆ สำหรับ...
official
supabase
supabase
ใช้เมื่อทำงานใดๆ ที่เกี่ยวข้องกับ Supabase ทริกเกอร์: ผลิตภัณฑ์ของ Supabase (ฐานข้อมูล, การยืนยันตัวตน, ฟังก์ชัน Edge, Realtime, พื้นที่จัดเก็บ, เวกเตอร์, Cron, คิว); ไคลเอนต์…
official
supabase-server
supabase
ใช้เมื่อเขียนโค้ดฝั่งเซิร์ฟเวอร์กับ Supabase — Edge Functions, แอป Hono, ตัวจัดการเว็บฮุค หรือแบ็กเอนด์ใดๆ ที่ต้องการการสร้างไคลเอนต์และการตรวจสอบสิทธิ์ของ Supabase
official
clickhouse-logs-queries
supabase
Write, review, and migrate Supabase logs queries against the ClickHouse-backed `logs` table (the `logs.all.otel` analytics endpoint). Use this whenever a task…
official
dev-toolbar-review
supabase
ใช้เมื่อตรวจสอบ PR ที่เกี่ยวข้องกับ packages/dev-tools/, packages/common/posthog-client.ts,
official
e2e-studio-tests
supabase
รันการทดสอบ e2e ในแอป Studio ใช้เมื่อถูกขอให้รันการทดสอบ e2e รันการทดสอบ studio การทดสอบ playwright หรือทดสอบฟีเจอร์
official