Supavoice gives any Supabase app a voice. It's one Edge Function in your project. Users ask and change things out loud, and it runs as the signed-in user, so the RLS policies you already wrote decide every row it can touch.
The whole front-end install
<script src="…/supavoice.js" data-supavoice data-url="https://<ref>.supabase.co" data-tables="todos" defer></script>
Supabase already turns your schema into two APIs: REST through PostgREST and GraphQL through pg_graphql. Supavoice reads the same schema and gives you the third.
Supavoice is one Edge Function in your project. Everything else it needs, your project already has.
supabase functions deploy voice
One command adds the Edge Function and generates your tools. Deploy it. Add one tag. Open source on GitHub, MIT licensed.
Run it in your Supabase project folder. It adds the voice Edge Function and turns your REST schema (OpenAPI) into narrow tools per table: list, add, update, delete. There is no SQL tool.
voice
npx github:rahulraina7/supavoice init
It runs in your Supabase project, next to your database. It checks the user's login itself.
supabase secrets set ANTHROPIC_API_KEY=… ELEVEN_LABS_KEY=… supabase functions deploy voice --no-verify-jwt
A floating mic appears for signed-in users. Name the tables it may use.
<script src="https://cdn.jsdelivr.net/gh/rahulraina7/supavoice@v0.1.0/widget/supavoice.js" data-supavoice data-url="https://<ref>.supabase.co" data-tables="todos" defer></script>
Every database call in a turn runs with the signed-in user's own token, so Postgres filters every row before the model sees it.
The user taps and speaks, or types.
ElevenLabs Scribe
Picks from the generated tools.
The user's own token, never a service key.
Returns only the rows this user may see.
ElevenLabs Flash
Writes wait for you. Add, update and delete hold until the user says "yes" or taps Confirm.
Owner columns come from the login. user_id and created_by are filled from the session, never by the model.
They're called RLS. Supavoice runs as the person talking, so even a fooled model can only ask. Postgres decides what comes back.
Each table gets list, add, update and delete. There is no tool that runs arbitrary queries.
Every call goes through supabase-js with the signed-in user's token.
Postgres decides what comes back. A prompt can change what the model asks for, not what the database returns.
Both demos are official examples from the supabase/supabase repo (Apache 2.0), with one script tag added.
The Slack demo updates live through Realtime while you talk to it.
The widget is one plain-JS script tag and the backend is a Supabase Edge Function, so your own backend language doesn't matter.
@supabase/ssr