Skip to content

Commit b526a69

Browse files
committed
Add best practices and troubleshooting tips
1 parent f78f794 commit b526a69

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed
76 KB
Binary file not shown.

docs/integrations/supabase.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ You can only generate sample data **once** per project. If you need to modify or
169169

170170
[Supabase Edge Functions](https://supabase.com/docs/guides/functions) let you run secure, server-side code without needing your own backend. These functions are perfect for tasks that require backend logic, secret handling, or integrations with external APIs such as OpenAI. Because they run on Supabase’s global edge network, they are fast, scalable, and isolated from your client code.
171171

172+
:::info
173+
Unlike database functions or triggers, edge functions execute outside the database engine, giving you full flexibility to write custom logic without being tied to SQL or database-level events.
174+
:::
175+
172176
Edge Functions are ideal for:
173177

174178
- **Calling external APIs securely** (e.g., Stripe, Twilio, OpenAI) without exposing keys in the client app
@@ -312,6 +316,22 @@ This is extremely helpful for verifying that your function is running correctly
312316
313317
:::
314318
319+
### Best Practices
320+
321+
- **Each Function Lives in Its Own Folder**: Every edge function should have its own directory containing an `index.ts` entry file. For example:
322+
323+
```jsx
324+
supabase/
325+
functions/
326+
generate-summary/
327+
index.ts
328+
send-email/
329+
index.ts
330+
```
331+
332+
- **Use Shared Modules for Reusable Logic:** If multiple functions need the same utilities (like an OpenAI client, validators, or formatting helpers), place them inside `supabase/functions/_shared/`. This avoids code duplication and keeps each function focused only on its own task.
333+
- **Use `database.types.ts` for Strong Typing:** Generate and import `database.types.ts` to ensure all database queries inside edge functions match your actual schema. This provides autocomplete, prevents schema mismatches, and makes your functions safer and easier to maintain.
334+
315335
## FAQs
316336
317337
<details>
@@ -350,4 +370,60 @@ When sample data is created, it inserts records directly into the Supabase datab
350370
351371
To fix it, you can delete the dummy user record from the Auth table and then sign up again in your app with that email.
352372
</p>
373+
</details>
374+
375+
<details>
376+
<summary>
377+
Why do I get “ClientException: Failed to fetch” when calling an Edge Function?
378+
</summary>
379+
380+
<p>
381+
This error almost always happens because the **browser blocked the request due to CORS**, so your Supabase Edge Function never received it. The browser sends a **CORS preflight (OPTIONS)** request first. If your function doesn’t handle `OPTIONS` or doesn’t return valid `Access-Control-Allow-*` headers, the browser stops the request and it reports “Failed to fetch.”
382+
383+
**Fix:** Add proper CORS handling inside your Edge Function. The example below includes the required CORS configuration—most importantly the *Access-Control-Allow-Origin* header—along with the other *Access-Control-Allow-** headers and correct handling of the OPTIONS preflight request.
384+
385+
```jsx
386+
// CORS headers added to allow the browser request to pass
387+
// The key fix is "Access-Control-Allow-Origin": "*"
388+
const corsHeaders = {
389+
"Access-Control-Allow-Origin": "*", // <-- required for web requests
390+
"Access-Control-Allow-Headers":
391+
"authorization, x-client-info, apikey, content-type", // required for Supabase auth + JSON
392+
"Access-Control-Allow-Methods": "GET, POST, OPTIONS", // allow methods including OPTIONS
393+
};
394+
395+
Deno.serve(async (req) => {
396+
if (req.method === "OPTIONS") {
397+
return new Response("ok", { headers: corsHeaders });
398+
}
399+
400+
const url = new URL(req.url);
401+
const habit = url.searchParams.get("habit") ?? "daily";
402+
const tone = url.searchParams.get("tone") ?? "encouraging";
403+
404+
return new Response(JSON.stringify({
405+
message: `Tiny step, big impact. Your ${habit} practice is blooming — keep it ${tone}!`,
406+
}), {
407+
headers: { ...corsHeaders, "Content-Type": "application/json" },
408+
});
409+
});
410+
411+
```
412+
413+
After updating, redeploy your edge function and test it. Then open **Supabase Dashboard → Edge Functions → Logs** to verify that the request is now reaching the server.
414+
</p>
415+
</details>
416+
417+
418+
419+
<details>
420+
<summary>
421+
Do I need to be logged in when calling my Supabase Edge Function?
422+
</summary>
423+
424+
<p>
425+
It depends on whether the function **requires JWT verification**. If the “Verify JWT with legacy secret” toggle is enabled in your Supabase Dashboard, the function expects an authenticated request with a valid JWT in the `Authorization` header. In that case, you must be logged in before calling the function; otherwise the server will reject the request with a **401 Unauthorized** (visible in function logs).
426+
427+
![supabase-edge-function-logged-in](imgs/supabase-edge-function-logged-in.avif)
428+
</p>
353429
</details>

0 commit comments

Comments
 (0)