Checked SaaS App4 tables · 12 policies · 6 checks

    SaaS Starter template for Lovable

    Multi-tenant workspaces, three roles and a working invite flow, with tenancy enforced in the database. The kit is three files: a build prompt for Lovable, a Supabase schema with row-level security, and verification queries that run as the wrong user to prove each policy denies what it should. The prompt is free; the full SQL comes with the bundle.

    By Marco Kohns · Stack: React + Vite, TypeScript, Tailwind CSS, shadcn/ui, Supabase

    The trap

    What goes wrong without the SaaS Starter kit?

    Letting members update their own membership row also lets them rewrite its role. The kit allows the update only when the caller is an owner or admin of that workspace.

    The mistake

    A member promoting themselves to owner: the policy Lovable writes when nobody names the rule.

    The check that catches it

    verify.sql, check 3: Should FAIL for a member (non-admin). If it succeeds, the write policy is too loose.

    The policies that prevent it are in the kit's schema.sql, which ships with the bundle; the hub shows one pattern per kit.

    verify.sql

    How do you prove the SaaS Starter policies work?

    Run every check as an ordinary signed-in user, never as service_role, which bypasses every policy and makes a broken schema look correct.

    The verification checks in the kit's verify.sql, as written in its comments
    #Expected result
    1Should return only workspaces you are a member of, never every workspace.
    2Should return zero rows for a workspace you do not belong to. Substitute a workspace id you are NOT a member of.
    3Should FAIL for a member (non-admin). If it succeeds, the write policy is too loose.catches the trap
    4Should FAIL. Nobody may read another workspace's invites.
    5Should FAIL with 'invite is invalid, expired, or already used'.
    6Confirm RLS is on. Every row must show rowsecurity = true.
    Lovable's Security view with the Deep security scan and Quick security scan cards and a No issues found panel, beside the chat reporting a clean scan
    Lovable's free scans on my SaaS project, 26 September 2026. A clean scan says row-level security is switched on; verify.sql shows what the policies deny.

    What is in the kit?

    • A build prompt with numbered priority, a named style direction, states, Done When checks, an explicit build order and safeguards
    • A Supabase schema: profiles, workspaces, workspace_members and workspace_invites
    • Row-level security on every table, deny by default, with owner, admin and member roles
    • Two SECURITY DEFINER helpers that avoid the recursive-policy trap on a membership table
    • An invite acceptance function, because the invitee cannot select the row they are accepting
    • Six verification queries that prove a member cannot promote themselves to owner

    What the kit does not do

    • Not a pre-built app you clone and run. There is no repository and no node_modules.
    • Not a design file or a theme. Lovable generates the interface from the prompt.
    • Not a substitute for reading the SQL. You are running it against your own database.

    Setup

    In what order do you set up the kit?

    Schema before prompt, because the prompt references the table names the schema creates.

    1. 01

      Run schema.sql in the Supabase SQL editor

      Before prompting Lovable. The prompt references these table names, so building first means rework.

    2. 02

      Run verify.sql as an ordinary signed-in user

      Not as service_role, which bypasses every policy and will make a broken schema look correct.

    3. 03

      Paste prompt.md into Lovable

      Unedited on the first pass, so you can see what the structure produces before changing it.

    4. 04

      Replace the audience line

      The Context section names a small team adopting a tool. Changing that one line changes which features Lovable prioritises more than anything else in the prompt.

    Things that catch people out

    • The trigger that makes a workspace creator an owner is load-bearing. Without it the creator cannot read the workspace they created, because the read policy requires membership. This is the most common way this schema appears broken when it is not.
    • The invite table has no anonymous read policy on purpose. Anyone who can select from it can enumerate pending invite tokens for every workspace.
    • Lovable will sometimes generate a client-side role check and nothing else. With the policies here, a missing UI check stays a cosmetic bug and the data stays protected.

    The files

    What do the kit files contain?

    The build prompt in full, and the first 12 lines of each SQL file so you can judge the code before you run it anywhere.

    The build prompt

    # Context
    Build a multi-tenant SaaS app where users belong to workspaces, each with its own members, roles and plan. Small teams adopt it together, so the first flow that must work is an owner inviting a colleague into the same workspace.
    
    ## Core Features (Priority Order)
    1. Email and password sign-in, session kept across refresh
    2. Workspace creation on first sign-in: insert into workspaces with created_by as the current user; the workspaces_add_owner trigger adds the owner membership
    3. Member list from workspace_members joined to profiles, showing each workspace_role: owner, admin or member
    4. Invites: owner and admin insert a workspace_invites row (invited_by as the current user) and copy the link /invite/[token]; opening it calls accept_workspace_invite and opens the returned workspace
    5. Role-gated controls via workspace_role_of: owner and admin change roles and remove members; only the owner renames the workspace
    6. Plan badge from workspaces.plan with an "Upgrade" button to a placeholder page
    
    ## Visual Style & Design
    - Corporate and professional: clear hierarchy, restrained colour, 8px radius
    - Sidebar layout: workspace switcher and navigation on the left, content on the right
    - Manrope for headings, Inter for body text
    - Colours: background #f8fafc, text #0f172a, muted #64748b, accent #2563eb for primary actions only
    - shadcn/ui Table for members, Badge for role and plan, Avatar, Dialog for the invite, DropdownMenu for role changes
    - Save these style keywords to the project knowledge.
    
    ## Signed In and Signed Out
    Signed-out visitors see sign-in and sign-up; an invite link survives sign-in. Signed-in users see their workspace.
    
    ## States
    - Empty: a workspace with one member shows "Invite your first teammate" next to the invite button
    - Loading: Skeleton rows for the member list
    - Error: a bad token shows "This invite is invalid, expired, or already used"; a denied write shows an inline message with retry
    
    ## Data & Access
    - Tables profiles, workspaces, workspace_members and workspace_invites, their row-level security policies and functions already exist in the connected Supabase project from schema.sql. Never weaken, drop or bypass them or create tables; if something is missing, stop and ask me.
    - Everything runs as the signed-in user; invites are accepted only through accept_workspace_invite.
    - Role comes from the database, never client state. No policy revokes invites; ask me before adding one.
    
    ## Done When
    - A second account opens an invite link, signs in and appears in the owner's member list with the invited role
    - Signed in as a member, role controls are hidden and a forced role change on workspace_members is rejected
    - Reusing an accepted invite link shows the invalid-invite error
    - Another workspace's id in the URL shows a not-found screen
    - Signed out, /dashboard redirects to sign-in
    
    ## Build Order
    Sign-in and protected routes, a role helper around workspace_role_of, workspace and member reads, invites with the accept route, the plan badge last.
    
    ## Safe-Guard Instructions
    - Keep the invite flow unchanged on later edits
    - No service role key in client code
    - The browser never writes workspaces.plan; billing sets it later
    
    ## Before Building
    Ask me any questions you need in order to fully understand what I want from this feature and how I envision it. Save my answers to the project knowledge so later prompts build on them.

    schema.sql

    Preview · full file in the bundle

    Tables, policies and functions

    -- SaaS starter schema for Lovable + Supabase
    -- Reviewed row-level security. Read the comments before running this.
    --
    -- The recursive-policy trap: a policy on workspace_members that itself queries
    -- workspace_members causes infinite recursion. The is_workspace_member() function below is
    -- SECURITY DEFINER specifically to break that cycle. Do not inline it into a policy.
    
    create type public.workspace_role as enum ('owner', 'admin', 'member');
    
    create table public.profiles (
      id uuid primary key references auth.users (id) on delete cascade,
      full_name text,
    The rest of schema.sql, every policy written and its denials verified, is in The Complete Lovable Bundle.Get the Bundle

    verify.sql

    Preview · full file in the bundle

    Policy verification queries

    -- Verification queries. Run these as an ordinary signed-in user, not as service_role.
    -- Every one of them must behave as described or a policy is wrong.
    
    -- 1. Should return only workspaces you are a member of, never every workspace.
    select id, name, plan from public.workspaces;
    
    -- 2. Should return zero rows for a workspace you do not belong to.
    --    Substitute a workspace id you are NOT a member of.
    select * from public.workspace_members
    where workspace_id = '00000000-0000-0000-0000-000000000000';
    
    -- 3. Should FAIL for a member (non-admin). If it succeeds, the write policy is too loose.
    The rest of verify.sql, every policy written and its denials verified, is in The Complete Lovable Bundle.Get the Bundle

    After the kit

    Which library prompts build on the SaaS Starter kit?

    Each extends the kit's tables with one feature, keeps its policies, and ends with Done When checks Lovable can verify.

    • SaaS MVP with User Auth

      A multi-tenant SaaS foundation with email auth, a workspace per sign-up, owner, admin and member roles, and tokenized invite links that handle expired tokens.

    • Subscription Checkout Flow

      Adds Stripe subscriptions to an existing app, with a signed, idempotent webhook as the only writer of subscription status and a success page that grants no access by itself.

    • Product Roadmap Planner

      A roadmap board with four stage columns, card order persisted in the database, and a dated public changelog entry each time a card moves to Shipped.

    • Payment History & Billing Pages

      A customer billing area that reads invoices from Stripe on every request, shows proration before any plan change, and looks up the customer from the signed-in user.

    • Lead Scoring System

      Rules-based lead scoring where every point traces to a named rule with a timestamp, replayed events never score twice, and reps work a ranked queue.

    • SaaS Teams & Permissions Manager

      Team management for an existing multi-tenant app where every role change, removal and ownership transfer re-checks the actor's role in the database and writes a log row.

    The full SQL for all 4 kits

    The Complete Lovable Bundle: every schema.sql and verify.sql, every Pro prompt, unlimited generation. One payment. No subscription, no renewal, ever.

    Disclosure: if you create a Lovable account through links on this page, we may earn a commission. It costs you nothing and does not change what we recommend. Create a free Lovable account

    Frequently asked

    What does the SaaS Starter template for Lovable include?

    A build prompt with numbered priority, a named style direction, states, Done When checks, an explicit build order and safeguards. A Supabase schema: profiles, workspaces, workspace_members and workspace_invites. Row-level security on every table, deny by default, with owner, admin and member roles. Two SECURITY DEFINER helpers that avoid the recursive-policy trap on a membership table. An invite acceptance function, because the invitee cannot select the row they are accepting. Six verification queries that prove a member cannot promote themselves to owner.

    What mistake does the SaaS Starter kit prevent?

    A member promoting themselves to owner. Letting members update their own membership row also lets them rewrite its role. The kit allows the update only when the caller is an owner or admin of that workspace.

    How do I prove the SaaS Starter policies work?

    Run verify.sql after schema.sql, as an ordinary signed-in user and never as service_role, which bypasses every policy. Check 3 is the one that catches the trap: Should FAIL for a member (non-admin). If it succeeds, the write policy is too loose.

    What we did not publish

    • A Lovable credit cost for this kit. The SQL was validated against Postgres 17; the kit was not built end to end in Lovable for this page.
    • The SQL in full; it is what the bundle sells.
    • The mistake SQL is an illustration written for this page; the kit SQL beside it is quoted from schema.sql.

    These templates are provided free and as-is, with no warranty of any kind. The SQL is intended to be run against your own Supabase project and will create and alter tables. Read it, run it on a development project first, and review every policy against your own requirements before going near production data. You remain responsible for the security and correctness of anything you ship. These schemas assume Supabase, which grants the anon and authenticated roles access to new tables in the public schema by default. Row-level security is what then restricts those roles. If you run this SQL on a plain Postgres instance instead, those grants do not exist, so the policies appear to work while the missing privileges are what blocks access, and a test there proves nothing about the policies.

    Other kits

    Checks parsed from the kit files; page checked 23 October 2026.

    Written by

    Marco Kohns

    Marco Kohns

    Founder of ProtoBites - Venture Growth Studio

    Growth PM at a Silicon Valley scale-up (a16z and General Catalyst backed), ex-Techstars where he consulted 13 early-stage startups, Reforge-trained. Every prompt on this site comes out of shipping ProtoBites' own portfolio products.