Part of: Databases and apps on SharePoint data

A client portal on Supabase, fed from SharePoint lists

Tags: Relational databasesDesktopCommand line

SPSync replicates SharePoint lists into Supabase Postgres on a schedule. A lookup becomes a key column, a multi-value column becomes a child table, and deleted items stay with a flag. A web or mobile app then reads the tables through Supabase's generated API, and SharePoint is never called from the app. Each table is written in one transaction, so the app never sees half a load.

Book a call to talk through your use case, see further walkthroughs or demos, and set up a trial in your own environment.

Supabase gives an app a Postgres database, a generated REST API and Realtime, but it has no way to pull rows out of SharePoint. Whitfield Reyes LLP keeps its Client Register, Matters and Conflicts Register there, and wants a client portal built on that data. This walkthrough uses SPSync to replicate the three lists into the firm’s Supabase project and then builds on the tables with Supabase’s own tools.

Writing the portal against the SharePoint list API is the alternative, and it means paginated calls, lookups that come back as ids and queries on non-indexed columns that can fail once a list passes 5,000 items. A Power Automate flow can copy rows until Matter Team, a multi-value person column, changes shape. Without either, someone exports to a spreadsheet and loads it by hand.

SharePoint for editing, Supabase for the app

The firm keeps editing in SharePoint. The portal reads from Supabase. SPSync reads the lists once in full and then follows them with delta queries, writing to Supabase Postgres on a schedule, so the app never calls SharePoint. The tables come from the lists: lookups and people become key columns, multi-value columns become child tables. The destination is covered on the SharePoint to Supabase page, and the wider pattern in building web and mobile apps on data the business keeps in SharePoint.

Connecting through Supabase’s pooler

Install the desktop app, or SPSync in your Azure for a tenant-wide setup, and sign in as a user who already opens the three lists. Sign-in is delegated, so SPSync sees what that user sees, and the permissions wizard lets an admin read what Sites.Selected grants before approving it. SPSync never writes to SharePoint.

When you add the Supabase destination, copy the pooler host from the project’s Connect dialog. SPSync connects through the transaction pooler by default, and always with TLS. That default is ours. The shared pooler is reachable over IPv4 on every Supabase plan, and a sync run opens a connection, loads and disconnects. Supabase’s connection guide describes transaction mode for serverless and edge functions, session mode for persistent backends on IPv4-only networks, and the direct connection for migrations. A run through the transaction pooler on a live Supabase project has not been tested yet, so if the first run cannot connect, switch the destination to the session pooler or the direct connection. The direct connection is IPv6 only unless the project has Supabase’s IPv4 add-on, which the SharePoint to Supabase page covers with the other connection details. On the command line, sign-in is a device code with the token held in the OS keychain.

Matters, clients and fee earners as Postgres tables

Rows are keyed on their SharePoint item id. The Client lookup on Matters becomes client_id, pointing at sp_clients. Matter Team becomes sp_matters__matter_team, one row per fee earner per matter, in place of a delimited string. Relationship partners and fee earners all resolve to sp_users, so the portal joins people the same way everywhere. New SharePoint columns appear on the next run; columns removed in SharePoint stay in Postgres, so the portal keeps working. Key columns have no foreign key constraints, which keeps load order from failing a sync. Add constraints yourself once the schema settles, if your app relies on them.

The first sync, seen in the table editor

Trigger the first run. It reads everything, and each run after it reads only what changed. The events screen reports 150 clients, 500 matters and 350 conflicts register entries. A table is committed in one transaction when its read completes, so the portal sees the previous data or the complete new data. Open Supabase’s table editor and filter sp_matters to one client’s open matters as you would in a spreadsheet. Joining sp_matters.client_id to sp_clients.sp_item_id is a plain SQL query, which the list cannot run because it stores the client as a lookup id.

The portal on the generated API and Realtime

Supabase generates a REST API over the replicated tables, and it regenerates after any schema change a later run makes. A small web app lists a client’s open matters from that endpoint without a backend of its own. Realtime can subscribe to sp_matters and show a changed row once a run writes it. Row Level Security is yours to configure for the roles the app reads with: SPSync writes the tables with its own role and leaves policies to you. A Power BI or Metabase report can read the same tables if the partners want one.

Refreshing every five minutes

On a five-minute interval each run reads only the changes, so the portal trails SharePoint by a few minutes at most. A full reconcile runs every seven days by default and re-checks every item. You can also run one on demand to confirm the two sides agree, or after an outage such as your own server failing or a Microsoft 365 incident. The desktop app and SPSync in your Azure set the schedule from a picker; with the command line, spsync run does one run and your scheduler decides how often.

Edits and deletions

An edit arrives with the next delta run. A matter deleted in SharePoint is soft-deleted in Supabase, kept and flagged, so the app decides whether to hide it or show it as closed. If you want Supabase to drop deleted rows outright, the command-line tool can hard delete.

