1Supabase Project
2Create Tables
3Configure App
4Test Connection
5Go Live

1Set Up Your Supabase Project

Log into Supabase and get your project URL and anon key. This takes about 3 minutes.

You already have a Supabase account — great! Just create a new project for Agent Builder.

Steps in the Supabase Dashboard

  • Go to supabase.com and log in to your account
  • Click New Project → name it supportbot-prod
  • Set a strong database password and choose a region close to your users
  • Wait ~2 minutes for the project to provision
  • Go to Project Settings → API and copy your Project URL and anon public key

Where to find your credentials

Supabase Dashboard Settings → API → Project API keys
Project URL  →  https://xxxxxxxxxxx.supabase.co
anon key     →  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

⚠️  Use the "anon" key (public) — NOT the "service_role" key
    The anon key is safe to use in browser JavaScript.
Never use the service_role key in frontend code — it bypasses Row Level Security and has full DB access. Only the anon key is safe for the browser.

2Create All 9 Tables in Supabase

Run this SQL in the Supabase SQL Editor to create all tables that Agent Builder needs. This creates all columns, indexes, and enables Row Level Security.

In your Supabase dashboard, go to SQL Editor (left sidebar) → click New Query → paste the SQL below → click Run.

Tables that will be created

sb_accounts id, name, slug, created_at RLS ON
sb_users id, account_id, name, email, password, role, active RLS ON
sb_superadmins id, name, email, password, active RLS ON
chatbot_flows id, account_id, name, nodes(jsonb), status, … RLS ON
flow_categories id, account_id, name, color, icon, … RLS ON
conversations id, account_id, flow_id, outcome, path(jsonb), … RLS ON
chatbot_settings id, account_id, welcome_headline, public_bot, … RLS ON
kb_articles id, account_id, title, content(jsonb), status, … RLS ON
api_integrations id, account_id, name, endpoints(jsonb), … RLS ON

SQL — Run this entire block in Supabase SQL Editor

SQL
-- ============================================================
--  Agent Builder — Supabase Table Creation Script
--  Run in: Supabase Dashboard → SQL Editor → New Query → Run
-- ============================================================

-- 1. ACCOUNTS
create table if not exists sb_accounts (
  id          text primary key,
  name        text not null,
  slug        text unique,
  created_at  bigint default extract(epoch from now())*1000
);

-- 2. USERS
create table if not exists sb_users (
  id          text primary key,
  account_id  text references sb_accounts(id) on delete cascade,
  name        text,
  email       text unique,
  password    text,
  role        text check (role in ('owner','admin','agent')),
  active      boolean default true
);

-- 3. SUPERADMINS
create table if not exists sb_superadmins (
  id          text primary key,
  name        text,
  email       text unique,
  password    text,
  active      boolean default true
);

-- 4. FLOW CATEGORIES
create table if not exists flow_categories (
  id               text primary key,
  account_id       text references sb_accounts(id) on delete cascade,
  name             text,
  description      text,
  icon             text,
  color            text,
  sort_order       integer default 0,
  starting_flow_id text,
  created_at       bigint default extract(epoch from now())*1000
);

-- 5. CHATBOT FLOWS
create table if not exists chatbot_flows (
  id            text primary key,
  account_id    text references sb_accounts(id) on delete cascade,
  name          text,
  description   text,
  category      text,
  category_id   text references flow_categories(id) on delete set null,
  nodes         jsonb default '[]'::jsonb,
  start_node_id text,
  status        text default 'draft',
  color         text default '#6366f1',
  steps_count   integer default 0,
  created_at    bigint default extract(epoch from now())*1000,
  updated_at    bigint default extract(epoch from now())*1000
);

-- 6. CONVERSATIONS
create table if not exists conversations (
  id          text primary key,
  account_id  text references sb_accounts(id) on delete cascade,
  agent_id    text,
  agent_name  text,
  flow_id     text,
  flow_name   text,
  started_at  bigint,
  ended_at    bigint,
  duration_ms bigint default 0,
  outcome     text default 'incomplete',
  steps_count integer default 0,
  path        jsonb default '[]'::jsonb,
  variables   jsonb default '{}'::jsonb,
  simulator   text,
  created_at  bigint default extract(epoch from now())*1000
);

