frontend-connect
npx skills add https://github.com/chloezhu010/vibe-ship --skill frontend-connect
Agent 安装分布
Skill 文档
Frontend Connect
Wire the AI-generated frontend to the live Supabase backend â replacing mock data and localStorage with real queries.
This skill is called by the
vibe-shiporchestrator.FRAMEWORK=nextjsorvite.
1. Apply framework best practices
If FRAMEWORK = nextjs: Invoke next-best-practices
If FRAMEWORK = vite: Invoke vercel-react-best-practices
2. Audit the codebase for mock data patterns
Scan for:
- Hardcoded arrays of objects (e.g.
const users = [{ id: 1, name: '...' }]) localStorage.getItem/localStorage.setItemcallsuseStateinitialised with static data that should be dynamicTODO: fetch from APIcomments
List every instance found with its file path and line number before making any changes.
3. Replace mock data with Supabase queries
For each instance found:
If FRAMEWORK = nextjs (Server Component pattern):
// Before
const items = [{ id: 1, title: 'Example' }]
// After
import { supabase } from '@/lib/supabase'
const { data: items } = await supabase.from('items').select('*')
If FRAMEWORK = vite (client-side hook pattern):
// Before
const [items, setItems] = useState([{ id: 1, title: 'Example' }])
// After
import { useEffect, useState } from 'react'
import { supabase } from '@/lib/supabase'
const [items, setItems] = useState([])
useEffect(() => {
supabase.from('items').select('*').then(({ data }) => setItems(data ?? []))
}, [])
Replace localStorage writes with Supabase inserts:
// Before
localStorage.setItem('items', JSON.stringify(newItem))
// After
await supabase.from('items').insert(newItem)
4. Create a DB mapping layer
Supabase returns snake_case column names; TypeScript interfaces typically use camelCase. Create a single file to handle all translation.
If FRAMEWORK = nextjs â create lib/db.ts
If FRAMEWORK = vite â create src/lib/db.ts
Import paths: Examples below use
@/lib/supabase. Checkvite.config.tsortsconfig.jsonfor the@alias â if it’s not configured or points to the project root rather thansrc/, use relative paths instead (e.g.'../lib/supabase').
For each entity, write a mapX function and an insert helper:
// Example for a "session" entity
export function mapSession(row: Record<string, unknown>) {
return {
id: row.id as string,
userId: row.user_id as string,
createdAt: row.created_at as string,
// map all columns here
}
}
export function toSessionRow(session: Partial<Session>) {
return {
user_id: session.userId,
// reverse map for inserts/updates
}
}
All Supabase query results pass through mapX before use. All inserts/updates pass through the inverse helper. Never scatter column name mapping across components.
Derived vs stored data: Before adding a column to the database, ask: can this value be computed from data already fetched? Counts, streaks, and progress percentages derived from a list of records should be computed client-side, not stored separately â stored copies go stale. Only persist user-set preferences (goals, settings) and source data (individual records).
5. Scope queries to the logged-in user
For any data that belongs to a specific user, first obtain the session, then add .eq('user_id', session.user.id) to the query.
If FRAMEWORK = nextjs (Server Component):
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
const supabase = createServerComponentClient({ cookies })
const { data: { session } } = await supabase.auth.getSession()
const { data: items } = await supabase
.from('items')
.select('*')
.eq('user_id', session?.user.id)
If FRAMEWORK = vite:
import { useAuth } from '@/contexts/AuthContext'
const { session } = useAuth()
useEffect(() => {
if (!session) return
supabase.from('items').select('*')
.eq('user_id', session.user.id)
.then(({ data }) => setItems(data ?? []))
}, [session])
Check supabase/migrations/ for RLS policies. If none exist, prompt: “Your data is not yet scoped to individual users. Go to Supabase â Authentication â Policies to add row-level security rules.”
6. Validate
Ask the user to:
- Run
npm run dev - Confirm data loads from Supabase (check Supabase â Table Editor to verify rows exist)
- Create or update an item and confirm the change appears in Supabase
Report: “â Frontend connected to Supabase. Mock data replaced with live queries.”