SPSync can also send the same lists to other destinations, one replication each, all listed on the destinations page. If yours is not there, tell us. Book a call to go through your own lists; a trial in your tenant can be arranged on the call.

Connect to SharePoint and sign in

What you see: A partner's delegated sign-in to the Whitfield Reyes LLP site, then the permissions wizard's one-page pack.

Why it matters: Client and matter data is read under a partner's existing permissions, which suits a firm that has to account for every copy of client data.

What it replaces: A broad Sites.Read.All grant that would expose every client site in the tenant.

  1. Open the desktop app, choose Connect a site and sign in with the account that already has access to Client Register, Matters and Conflicts Register.

  2. Review the permissions wizard's one-page pack before approving Sites.Selected access for the Whitfield Reyes LLP site.

Pick the lists and the Supabase destination

What you see: Client Register, Matters and Conflicts Register ticked together and pointed at the Supabase Postgres database.

Why it matters: One connection string covers all three lists, and SPSync creates and alters the tables itself, so nobody writes a schema by hand first.

What it replaces: A Power Automate flow per list that stops copying when Matter Team changes.

  1. Tick Client Register, Matters and Conflicts Register, name the replication and choose the Supabase destination.

  2. Add the destination with the pooler host from your Supabase project's Connect dialog. SPSync uses the transaction pooler unless you choose the session pooler or the direct connection.

Run the first sync

What you see: 150 clients, 500 matters and 350 conflicts register entries written, broken out by list on the run's own events screen.

Why it matters: A matter opened in SharePoint reaches the portal on the next five-minute run, with no full reload of the lists.

What it replaces: A spreadsheet export loaded into Postgres by hand.

  1. Click Save and run, open the run's own events and watch the per-list row counts arrive: 150 clients, 500 matters, 350 conflicts register entries.

  2. Set the schedule to five minutes so the three-list replication checks for changes twelve times an hour.

See the result: lookups, child tables and joins

What you see: sp_matters joined to sp_clients in a SQL query, and the Matter Team column arriving as its own child table.

Why it matters: The portal needs each matter with its client and fee earners, and Postgres can serve that in one query.

What it replaces: Lookup ids resolved one call at a time against the SharePoint list API.

  1. Open the destination database and browse sp_clients, sp_matters and sp_conflicts_register; each keeps the SharePoint item id as its key.

  2. Run a join between sp_matters and sp_clients on client_id, something no SharePoint list view answers directly.

Use the replica: table editor, auto API and Realtime

What you see: Supabase's table editor on the replicated tables, a small web app reading sp_matters through the auto-generated REST API, and a Realtime subscription on the same table.

Why it matters: App developers work with the Supabase tools they already know, and SharePoint throttling never reaches the portal.

What it replaces: A client portal built straight on the SharePoint list API, with paginated calls and opaque lookup ids.

  1. Open sp_matters in Supabase's table editor and filter it to open matters for one client, the way you would in a spreadsheet.

  2. Point a small web app at Supabase's auto-generated REST API for sp_matters, and subscribe to the table with Realtime.

Set it up

Signing in and connecting are covered in the SharePoint connection guide. For the database side, follow the PostgreSQL setup guide. If a connection test fails, see troubleshooting.

What you get

We'll set it up with you on the call: your use case, further walkthroughs or demos, and a trial in your own environment.

Frequently asked questions

How do you replicate a SharePoint list to Supabase?

Sign in to SharePoint with delegated access or an admin-granted Sites.Selected app permission, choose the site and lists, and give SPSync the connection details from your Supabase project's Connect dialog. SPSync builds the tables and refreshes them on a schedule.

Does SPSync connect through Supabase's connection pooler?

Yes, through the transaction pooler by default. That is SPSync's choice: the shared pooler works over IPv4 on every Supabase plan, and a sync run is a short connect, load and disconnect job. Supabase's own guide describes transaction mode for serverless functions and sends migrations to the direct connection. A run through the transaction pooler on a live Supabase project has not been tested yet. If the first run cannot connect, switch to the session pooler or the direct connection.

How do Matter Team and the Client lookup appear in Supabase?

The Client lookup becomes client_id on sp_matters, joining to sp_clients. Matter Team, a multi-value person column, becomes sp_matters__matter_team with one row per fee earner, and each person resolves to a single row in sp_users.

Can an app use Supabase's auto-generated API on the replicated tables?

Yes. Once the tables exist, Supabase's generated REST and Realtime APIs work against them the same way they would against any other Postgres table.

Does SPSync manage Row Level Security policies?

No. SPSync replicates the tables and connects with a role that can write them. Writing and managing Row Level Security policies for the roles your app reads with stays with you, the same as on any other Postgres table.

Will a matter deleted in SharePoint vanish from the portal?

Only if the app filters it out. A deleted matter stays in sp_matters with a deleted flag, so the portal can hide it or show it as closed. Edits arrive with the next delta run, and the command-line tool can hard delete instead if you prefer.

What we covered

Compared with

Book a call to talk through your use case, see further walkthroughs or demos, and set up a trial in your own environment. No obligation.