mirror of
https://github.com/supabase/supabase.git
synced 2026-06-18 05:33:50 +08:00
## What Migrates the Edge Functions **documentation** from the legacy `Deno.serve` + manual `createClient` pattern to the [`@supabase/server`](https://github.com/supabase/server) `withSupabase` wrapper. This is the part of [COM-269](https://linear.app/supabase/issue/COM-269) that AI coding assistants index, so it's split out to ship first; the standalone `examples/` functions follow in a second PR. ## Canonical pattern ```ts import { withSupabase } from 'npm:@supabase/server@1' export default { fetch: withSupabase({ auth: 'user' }, async (req, ctx) => { const { data } = await ctx.supabase.from('countries').select('*') return Response.json({ data }) }), } ``` - `export default { fetch }` object shape (not `Deno.serve`, not a bare default export), versioned `npm:@supabase/server@1`. - `auth` mode picks the caller: `user` → `ctx.supabase` (RLS); `secret`/`publishable`/`none` → set `verify_jwt = false`, `secret` uses `ctx.supabaseAdmin`. - `Response.json(...)` over `new Response(JSON.stringify(...))`. ## Changes - **AI prompt** (`examples/prompts/edge-functions.md`) — rewritten to lead with `withSupabase` as the default; `auth`-mode table; `@supabase/server@1`. Highest AI-indexing impact. - **connect-to-postgres** — "Using supabase-js" now uses `ctx.supabase` (+ its CodeSample deps `postgres-on-the-edge`, `drizzle`). - **Example pages** — semantic-search, push-notifications, amazon-bedrock, cloudflare-turnstile, og-image, send-emails, slack-bot-mention, auth-send-email-hook. - **Guides** — ai-models, background-tasks, routing (+ `restful-tasks` dep), kysely-postgres, sentry-monitoring, upstash-redis, elevenlabs ×2, websockets, cors (reframed: CORS is automatic with `withSupabase`). ## Notable fixes - **websockets**: the JWT-auth examples had a latent bug — handler wasn't `async` and called `getClaims()` without the extracted token. Now `await supabase.auth.getUser(jwt)`. (`withSupabase` can't authenticate WebSocket clients since they can't send headers — noted in the page.) - **restful-tasks**: fixed a broken `npm:supabase-js` import → `npm:@supabase/supabase-js`. ## Follow-ups (not in this PR) - The ~42 standalone `examples/` edge functions → second PR. - A dedicated `withSupabase` intro page (today it's only documented inside the auth-framed "Securing Edge Functions" page). - `.claude/skills/supabase-server/SKILL.md` is stale (`allow:` vs `auth:`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated Edge Function examples to the modern withSupabase + exported fetch handler pattern across guides and examples. * Standardized JSON response/error handling (uses built-in JSON helpers) and preserved streaming/SSE behaviors where applicable. * Clarified auth modes, context clients (user vs admin), and automatic CORS handling; removed manual preflight boilerplate. * Updated local serve/deploy instructions to include --no-verify-jwt for relevant examples. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
91 lines
2.3 KiB
Plaintext
91 lines
2.3 KiB
Plaintext
---
|
||
title: 'Sending Emails'
|
||
description: 'Sending emails from Edge Functions using the Resend API.'
|
||
tocVideo: 'Qf7XvL1fjvo'
|
||
---
|
||
|
||
Sending emails from Edge Functions using the [Resend API](https://resend.com/).
|
||
|
||
### Prerequisites
|
||
|
||
To get the most out of this guide, you’ll need to:
|
||
|
||
- [Create an API key](https://resend.com/api-keys)
|
||
- [Verify your domain](https://resend.com/domains)
|
||
|
||
Make sure you have the latest version of the [Supabase CLI](/docs/guides/cli#installation) installed.
|
||
|
||
### 1. Create Supabase function
|
||
|
||
Create a new function locally:
|
||
|
||
```bash
|
||
supabase functions new resend
|
||
```
|
||
|
||
Store the `RESEND_API_KEY` in your `.env` file.
|
||
|
||
### 2. Edit the handler function
|
||
|
||
Paste the following code into the `index.ts` file:
|
||
|
||
```tsx
|
||
import { withSupabase } from 'npm:@supabase/server@^1'
|
||
|
||
const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY')
|
||
|
||
const handler = async (_request: Request): Promise<Response> => {
|
||
const res = await fetch('https://api.resend.com/emails', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
Authorization: `Bearer ${RESEND_API_KEY}`,
|
||
},
|
||
body: JSON.stringify({
|
||
from: 'onboarding@resend.dev',
|
||
to: 'delivered@resend.dev',
|
||
subject: 'hello world',
|
||
html: '<strong>it works!</strong>',
|
||
}),
|
||
})
|
||
|
||
const data = await res.json()
|
||
|
||
return Response.json(data)
|
||
}
|
||
|
||
export default { fetch: withSupabase({ auth: ['user', 'secret'] }, handler) }
|
||
```
|
||
|
||
### 3. Deploy and send email
|
||
|
||
Run function locally:
|
||
|
||
```bash
|
||
supabase start
|
||
supabase functions serve --no-verify-jwt --env-file .env
|
||
```
|
||
|
||
The function accepts a signed-in user's JWT or a secret key, so it can be triggered from your app (via `supabase.functions.invoke`) or from a database function. Test it locally with a secret key:
|
||
|
||
```bash
|
||
curl -i --request POST 'http://localhost:54321/functions/v1/resend' \
|
||
--header 'apikey: <SUPABASE_SECRET_KEY>'
|
||
```
|
||
|
||
Deploy function to Supabase:
|
||
|
||
```bash
|
||
supabase functions deploy resend --no-verify-jwt
|
||
```
|
||
|
||
<Admonition type="caution">
|
||
|
||
When you deploy to Supabase, make sure that your `RESEND_API_KEY` is set in [Edge Function Secrets Management](/dashboard/project/_/functions/secrets)
|
||
|
||
</Admonition>
|
||
|
||
### 4. Try it yourself
|
||
|
||
Find the complete example on [GitHub](https://github.com/resendlabs/resend-supabase-edge-functions-example).
|