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.
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:
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:
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:
{
"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
- vibe-coding · patterns
Vibe-Coding with a Database: 10 Patterns That Don't Break
Ten concrete patterns for keeping AI-paired database work clean: typed schemas, migration discipline, RLS-as-authz, write-confirmation gates, and the anti-patterns to avoid.
Read article - supabase · ai
Why Supabase is the AI Agent's Favorite Postgres in 2026
Schema introspection in one HTTP call, RLS as the authorization primitive, JWT-based claims your agent can simulate. Why Supabase ended up perfectly aligned with the AI-paired era.
Read article - typescript · drizzle
Type-Safe Database Access for AI-Paired Codebases
Why type-safety isn't optional when an AI writes most of your code. Drizzle vs Prisma vs Kysely vs sqlc compared for the AI-paired workflow.
Read article