Skip to content
All articles
Articlecursorsupabasevibe-coding

The Cursor + Supabase Stack in 2026

End-to-end setup for the AI-paired stack that ships the fastest in 2026: Cursor for the editor, Supabase for the database, Drizzle for types, MCP servers for schema access.

12 min read

The Cursor + Supabase + Drizzle stack has converged in 2026 as the fastest way to ship CRUD apps with an AI in the loop. Three reasons: every layer is type-checked end-to-end, the database is introspectable, and the agent can read everything it needs in the repo.

The stack

  • Cursor: the editor. Rules file lives in the repo; the agent reads it.
  • Next.js 15: app router; server actions handle most write paths.
  • Supabase: Postgres, auth, storage, realtime. RLS is your authz layer.
  • Drizzle: schema-as-TypeScript + migrations.
  • Optional: an admin tool like Suparbase for ops work.

Drizzle schema as the source of truth

Everything starts here. The schema file is what your agent reads every turn:

src/db/schema.tsts
import {
  pgTable, uuid, text, timestamp, boolean, index,
} from "drizzle-orm/pg-core";

export const projects = pgTable(
  "projects",
  {
    id:         uuid("id").primaryKey().defaultRandom(),
    tenantId:   uuid("tenant_id").notNull(),
    name:       text("name").notNull(),
    slug:       text("slug").notNull(),
    archived:   boolean("archived").notNull().default(false),
    createdAt:  timestamp("created_at").defaultNow().notNull(),
  },
  (t) => ({
    tenantIdx:  index("projects_tenant_idx").on(t.tenantId),
    slugIdx:    index("projects_slug_idx").on(t.tenantId, t.slug),
  }),
);

export type Project        = typeof projects.$inferSelect;
export type ProjectInsert  = typeof projects.$inferInsert;

Cursor rules file

The rules file (.cursorrules or AGENTS.md) is where you put the conventions the agent should follow. Every team's version is different; ours is roughly:

.cursorrules
When working in this repo:

- Schema changes: edit src/db/schema.ts, then run
  `pnpm drizzle-kit generate && pnpm drizzle-kit migrate`.
  Never ALTER TABLE in production directly.

- Reads use the typed Drizzle query builder, not raw SQL.

- Writes go through src/lib/audit.ts:recordAndApply so every
  change ends up in audit_log.

- RLS stays on. Every new table needs policies in the same migration.
  Default to: USING (tenant_id IN (SELECT public.my_tenants())).

- For Supabase admin operations that need service_role, use
  src/lib/sb-admin.ts. Add a code comment naming the reason.

- For new server actions, default to "use server"; return typed errors
  using neverthrow's Result type.

MCP servers for live schema

Cursor (and Claude Code, Windsurf, etc.) speak the Model Context Protocol. The Supabase team ships an MCP server that gives the agent live access to your schema introspection. With it, the agent can:

  • List tables and columns on the running project, not just the repo.
  • Read RLS policies as they exist in production.
  • Run an EXPLAIN on a generated query to verify the plan.
  • Suggest indexes based on real slow queries.

Setup is a single block in .cursor/mcp.json:

.cursor/mcp.jsonjson
{
  "mcpServers": {
    "supabase": {
      "command": "npx",
      "args": ["-y", "@supabase/mcp-server", "--read-only"]
    }
  }
}

Patterns that work

1. Type the input + output of every server action

Zod schemas at the input boundary; inferred return type from Drizzle. The agent reads both and writes correct callers.

2. Co-locate UI + server action + schema for a feature

app/projects/page.tsx, app/projects/actions.ts, app/projects/schema.ts. The agent looks for the trio when adding a related feature.

3. Test the negative path

The agent will write the happy-path test. You ask it explicitly for the negative-path tests: "write a test that a non-member cannot read a project they don't belong to."

4. Use an admin tool for the data, not the agent

Don't ask the agent to "go check the staging database for bad rows". Open the admin, use Cmd-K, find the row, fix it. The agent is for code; the admin is for ops.

The stack is boring on purpose. Each piece does one thing. Nothing is exotic. The result is a development loop where you describe a feature in plain English and the agent ships a typed, RLS-protected, audit-logged implementation in minutes.

Suparbase is an admin workspace for Supabase. Encrypted credentials, server-side proxy, RLS debugger, SQL playground, AI assistant with diff-confirmed writes. Free tier for solo projects.

Related articles