Files
supabase/apps/studio/components/interfaces/HomeNew/TableQuickstart/useQuickstart.ts
Sean Oliver ec4bc204b1 feat: Add TableQuickstart experiment for onboarding flow
Implements a growth engineering experiment to improve new user onboarding
by providing AI-powered and template-based table creation options.

Features:
- AI prompt interface for describing app requirements
- Pre-built templates for common app types (social media, e-commerce, blog, etc.)
- Seamless integration with existing table editor
- State management using Valtio for reliable data flow
- PostHog feature flag controlled (tableQuickstart)

Technical implementation:
- Uses Valtio proxy-based state management instead of sessionStorage
- Properly handles quickstart flow to prevent race conditions
- Integrates with TableEditor via useQuickstartData hook
- Cleans up state appropriately to prevent panel re-opening issues
- Full TypeScript support with proper type definitions

The experiment aims to reduce time-to-value for new users by providing
smart defaults and reducing the SQL knowledge barrier for initial setup.
2025-09-17 16:01:40 -07:00

88 lines
2.5 KiB
TypeScript

import { useState, useCallback } from 'react'
import { useRouter } from 'next/router'
import { useParams } from 'common'
import type { TableSuggestion } from './types'
import { SOCIAL_MEDIA_TABLES } from './mockData'
import { useQuickstartStore } from './quickstartStore'
export const useQuickstart = () => {
const router = useRouter()
const { ref } = useParams()
const projectId = ref as string
const quickstartStore = useQuickstartStore()
const [currentStep, setCurrentStep] = useState<'input' | 'preview'>('input')
const [candidates, setCandidates] = useState<TableSuggestion[]>([])
const [selectedTable, setSelectedTable] = useState<TableSuggestion | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [userInput, setUserInput] = useState<string>('')
const [isGenerating, setIsGenerating] = useState(false)
const onTablesReady = (
tables: TableSuggestion[] = SOCIAL_MEDIA_TABLES,
input: string = 'social media app with posts and comments'
) => {
setCandidates(tables)
setUserInput(input)
setCurrentStep('preview')
setIsGenerating(false)
}
const handleAiGenerate = useCallback((prompt: string) => {
setIsGenerating(true)
// TODO [Sean]: Replace with actual AI API call
onTablesReady(SOCIAL_MEDIA_TABLES, prompt)
}, [])
const handleSelectTable = useCallback(
async (table: TableSuggestion) => {
setSelectedTable(table)
setLoading(true)
setError(null)
try {
if (!table.tableName || !Array.isArray(table.fields) || table.fields.length === 0) {
throw new Error('Invalid table structure')
}
quickstartStore.setQuickstartData(table)
await router.push(`/project/${projectId}/editor`)
} catch (e) {
const errorMessage = e instanceof Error ? e.message : 'Failed to navigate to table editor'
setError(errorMessage)
setLoading(false)
setCurrentStep('preview')
quickstartStore.clearQuickstartData()
}
},
[projectId, router, quickstartStore]
)
const handleBack = useCallback(() => {
if (currentStep === 'preview') {
setCurrentStep('input')
setCandidates([])
setError(null)
setSelectedTable(null)
setIsGenerating(false)
}
}, [currentStep])
return {
currentStep,
candidates,
selectedTable,
loading,
error,
userInput,
isGenerating,
onTablesReady,
handleAiGenerate,
handleSelectTable,
handleBack,
}
}