Browse docs All docs
Docs / Add Supabase authentication to your app
Guidedeploymill://guides/auth/supabase

Add Supabase authentication to your app

You are an agent wiring Supabase Auth as the external identity provider for end-user login / accounts in a DeployMill-managed app. Read this together with the general deploymill://guides/auth reference (the four platform facts about auth on DeployMill still apply) and deploymill://guides/secrets (the secret hand-off).

DeployMill operates nothing here

This is bring-your-own auth. DeployMill does not run a user store, a login UI, or any token validation for you. What it does is small and explicit:

  • It records your choice in the auth block of .deploymill/project.json (provider-neutral config).
  • It hands off the Supabase values the normal way (set_env_vars / request_secret) so the agent never sees them.
  • On reconcile_project it runs a read-only presence-check that the expected env-var names are set on the app, and emits a typed auth_secret_missing hint (with this guide's URI) when they are not. It reads key names only, never the values.

Supabase holds your users and sessions. Your app talks to Supabase Auth with its client SDK. (This is distinct from using Supabase as your managed database, which is the database block. Here you are using Supabase only for user login.)

The env-var contract

Supabase Auth needs these env vars on the app:

  • SUPABASE_URL: your project URL (e.g. https://abcd1234.supabase.co). Not secret.
  • SUPABASE_ANON_KEY: the public anon/publishable key. Handle it as a secret via the hand-off so it isn't pasted into a transcript. (Do not put the service_role key in a browser-exposed context.)

These are the exact names the reconcile presence-check looks for. If either is missing, reconcile_project returns applied.auth.hint === "auth_secret_missing" with the missing name(s) in applied.auth.missingEnvKeys and a pointer to this guide.

The secret hand-off (agent never sees values)

  1. request_secret({ name: "SUPABASE_ANON_KEY" }) → hand the returned link to the user → poll secret_request_statusbind_secret({ applicationId, name: "SUPABASE_ANON_KEY" }) (or declare it under secrets in project.json and reconcile). The value is resolved server-side. It never appears in chat.
  2. set_env_vars({ applicationId, vars: { SUPABASE_URL: "https://<project>.supabase.co" } }). The project URL is not secret.

Add the app's prod host and every preview host to the Supabase Auth redirect-URL allow-list. See deploymill://guides/secrets for the full vault flow.

App-side SDK snippet

A minimal sketch using @supabase/supabase-js:

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

// Reads SUPABASE_URL + SUPABASE_ANON_KEY from the env DeployMill injected.
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!);

const { data, error } = await supabase.auth.signInWithPassword({ email, password });

(Use the matching Supabase SDK for your framework. The env-var names are the same.)

The auth project.json block

Declare the provider so reconcile records it and runs the presence-check:

{
  "version": 2,
  "auth": { "provider": "supabase", "audience": "users" }
}

audience is optional and only "users" today (end-user login). Then reconcile_project. If the keys are wired you get applied.auth.hint === null. If not, fix the missing names it reports and reconcile again.