-- 7. CHATBOT SETTINGS
create table if not exists chatbot_settings (
  id               text primary key,
  account_id       text unique references sb_accounts(id) on delete cascade,
  welcome_headline text default 'How can we help?',
  welcome_subtitle text default 'Choose a category below.',
  welcome_tagline  text default '',
  public_bot       boolean default false,
  default_flow_id  text default ''
);

-- 8. KB ARTICLES
create table if not exists kb_articles (
  id            text primary key,
  account_id    text references sb_accounts(id) on delete cascade,
  title         text,
  slug          text,
  category      text,
  content       jsonb,
  excerpt       text,
  tags          text,
  status        text default 'draft',
  linked_flow_id text default '',
  helpful_yes   integer default 0,
  helpful_no    integer default 0,
  view_count    integer default 0,
  created_at    bigint default extract(epoch from now())*1000,
  updated_at    bigint default extract(epoch from now())*1000
);

-- 9. API INTEGRATIONS (legacy — kept for migration compatibility)
create table if not exists api_integrations (
  id               text primary key,
  account_id       text references sb_accounts(id) on delete cascade,
  name             text,
  description      text,
  base_url         text,
  auth_type        text default 'none',
  auth_header      text,
  auth_value       text,
  default_headers  text,
  endpoints        jsonb default '[]'::jsonb,
  icon             text default '🔌',
  color            text default '#6366f1',
  status           text default 'active',
  last_tested_at   bigint,
  last_test_status text default 'untested',
  created_at       bigint default extract(epoch from now())*1000
);

-- 10. PLATFORM SETTINGS (global — one row, id = 'global')
create table if not exists platform_settings (
  id                  text primary key default 'global',
  openrouter_api_key  text default '',
  openrouter_model    text default 'openai/gpt-4o-mini',
  updated_at          bigint default extract(epoch from now())*1000
);

-- 11. API COLLECTIONS (MCP Collection manager — replaces api_integrations)
create table if not exists api_collections (
  id          text primary key,
  account_id  text references sb_accounts(id) on delete cascade,
  name        text not null,
  description text default '',
  base_url    text default '',
  auth_type   text default 'none',
  auth_key    text default '',
  auth_value  text default '',
  icon        text default '🔌',
  color       text default '#6366f1',
  sort_order  integer default 0,
  created_at  bigint default extract(epoch from now())*1000
);

-- 12. API REQUESTS (child of api_collections)
create table if not exists api_requests (
  id             text primary key,
  account_id     text references sb_accounts(id) on delete cascade,
  collection_id  text references api_collections(id) on delete cascade,
  name           text default 'New Request',
  method         text default 'GET',
  path           text default '/',
  headers        text default '[]',
  params         text default '[]',
  body           text default '',
  auth_override  text default null,
  purpose        text default '',
  outcome_map    text default '[]',
  last_response  text default '',
  mcp_tool_def   text default '',
  sort_order     integer default 0,
  created_at     bigint default extract(epoch from now())*1000,
  updated_at     bigint default extract(epoch from now())*1000
);

-- ============================================================
--  INDEXES for performance
-- ============================================================
create index if not exists idx_users_account    on sb_users(account_id);
create index if not exists idx_users_email      on sb_users(email);
create index if not exists idx_flows_account    on chatbot_flows(account_id);
create index if not exists idx_flows_cat        on chatbot_flows(category_id);
create index if not exists idx_cats_account     on flow_categories(account_id);
create index if not exists idx_convs_account    on conversations(account_id);
create index if not exists idx_convs_agent      on conversations(agent_id);
create index if not exists idx_kb_account       on kb_articles(account_id);
create index if not exists idx_api_account      on api_integrations(account_id);
create index if not exists idx_api_col_account  on api_collections(account_id);
create index if not exists idx_api_req_col      on api_requests(collection_id);
create index if not exists idx_api_req_account  on api_requests(account_id);

