How v0 thinks about databases
v0 started as a UI generator and, through 2025 and into 2026, grew into something closer to a full app builder — a VS Code-style editor, Git integration, agentic workflows, and database connectivity. The way v0 handles data is deliberately open: it does not run a database itself. Instead it offers a marketplace of integrations.
Connect one from the chat sidebar — or just ask v0 to add a database — and v0 provisions an account on that provider and injects the environment variables. The current lineup includes Neon, Supabase, Upstash, Vercel Blob, and, since early 2026, Amazon Aurora and DynamoDB. That openness is a strength — but it also means the database decision, and the administration that comes with it, is still yours.
What each option actually asks of you
The marketplace options are all capable, and they are all real databases with real surface area:
- Neon gives you serverless Postgres — fast to start, but you design the schema and run migrations yourself.
- Supabase adds auth and storage, and expects Row Level Security policies written in SQL to keep data safe on a public anon key.
- Aurora and DynamoDB are production-grade AWS services — and they assume you know AWS.
- Vercel Blob covers files, but it is a separate integration from whatever holds your data.
If you are an engineer, that is a fine menu. If you came to v0 to skip the engineering, every one of those still hands you a database to administer. That is the specific gap Cradler is built for.
Connecting Cradler to a v0 app, step by step
You use v0's own Vars panel — the same place every integration lives.
- 01
Create a Cradler project
Sign up at cradler.ai and create a project. You get an isolated PostgreSQL database, file storage, a gateway URL, a project ID, an anon key, and a service key.
- 02
Add your keys to v0's Vars panel
In your v0 chat, open the Vars panel in the sidebar and add the Cradler gateway URL, project ID, and anon key as environment variables — the same panel v0 uses for any integration.
- 03
Install @cradler/sdk and prompt v0
Tell v0 to install @cradler/sdk and create a Cradler client, then ask it to read and write your data in plain language — for example, persist contact form submissions.
- 04
Deploy to Vercel — the schema keeps up
v0 deploys to Vercel as usual. Cradler creates each table on its first insert and adds columns as new fields appear, with daily backups, so there is no migration to run.
The code, end to end
Picture a dashboard you prompted v0 to build — a feedback widget for a product. You want each submission stored and a filtered list shown to the team. Because v0 builds Next.js apps, the natural shape is a route handler using the service key on the server:
// lib/cradler.ts — one shared server client
import { createClient } from "@cradler/sdk";
export const cradler = createClient({
url: process.env.CRADLER_URL!,
projectId: process.env.CRADLER_PROJECT_ID!,
apiKey: process.env.CRADLER_SERVICE_KEY!, // server only
});
// app/api/feedback/route.ts
import { cradler } from "@/lib/cradler";
export async function POST(req: Request) {
const { message, rating, page } = await req.json();
// First insert creates the "feedback" table and its
// columns. rating is numeric, the rest text — inferred.
await cradler.from("feedback").insert({ message, rating, page });
return Response.json({ ok: true });
}
export async function GET() {
// Only show feedback rated 3 or higher, newest first.
const { rows, count } = await cradler
.from("feedback")
.select("message", "rating", "page", "createdAt")
.gte("rating", 3)
.order("createdAt", { desc: true })
.limit(100);
return Response.json({ feedback: rows, total: count });
}The filter methods — .gte(), .eq(), .ilike(), .in(), .order(), .limit()— read like the query builders v0's model was trained on, which is why its generations land. A query is lazy: it runs when you await it, and .first() returns a single row or null instead of an array.
File uploads without a second integration
If your v0 app accepts an upload — a screenshot attached to that feedback, say — you do not need a separate Vercel Blob integration. Storage is in the same Cradler project:
async function attachScreenshot(feedbackId: string, file: File) {
const path = `feedback/${feedbackId}/${file.name}`;
// Bytes go straight to object storage via a presigned
// URL — they never pass through the Cradler gateway.
await cradler.storage.upload(path, file, {
contentType: file.type,
});
await cradler
.from("feedback")
.update({ screenshotPath: path })
.eq("id", feedbackId);
}Gotchas worth knowing
Pick the right key for the right side.v0 components can be server or client. In a route handler or server action, use the service key. In anything that reaches the browser, use the anon key and set each table's permissions in the Cradler dashboard — the anon key respects them, the service key bypasses them.
Let the schema emerge, do not pre-plan it. You do not need to decide every column up front. Ship the feature, and if next week you add categoryto a feedback insert, Cradler adds the column on that write. Resist the urge to ask v0 to “design the schema first” — there is nothing to design.
Renames are a dashboard action. Cradler grows the schema automatically but never drops or renames a column on its own. Those are explicit, confirmed, backed-up actions, so a loose prompt cannot lose data.
Why this pairing works
v0 ships deployment-ready code; Cradler ships a backend that needs no operations. Together you go from a prompt to a live, data-backed app without a schema diagram or a migration file in sight. And the AI doing the work has what it needs to be accurate: a typed SDK, generated types, an llms.txt, and @cradler/mcp for tools that speak the Model Context Protocol. The full API is documented on the @cradler/sdk npm page, and the database underneath is plain PostgreSQL.