---
title: supabase-js examples
description: 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:

```js
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:

```js
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)](/sherlock/sign-in-with-sherlock-by-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:

```js
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](/sherbase/reload-schema-and-rotate-secret).