-- ============================================================
--  ROW LEVEL SECURITY — allow anon key full access
--  (Your app handles auth in JS — Supabase just stores data)
-- ============================================================
alter table sb_accounts        enable row level security;
alter table sb_users           enable row level security;
alter table sb_superadmins     enable row level security;
alter table flow_categories    enable row level security;
alter table chatbot_flows      enable row level security;
alter table conversations      enable row level security;
alter table chatbot_settings   enable row level security;
alter table kb_articles        enable row level security;
alter table api_integrations   enable row level security;
alter table platform_settings  enable row level security;
alter table api_collections    enable row level security;
alter table api_requests       enable row level security;

-- Grant anon role full CRUD access
-- NOTE: CREATE POLICY does not support IF NOT EXISTS in PostgreSQL.
-- We use DROP IF EXISTS first, then CREATE — safe to re-run.
drop policy if exists "anon_all" on sb_accounts;
create policy "anon_all" on sb_accounts
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on sb_users;
create policy "anon_all" on sb_users
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on sb_superadmins;
create policy "anon_all" on sb_superadmins
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on flow_categories;
create policy "anon_all" on flow_categories
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on chatbot_flows;
create policy "anon_all" on chatbot_flows
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on conversations;
create policy "anon_all" on conversations
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on chatbot_settings;
create policy "anon_all" on chatbot_settings
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on kb_articles;
create policy "anon_all" on kb_articles
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on api_integrations;
create policy "anon_all" on api_integrations
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on platform_settings;
create policy "anon_all" on platform_settings
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on api_collections;
create policy "anon_all" on api_collections
  for all to anon using (true) with check (true);

drop policy if exists "anon_all" on api_requests;
create policy "anon_all" on api_requests
  for all to anon using (true) with check (true);

-- ============================================================
--  Done! All 12 tables ready.
-- ============================================================
select 'Agent Builder tables created successfully!' as status;
After running, you'll see Agent Builder tables created successfully! in the output panel. If you see any errors, make sure you're running as the database owner (default in Supabase).

3Configure Your App

Enter your Supabase credentials below. This generates the js/sb-config.js file content you need to paste into your project.

4Test Your Supabase Connection

Enter your credentials and run a live connection test directly from this page to verify everything is set up correctly.

What the test checks

Network reachabilityCan we reach your Supabase project URL?
Anon key validityIs the Authorization header accepted?
Table existenceDoes sb_accounts table exist and respond?
RLS policyCan anon key read data (policy allows it)?

5Deploy & Go Live

Final checklist before you publish. Once all items are checked, your Agent Builder will be running on Supabase in production.

  • ✅ Ran the SQL in Supabase — all 12 tables created (check in Table Editor)
  • ✅ Updated js/sb-config.js with your real Supabase URL and anon key
  • ✅ Replaced sb-storage-v2.jssb-storage-supabase.js in all HTML files
  • ✅ Added Supabase CDN script tag before other scripts in all HTML files
  • ✅ Connection test in Step 4 passed with green ✓
  • ✅ Logged in to Agent Builder — demo data seeded automatically on first login
  • ✅ Published via the Genspark Publish tab

What happens on first login after migration

Auto-seeding works exactly the same:
SBAuth.seedDemoIfEmpty() runs on every page load. On first use with an empty Supabase DB, it will automatically create the superadmin account, demo company, demo users, and all sample flows — just like the Genspark version.

Supabase Free Tier Limits

Storage500 MB — enough for ~1M rowsFree
API RequestsUnlimited — no request quotaFree
Bandwidth2 GB/month egressFree
Inactivity pauseProject pauses after 7 days inactivityWatch out
Free tier pauses after 7 days of inactivity. For always-on production, upgrade to the $25/month Pro plan — it removes the pause and increases limits significantly.
🎉

You're Ready to Go Live!

Your Agent Builder is now backed by Supabase PostgreSQL — a production-grade, scalable database that will grow with your business.