Checked App Builder3 tables · 12 policies · 6 checks

    Lightweight CRM template for Lovable

    Companies, contacts and an append-only note timeline: shared team reads, owner-only writes. 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 Lightweight CRM kit?

    Without with check, the owner passes the first test and then writes a new owner_id, handing the record away. The kit checks ownership before and after the write.

    The mistake

    A record reassigned to someone else: the policy Lovable writes when nobody names the rule.

    The check that catches it

    verify.sql, check 4: Should FAIL or affect zero rows. You cannot reassign a record to yourself.

    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 Lightweight CRM 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 the whole team's contacts. This schema is deliberately shared.
    2Should SUCCEED, and owner_id should default to you without being supplied.
    3Should FAIL or affect zero rows. You cannot edit someone else's record.
    4Should FAIL or affect zero rows. You cannot reassign a record to yourself.catches the trap
    5Should FAIL. A note must be attributed to its actual author.
    6Confirm RLS is on for all three tables.
    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 that puts speed of entry first
    • A schema with companies, contacts, notes and a pipeline stage enum
    • Shared team reads with owner-only writes, and a with-check clause that blocks reassignment
    • A GIN full-text index so search works without a separate search service
    • Six verification queries, including one proving user B cannot steal user A's record

    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

      Decide shared or private before running schema.sql

      This schema is a shared team CRM: every authenticated user reads every record. For per-user isolation, change the select policies to owner_id = auth.uid() first.

    2. 02

      Run schema.sql in the Supabase SQL editor

    3. 03

      Run verify.sql as two different users

      Queries 3 and 4 only mean anything when run by someone who does not own the record.

    4. 04

      Paste prompt.md into Lovable

    Things that catch people out

    • owner_id defaults to auth.uid() in the schema, so the client never sends it. So ownership is derived on the server, and the browser never chooses it.
    • The with check clause on the update policies is the part people omit. Without it an owner can update their own row and set owner_id to somebody else, or a user can claim a record by rewriting the owner. Verification query 4 tests exactly that.
    • Shared reads are a deliberate default for a sales team. It is the one policy decision in these templates to confirm on purpose before running it.

    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 lightweight shared CRM for a small sales team, typically a founder doing their own sales, tracking companies, people and what was said. Speed of entry matters most, so common actions work from the keyboard.
    
    ## Core Features (Priority Order)
    1. Contact list from contacts, searched instantly over loaded rows by full_name, email and company, with a server query on full_name and email beyond the loaded page
    2. Contact detail with a note timeline from notes, newest first
    3. Add a note in two keystrokes (N, then Cmd+Enter), no modal
    4. Companies from companies, listing contacts through contacts.company_id
    5. Stage from pipeline_stage (new, contacted, qualified, proposal, won, lost), changed inline by the record's owner
    6. Owner shown on every record
    
    ## Visual Style & Design
    - Minimal and focused: dense list, roomy detail, keyboard hints
    - Split screen: contact list on the left, detail on the right; below md the list becomes cards
    - Geist for headings, Inter for body text
    - Colours: background #ffffff, text #111827, muted #6b7280, accent #7c3aed; one colour per stage, identical in list and detail
    - shadcn/ui Table, Command for search, Badge for stage, Avatar, Textarea for notes, Select for stage
    - Save these style keywords to the project knowledge.
    
    ## Signed In and Signed Out
    Signed-out visitors see sign-in only. Signed-in users see the whole team's records, with edit controls only on records they own.
    
    ## States
    - Empty: distinct messages for no contacts ("Add your first contact"), no search results and no notes
    - Loading: Skeleton rows in list and timeline
    - Error: a stage change updates optimistically and reverts with a toast; a failed note keeps its text with retry
    
    ## Data & Access
    - Tables companies, contacts and notes, the pipeline_stage type, the touch_updated_at trigger and every row-level security policy 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.
    - Every signed-in user reads every record; only the owner updates or deletes a company or contact, only the author a note.
    - The client never sends owner_id or author_id; defaults set them from auth.uid().
    
    ## Done When
    - A contact created without an owner field shows the signed-in user as owner
    - Signed in as a second account, the first account's contacts are visible with stage and edit controls disabled, and a forced stage update changes zero rows
    - A forced update setting owner_id on another user's contact changes zero rows
    - A note saves with the signed-in user as author and appears at the top of the timeline
    - Signed out, /contacts redirects to sign-in
    
    ## Build Order
    Sign-in and the contact list, detail and timeline, note creation with its failure path, companies, the inline stage change last.
    
    ## Safe-Guard Instructions
    - Notes stay append-only in the UI: no edit, bulk delete or reassignment controls
    - Ask me before opening sign-up beyond the team, because every signed-in account reads every record
    - No service role key in client code
    
    ## 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

    Companies, contacts, notes and policies

    -- Lightweight CRM schema for Lovable + Supabase
    -- Reviewed row-level security. Read the comments before running this.
    --
    -- Model choice worth understanding: this is a SHARED team CRM. Every authenticated user can
    -- read every record, because a sales team that cannot see each other's pipeline is not
    -- useful. Writes are restricted to the owner. If you need per-user isolation instead, change
    -- the select policies to owner_id = auth.uid() and re-run the verification queries.
    
    create type public.pipeline_stage as enum
      ('new', 'contacted', 'qualified', 'proposal', 'won', 'lost');
    
    create table public.companies (
    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 user A, then sign in as user B and repeat 3 and 4.
    
    -- 1. Should return the whole team's contacts. This schema is deliberately shared.
    select id, full_name, stage, owner_id from public.contacts limit 20;
    
    -- 2. Should SUCCEED, and owner_id should default to you without being supplied.
    insert into public.contacts (full_name, email) values ('Verify Person', 'v@example.com');
    select full_name, owner_id = auth.uid() as owned_by_me
    from public.contacts where email = 'v@example.com';
    
    -- As user B, against a contact owned by user A:
    
    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 Lightweight CRM kit?

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

    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 Lightweight CRM template for Lovable include?

    A build prompt that puts speed of entry first. A schema with companies, contacts, notes and a pipeline stage enum. Shared team reads with owner-only writes, and a with-check clause that blocks reassignment. A GIN full-text index so search works without a separate search service. Six verification queries, including one proving user B cannot steal user A's record.

    What mistake does the Lightweight CRM kit prevent?

    A record reassigned to someone else. Without with check, the owner passes the first test and then writes a new owner_id, handing the record away. The kit checks ownership before and after the write.

    How do I prove the Lightweight CRM policies work?

    Run verify.sql after schema.sql, as an ordinary signed-in user and never as service_role, which bypasses every policy. Check 4 is the one that catches the trap: Should FAIL or affect zero rows. You cannot reassign a record to yourself.

    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.