Lovable + Cradler

How to add a database to a Lovable app

A Lovable app already has a database — Lovable Cloud. The real question is when to bring your own. This guide explains how Lovable handles data today, the point at which an external backend earns its keep, and how to wire Cradler in so the same data is yours to reuse.

Short answer

Every Lovable project ships with Lovable Cloud, a managed Supabase backend, so you usually do not need to add a database at all to get started. You connect an external database when you want to read that data from outside Lovable, own it under your own account, or keep it portable. To do that without learning SQL, point your Lovable app at a Cradler project: install @cradler/sdk, and Cradler creates tables and columns automatically as your app saves data.

What Lovable already gives you

Lovable turns a chat prompt into a working React app, and since the launch of Lovable Cloud the backend is no longer an afterthought. Every project gets a fully managed Supabase instance — Postgres, authentication, file storage, and edge functions — provisioned and owned by Lovable. You never see it in a Supabase dashboard and you never touch a connection string. For a prototype, that is genuinely the fastest backend you can get.

So if you just asked Lovable to “save form submissions,” it probably already did, using Lovable Cloud. The honest advice: do not replace that while you are still figuring out the app. The reason to read further is not that Lovable Cloud is bad — it is that it is a closed box.

When you actually need your own backend

Lovable Cloud runs on a Supabase project that Lovable owns, not you. You do not get the service-role key or the database URL, and the project does not appear in your own Supabase account. That is fine until one of these is true:

  • A second app, a mobile client, an n8n workflow, or a scheduled job needs to read or write the same data.
  • You want the database under your own account and billing — so the backend survives even if you stop using Lovable.
  • You want a paper trail you control: your own backups, your own keys, your own export.

At that point you connect a backend you own. Lovable supports connecting your own Supabase project, which is the right call if you are comfortable writing schemas and Row Level Security policies in SQL. If you are not — if you came to Lovable precisely so you would not have to — Cradler is the backend designed for that gap.

Connecting Cradler to a Lovable app, step by step

Four steps. None of them involve SQL.

  1. 01

    Create a Cradler project

    Sign up at cradler.ai and create a project. Cradler provisions an isolated PostgreSQL database plus file storage and hands you a gateway URL, a project ID, an anon key, and a service key.

  2. 02

    Add @cradler/sdk to your Lovable code

    Open the GitHub repo Lovable syncs your project to, or edit in Lovable directly, and install @cradler/sdk. Put the gateway URL, project ID, and anon key in environment variables.

  3. 03

    Describe the data feature to Lovable in chat

    Ask Lovable in plain language to save and read your data through the Cradler client — for example, store waitlist sign-ups or load a list of testimonials.

  4. 04

    Publish — the schema fills itself in

    The first write creates the table; a later write with a new field adds the column. There is no migration step, and every Cradler database is backed up daily.

The code Lovable will write

Say you built a coaching landing page in Lovable and want to capture waitlist sign-ups in a database you own. You create one client, then insert and read with it. This is the whole integration:

import { createClient } from "@cradler/sdk";

const cradler = createClient({
  url: process.env.NEXT_PUBLIC_CRADLER_URL!,
  projectId: process.env.NEXT_PUBLIC_CRADLER_PROJECT_ID!,
  apiKey: process.env.NEXT_PUBLIC_CRADLER_ANON_KEY!,
});

// Save a waitlist sign-up. The "signups" table and its
// columns are created on this first call — no migration.
export async function joinWaitlist(email: string, plan: string) {
  await cradler.from("signups").insert({
    email,
    plan,
    source: "landing-page",
  });
}

// Read the latest sign-ups for an admin view.
export async function recentSignups() {
  const { rows } = await cradler
    .from("signups")
    .select("email", "plan", "createdAt")
    .order("createdAt", { desc: true })
    .limit(50);
  return rows;
}

Notice there is no CREATE TABLE anywhere. The first insert() tells Cradler a signups collection exists; it infers the column types from the values (text for the strings) and builds the table. If you later add cradler.from("signups").insert({ email, plan, referredBy }), Cradler runs an ADD COLUMN for referred_by on the fly. Camel case in your code maps to snake case in Postgres automatically.

Adding image uploads

If your Lovable app lets users upload a profile photo or a document, storage is part of the same Cradler project — no separate bucket, no second provider. Upload the file, then save its path in a row:

async function saveProfilePhoto(userId: string, file: File) {
  const path = `avatars/${userId}/${file.name}`;

  await cradler.storage.upload(path, file, {
    contentType: file.type,
  });

  await cradler
    .from("profiles")
    .update({ avatarPath: path })
    .eq("userId", userId);
}

// Later, get a signed URL to display it.
async function avatarUrl(path: string) {
  return cradler.storage.getUrl(path);
}

Gotchas worth knowing

The anon key is public.Anything in a client-side Lovable component ships to the browser, so use the anon key there and gate each table's read/insert/update/ delete permissions in the Cradler dashboard. Keep the service key, which bypasses those checks, only in server code.

Type conflicts are rejected, not coerced.If a column emerged as text and you later send a number for it, Cradler returns a clear error rather than silently corrupting the column. Lovable's AI reads that error and corrects the call — usually in the same chat turn.

Destructive changes are deliberate. Cradler adds tables and columns automatically but never renames or drops them on its own. Renaming a field or changing a type is a confirmed action in the dashboard, with a backup — so an off-hand prompt can never delete a column of real data.

Why Cradler suits Lovable builders

Lovable's whole pitch is that you describe an app and the AI builds it. A backend should hold to the same standard. Cradler ships a typed SDK, per-project generated TypeScript types, an llms.txt, and @cradler/mcp, an MCP server — so the AI generating your data code is working from your real schema, not a guess. And because the database is standard PostgreSQL, nothing about it is locked to Cradler if you ever want to take it elsewhere. See the @cradler/sdk package for the full API.

Frequently asked questions

Does a Lovable app already come with a database?

Yes. Every new Lovable project ships with Lovable Cloud, a managed Supabase backend that gives you a Postgres database, auth, and storage with no setup. You only need a separate backend when you want to read that data from outside Lovable, keep it under your own account, or move off Lovable later. In those cases you connect your own Supabase project or a backend like Cradler.

How do I add a database to a Lovable app without writing SQL?

Create a Cradler project, install @cradler/sdk, and tell Lovable in chat to save and read your data through the Cradler client. Cradler runs real PostgreSQL underneath but you never write SQL: it creates the table on the first insert and adds a column the first time you save a new field.

Lovable Cloud vs. connecting your own backend — which should I pick?

Use Lovable Cloud while you are prototyping; it is the fastest path and needs zero configuration. Switch to your own backend (your Supabase project or Cradler) once the data matters: when another app, a mobile client, or an automation needs the same database, when you want the project under your own account and billing, or when you want portability if you ever leave Lovable.

Where do uploaded images go in a Lovable app on Cradler?

Cradler includes file storage in the same project as the database. You upload with client.storage.upload() and the file is stored in object storage and served over a CDN. There is no separate bucket or storage provider to configure — one project covers data and files.

Will I lose my Lovable Cloud data if I move to Cradler?

No. Lovable Cloud data lives in a Postgres database; you can export it and insert it into a Cradler project, since Cradler is also PostgreSQL. Many builders run both for a while — Lovable Cloud for auth and Cradler for the application data they want to own and reuse — then consolidate once the app is stable.

Keep reading

Give your Lovable app a backend you own

Create a Cradler project and get a database, file storage, and API keys in seconds. Free to start — no credit card.