Create a new Supabase Edge Function with Deno
Creates production-ready Supabase Edge Functions with authentication, error handling, and TypeScript.
/plugin marketplace add citadelgrad/scott-claude-code/plugin install scott-claude-code@scott-claude-codeclaude-sonnet-4-5supabase/Create a new Supabase Edge Function.
$ARGUMENTS
Edge Functions run on Deno Deploy (not Node.js):
npx supabase functions new function-name
// supabase/functions/function-name/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req: Request) => {
try {
// 1. Parse request
const { data } = await req.json()
// 2. Create Supabase client
const supabaseClient = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
{
global: {
headers: {
Authorization: req.headers.get('Authorization')!
}
}
}
)
// 3. Verify user (if needed)
const {
data: { user },
error: authError
} = await supabaseClient.auth.getUser()
if (authError || !user) {
return new Response(
JSON.stringify({ error: 'Unauthorized' }),
{ status: 401, headers: { 'Content-Type': 'application/json' } }
)
}
// 4. Business logic
const result = await processData(data, user)
// 5. Return response
return new Response(
JSON.stringify({ data: result }),
{
status: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
}
)
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{
status: 500,
headers: { 'Content-Type': 'application/json' }
}
)
}
})
Webhook Handler
serve(async (req) => {
const signature = req.headers.get('stripe-signature')
// Verify webhook signature
// Process event
return new Response('OK', { status: 200 })
})
Scheduled Function (with pg_cron)
serve(async () => {
// Run daily cleanup, send emails, etc.
const supabase = createClient(url, serviceKey)
await supabase.from('old_records').delete().lt('created_at', oldDate)
return new Response('Done', { status: 200 })
})
API Proxy/Transform
serve(async (req) => {
const apiKey = Deno.env.get('THIRD_PARTY_API_KEY')
const response = await fetch('https://api.example.com/data', {
headers: { 'Authorization': `Bearer ${apiKey}` }
})
const data = await response.json()
// Transform and return
return new Response(JSON.stringify(data), { status: 200 })
})
# Start Supabase locally
npx supabase start
# Serve function locally
npx supabase functions serve function-name
# Test with curl
curl -X POST http://localhost:54321/functions/v1/function-name \
-H "Authorization: Bearer YOUR_ANON_KEY" \
-H "Content-Type: application/json" \
-d '{"key":"value"}'
# Deploy to Supabase
npx supabase functions deploy function-name
# Set secrets
npx supabase secrets set API_KEY=your-secret-key
# View logs
npx supabase functions logs function-name
// Using Supabase client
const { data, error } = await supabase.functions.invoke('function-name', {
body: { key: 'value' }
})
// Direct fetch
const response = await fetch(
`${SUPABASE_URL}/functions/v1/function-name`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ key: 'value' })
}
)
Security
Performance
Error Handling
Code Organization
# Set locally
echo "API_KEY=secret" > supabase/functions/.env
# Set in production
npx supabase secrets set API_KEY=secret
# Access in function
const apiKey = Deno.env.get('API_KEY')
CORS Handling
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response('ok', {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'authorization, content-type'
}
})
}
// Handle request
})
Database Access
// Read with RLS (uses user's token)
const { data } = await supabaseClient
.from('posts')
.select('*')
// Admin access (bypasses RLS)
const supabaseAdmin = createClient(url, serviceRoleKey)
const { data } = await supabaseAdmin
.from('posts')
.select('*')
Generate production-ready Edge Functions with proper error handling, authentication, and type safety.