Supabase new user notifications on your phone.

Get a low-priority push notification when someone signs up to your app with Supabase Auth, with their name and sign-in method.

How it works

Three steps to your first push

STEP 01

Install the recipe

One click in Studio gives you a personal webhook URL.

STEP 02

Paste your URL into Supabase

Add it as a webhook for Insert on auth.users.

STEP 03

Get a push on your phone

With the text, sound and buttons from the recipe.

Setup

How to set up the Supabase insert on auth.users webhook

  1. Click Install in Studio and sign in. The recipe is added to your account and you get a personal webhook URL.
  2. In the Supabase dashboard, open Integrations > Database Webhooks (enable it if asked) and click Create a new hook.
  3. Pick the table and the Insert on auth.users event, and choose HTTP Request with method POST.
  4. Paste your webhook URL as the URL, adding any options from the setup notes below, and create the webhook.https://••••••••/•••••••• your personal URL, shown after install
  5. New Supabase Auth users are rows in the `auth.users` table. Instead of the dashboard form (which would send the whole row, password hash and tokens included), run this once in the **SQL Editor**. It posts the same payload as a Database Webhook, but only with the columns the push needs:
  6. ```sql
  7. create extension if not exists pg_net with schema extensions;
  8. create or replace function public.justpush_new_user()
  9. returns trigger
  10. language plpgsql
  11. security definer
  12. set search_path = ''
  13. as $$
  14. begin
  15. perform net.http_post(
  16. url := 'your webhook URL',
  17. body := jsonb_build_object(
  18. 'type', tg_op,
  19. 'table', tg_table_name,
  20. 'schema', tg_table_schema,
  21. 'record', jsonb_build_object(
  22. 'id', new.id,
  23. 'email', new.email,
  24. 'phone', new.phone,
  25. 'created_at', new.created_at,
  26. 'raw_app_meta_data', new.raw_app_meta_data,
  27. 'raw_user_meta_data', new.raw_user_meta_data
  28. ),
  29. 'old_record', null
  30. ),
  31. headers := '{"Content-Type": "application/json"}'::jsonb,
  32. timeout_milliseconds := 5000
  33. );
  34. return new;
  35. exception when others then
  36. -- Never block a signup because the notification couldn't be queued.
  37. return new;
  38. end;
  39. $$;
  40. create trigger justpush_new_user
  41. after insert on auth.users
  42. for each row execute function public.justpush_new_user();
  43. ```
  44. `pg_net` sends the request in the background after the signup commits, so it doesn't slow sign-ups down.
  45. To name your app in the title ("👤 New Acme user"), end the URL in the SQL with `?app=Acme`.
  46. To remove it:
  47. ```sql
  48. drop trigger if exists justpush_new_user on auth.users;
  49. drop function if exists public.justpush_new_user();
  50. ```
  51. The request isn't signed, so keep your endpoint URL private.
The code

What runs when the webhook arrives

Studio calls handleRequest(request) with the incoming webhook and sends the message it returns. It's yours after install; change anything.

transform.js
1// Supabase → new Auth user (INSERT on auth.users)
2// Fires when someone signs up with Supabase Auth, via a database trigger on auth.users
3// that posts the Database Webhook payload (see INSTALL.md for the SQL).
4// Docs: https://supabase.com/docs/guides/database/webhooks
5
6// Sign-in providers, and how to name them.
7const PROVIDERS = {
8 email: "email",
9 phone: "phone",
10 google: "Google",
11 github: "GitHub",
12 apple: "Apple",
13 azure: "Microsoft",
14 facebook: "Facebook",
15 discord: "Discord",
16 twitter: "X (Twitter)",
17 gitlab: "GitLab",
18 bitbucket: "Bitbucket",
19 slack_oidc: "Slack",
20 linkedin_oidc: "LinkedIn",
21 spotify: "Spotify",
22 twitch: "Twitch",
23 notion: "Notion",
24 zoom: "Zoom",
25 figma: "Figma",
26 kakao: "Kakao",
27 keycloak: "Keycloak",
28 workos: "WorkOS",
29 sso: "SSO",
30}
31
32// Supabase sends plain strings; treat blanks as missing.
33function text(value) {
34 return typeof value === "string" && value.trim() ? value.trim() : null
35}
36
37function pick(table, key, fallback) {
38 return typeof key === "string" && Object.prototype.hasOwnProperty.call(table, key) ? table[key] : fallback
39}
40
41function handleRequest(request) {
42 const body = request.body && typeof request.body === "object" ? request.body : {}
43 const user = body.record
44
45 // Guard: only new rows in auth.users.
46 if (body.type !== "INSERT" || body.schema !== "auth" || body.table !== "users" || !user || typeof user !== "object") {
47 console.log(`Ignoring Supabase ${body.type ?? "unknown"} on ${body.schema ?? "?"}.${body.table ?? "?"}`)
48 return null
49 }
50
51 const meta = user.raw_user_meta_data && typeof user.raw_user_meta_data === "object" ? user.raw_user_meta_data : {}
52 const app = user.raw_app_meta_data && typeof user.raw_app_meta_data === "object" ? user.raw_app_meta_data : {}
53 const name = text(meta.full_name) ?? text(meta.name) ?? text(meta.user_name)
54 const contact = text(user.email) ?? text(user.phone)
55 const anonymous = user.is_anonymous === true || (!contact && !name)
56 const who = anonymous ? "An anonymous user" : name && contact ? `${name} (${contact})` : name || contact
57 const raw = text(app.provider)
58 const provider = raw ? pick(PROVIDERS, raw, raw) : null
59 // ?app=MyApp names your project in the title.
60 const project = text(request.query?.app)
61
62 return {
63 title: `👤 New ${project ? `${project} ` : ""}user`,
64 message: `${who} signed up` + (provider && !anonymous ? ` with ${provider}` : ""),
65 topic: "Supabase",
66 priority: -1, // Low — good news, nothing to do
67 }
68}
Payload

The Supabase INSERT webhook

This is what Supabase sends to your URL for insert on auth.users. It is a sample, trimmed to the fields recipes use.

INSERT · sample.json
1{
2 "type": "INSERT",
3 "table": "users",
4 "record": {
5 "id": "8f6a1c2e-0000-4000-8000-000000000001",
6 "email": "[email protected]",
7 "phone": null,
8 "created_at": "2026-09-29T09:20:31.118Z",
9 "raw_app_meta_data": {
10 "provider": "github",
11 "providers": [
12 "github"
13 ]
14 },
15 "raw_user_meta_data": {
16 "full_name": "Ada Lovelace",
17 "user_name": "ada"
18 }
19 },
20 "schema": "auth",
21 "old_record": null
22}
FAQ

Supabase new user notifications: questions

Does this work on iPhone and Android?

Yes. Install the JustPush app from the App Store or Google Play and sign in. Every phone signed in to your account gets the notification.

Do I need to write code?

No. Install the recipe in Studio, paste your webhook URL into Supabase and you are done. The code is there if you want to change the text, the sound or the buttons.

Can I change what the notification says?

Yes. After install the recipe's code is yours. Edit it in Studio and test it against the sample payload before you save.

What does it cost?

JustPush is free for 30 days. After that it's $19.99 a year, or $39.99 once. There is no extra charge for recipes.

Ready when you are

Supabase on your phone in two minutes.

Install the recipe, paste one URL, done. Free for 30 days, no credit card required.