Set Up Supabase with Cursor in 5 Minutes
An opinionated quickstart: Supabase project, Drizzle for type-safe queries, Cursor rules file, your first table. The same template we use to start every new vibe-coded project in 2026.
This is the opinionated setup we use to start every new vibe-coded project. Five minutes of work; the rest of the project is downstream.
Step 1: Create the Supabase project
Head to supabase.com/dashboard, create a new project. Pick the closest region. Save the database password somewhere safe.
From the project settings, grab:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY- The direct connection string (Settings → Database → Connection string).
Step 2: Bootstrap a Next.js app with Drizzle
pnpm create next-app@latest my-app --typescript --app --tailwind
cd my-app
# Drizzle + postgres-js + Zod
pnpm add drizzle-orm postgres zod
pnpm add -D drizzle-kit @types/pgAdd drizzle.config.ts at the root:
import type { Config } from "drizzle-kit";
export default {
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: { url: process.env.DATABASE_URL! },
} satisfies Config;Step 3: Wire up the Supabase connection
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
const sql = postgres(process.env.DATABASE_URL!, {
max: 1, // serverless-friendly
prepare: false, // safe for transaction-mode pooling
});
export const db = drizzle(sql);Add .env.local:
DATABASE_URL=postgres://postgres:[password]@db.[project].supabase.co:6543/postgres
NEXT_PUBLIC_SUPABASE_URL=https://[project].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=ey...Step 4: Define your first schema
import { pgTable, uuid, text, timestamp } from "drizzle-orm/pg-core";
export const posts = pgTable("posts", {
id: uuid("id").primaryKey().defaultRandom(),
authorId: uuid("author_id").notNull(),
title: text("title").notNull(),
content: text("content"),
status: text("status").$type<"draft" | "published">().notNull().default("draft"),
createdAt: timestamp("created_at").defaultNow().notNull(),
});Generate and apply the migration:
pnpm drizzle-kit generate
pnpm drizzle-kit migrateStep 5: Add a Cursor rules file
Drop .cursorrules (or AGENTS.md if you prefer the open standard) at the repo root:
When working on database code:
1. Every schema change is a migration in `drizzle/`. Run
`pnpm drizzle-kit generate` after every `src/db/schema.ts`
change, then `pnpm drizzle-kit migrate`. Never ALTER TABLE
in production directly.
2. Read `src/db/schema.ts` before writing any query. Use the
types from `drizzle-orm` and the inferred row types. Do not
invent column names.
3. Row-Level Security stays on. Every new table needs a policy in
the migration that creates the table.
4. Default to the anon Supabase client. Use service_role only with
an explicit comment explaining why.Step 6: Ship the first feature
Open Cursor and ask: "create a route at /api/posts that lists the 10 most recent published posts". The agent reads your schema, generates a typed query, returns the route. You ship.