Skip to content
GitHub
Get started →

Supabase adapter

The Supabase adapter uses the @supabase/supabase-js client and talks to your project over PostgREST. This is the recommended path if you use Supabase — it respects your Row Level Security policies.

Alternatively you can use the Postgres adapter pointed at Supabase’s direct Postgres connection string. Pick based on preference:

PathNotes
Supabase adapter (this page)Uses PostgREST. RLS applies. Uses anon or service key.
Postgres adapterUses raw Postgres. RLS does not apply. Uses a DB user.

Config shape

{
"type": "supabase",
"config": {
"url": "https://abcdefghi.supabase.co",
"key": "${SUPABASE_ANON_KEY}"
},
"collections": {
"menu_items": {
"source": "menu_items",
"searchable_fields": ["name", "description"],
"filterable_fields": ["category", "price", "vegan"],
"display_fields": ["id", "name", "price", "category"]
}
}
}

Setup

  1. Pick an API key

    Supabase has two keys:

    • anon — respects RLS. Recommended. Make sure you have a read-only RLS policy for the tables Spelo needs.
    • service_role — bypasses RLS. Only use if you understand the implications.

    Find them in Project SettingsAPI.

  2. Write an RLS policy (if using the anon key)

    Example — public read on menu_items:

    ALTER TABLE menu_items ENABLE ROW LEVEL SECURITY;
    CREATE POLICY "Public read menu" ON menu_items
    FOR SELECT
    USING (true);

    For per-tenant data, scope by a claim in the JWT. Spelo’s anon key request can be further filtered by your RLS.

  3. Paste URL + key in the dashboard

    Dashboard → DataSupabase → paste → Test connection.

  4. Map collections — the source is the table name (case-sensitive, schema-qualified as schema.table if needed).

Operator translation

SearchParams operatorPostgREST chain
eq.eq(field, value)
neq.neq(field, value)
gt / gte / lt / lte.gt/.gte/.lt/.lte(field, value)
contains (array column).contains(field, [value])
contains (text column).ilike(field, '%value%')
in.in(field, values)
free-text query.or('a.ilike.%q%,b.ilike.%q%,...') over searchable_fields

Security notes

  • Values in the .or() expression are escaped so commas and parentheses can’t break out of the PostgREST expression.
  • The adapter never uses .upsert, .update, .delete, or .rpc. Read-only by construction.

Supabase Edge Functions

If you host bespoke query logic in a Supabase Edge Function, point the REST adapter or Webhook adapter at the function URL instead.

Troubleshooting

  • JWSError → invalid key. Copy-paste again from Project SettingsAPI.
  • Empty results with no error → your RLS policy is denying the read. Log in to the Supabase SQL editor as anon and run SELECT * FROM your_table — if it’s empty, the policy is the issue.
  • PGRST116 (too many rows) → you asked for more rows than PostgREST’s limit. Spelo caps max_limit at 10 so this shouldn’t happen, but check for misconfig.

More: Database connection errors.