shebang!

supabase-js examples

Two working sign-in paths against a sherbase database's Data API — embedded email/OTP, and the sherlock redirect flow.

supabase-js examples

Both examples point supabase-js at a database's Data API — createClient(api_url, publishable_key) — and differ only in how the user signs in.

Embedded — sign-in lives in your app

Your app's own end users sign up and sign in directly through supabase-js, never through the MCP server or the platform API. Two supported flows:

Email + password, confirmed with a 6-digit code sent by email:

import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  "https://api.shebang.pro/db/<slug>",
  "sb_publishable_<slug>_…",
);

await supabase.auth.signUp({ email, password });
await supabase.auth.verifyOtp({ email, token: "<6-digit code>", type: "signup" });

const { data, error } = await supabase.from("todos").select("*");

OTP-only sign-in, no password at all:

await supabase.auth.signInWithOtp({ email });
await supabase.auth.verifyOtp({ email, token: "<6-digit code>", type: "email" });

An already-registered user signs back in with supabase.auth.signInWithPassword({ email, password }) instead of signUp.

Redirect — sign-in lives in sherlock

Send the user through the OAuth 2.1 flow in sign in with sherlock (redirect), then pass the access_token you get back as a Bearer header when constructing the client, so row-level security sees the signed-in user:

import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  "https://api.shebang.pro/db/<slug>",
  "sb_publishable_<slug>_…",
  { global: { headers: { Authorization: `Bearer ${access_token}` } } },
);

const { data: inserted, error: insertErr } = await supabase
  .from("notes")
  .insert({ body: "hello from redirect login" })
  .select();

const { data: notes, error: selectErr } = await supabase
  .from("notes")
  .select("*")
  .order("id", { ascending: true });

Every row returned or written here is scoped by whatever row-level security policies the table has — the same notes table with the same policies behaves identically whether the signed-in user arrived through the embedded flow above or this redirect flow.

Next

Reload schema and rotate secret.