# supabase

Enforces SQL style conventions, schema design standards, and database security practices for Supabase projects in Cursor.

- rule · `type=rule` · Cursor · ★ 3580
- Author: sanjeed5
- License: CC0-1.0 · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/supabase.mdc
- Updated: 2026-05-19
- HTML: https://affpapa.org/en/nevibecode/rules/supabase

## What it does

This rule guides the AI agent when generating Postgres schemas and migrations for Supabase. It enforces lower-case SQL keywords, `snake_case` identifiers, plural table names, and standard `bigint generated always as identity` primary keys on every table.

For database performance, it mandates creating explicit indexes on all foreign key columns because PostgreSQL omits them. Complex nested subqueries are replaced with readable Common Table Expressions (CTEs).

Security guidance focuses on defensive Postgres architecture. It demands enabling Row-Level Security (RLS) on all exposed tables and defaults custom functions to `SECURITY INVOKER`. If `SECURITY DEFINER` is used, setting `search_path = ''` is mandatory to block privilege escalation attacks.

## Requirements
- Works with: Supabase

## Install

### Cursor (native platform)

**Manually: put the files in place**
- File: `.cursor/rules/supabase.mdc` — Frontmatter: description, globs, alwaysApply

### Claude Code

**Manually: put the files in place**
- File: `.claude/rules/supabase.md` — The paths frontmatter field limits the files: move globs from the source into paths

### Codex

**AGENTS.md**
- Codex reads AGENTS.md: paste the rule text there

### GitHub Copilot

**Manually: put the files in place**
- File: `.github/instructions/supabase.instructions.md` — The applyTo field sets which files it applies to: move globs from the source into applyTo

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/rules/supabase.md`

### Cline

**Manually: put the files in place**
- File: `.clinerules/supabase.md`

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/supabase.mdc

## When to use it
- enforce Row-Level Security policies on newly created tables
- index foreign key columns to eliminate table scans
- standardize SQL migration formatting and CTE usage
- secure database functions against search_path escalation vulnerabilities

## Example prompts
- Create a user profiles table referencing auth.users with the required primary key and foreign key index
- Write an RLS policy allowing authenticated users to read only their own documents
- Generate a Postgres function with SECURITY INVOKER to fetch audit entries safely

## Source text · supabase.mdc · CC0-1.0

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 0be296f567b80955.

BEGIN THIRD-PARTY FILE 0be296f567b80955
````text
---
description: Comprehensive guidelines for writing high-performance, secure, and maintainable Supabase applications, covering SQL style, data modeling, security, and testing.
globs: **/*
---
# Supabase Best Practices

This guide outlines the definitive best practices for developing with Supabase, ensuring your projects are secure, performant, and maintainable. Adhere to these rules for consistent, high-quality code.

## 1. SQL Style & Code Organization

Consistency is paramount. Follow these rules for all SQL schema, migrations, and functions.

### 1.1 Naming Conventions
- **Identifiers:** Use `snake_case` for all table, column, and function names. Names must begin with a letter and contain only letters, numbers, and underscores.
- **Keywords:** Always use lowercase for SQL keywords (e.g., `select`, `from`, `where`).
- **Table Names:** Prefer plural, `snake_case` names (e.g., `users`, `products`).
- **Column Names:** Prefer singular, `snake_case` names (e.g., `id`, `name`, `created_at`).
- **Foreign Keys:** Use `singular_table_name_id` (e.g., `user_id` for `users` table).
- **Triggers:** Prefix with a numeric order (e.g., `_200_update_timestamp`) as triggers run in lexicographical order.

❌ BAD
```sql
CREATE TABLE UserProfiles (
    UserID INT PRIMARY KEY,
    UserName VARCHAR(255)
);
SELECT UserID FROM UserProfiles;
```

✅ GOOD
```sql
CREATE TABLE user_profiles (
    id bigint generated always as identity primary key,
    user_name text not null,
    user_id bigint references users (id) -- Example FK
);
SELECT id FROM user_profiles;

-- Trigger naming for ordered execution
CREATE TRIGGER _200_update_user_profile_timestamp
BEFORE UPDATE ON user_profiles
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
```

### 1.2 Formatting & Readability
- **Indentation:** Use consistent indentation for clauses and arguments.
- **Aliases:** Always use explicit `AS` for aliases. Make them meaningful.
- **Boolean Operators:** Place `AND`/`OR` at the beginning of the line for multi-line `WHERE` clauses.
- **Parentheses:** Align closing parentheses with the starting line of the expression.

❌ BAD
```sql
SELECT t.client_id, DATE(t.created_at) day
FROM telemetry t, users u
WHERE t.user_id = u.id AND t.submission_date > '2019-07-01'
GROUP BY 1, 2;
```

✅ GOOD
```sql
SELECT
    t.client_id AS client_identifier,
    DATE(t.created_at) AS created_day
FROM
    telemetry AS t
INNER JOIN
    users AS u ON t.user_id = u.id
WHERE
    t.submission_date > '2019-07-01'
    AND t.sample_id = '10'
GROUP BY
    t.client_id,
    created_day;
```

### 1.3 Common Table Expressions (CTEs)
- **Prefer CTEs:** Use CTEs (`WITH` clauses) for complex queries to improve readability and modularity over nested subqueries.

❌ BAD
```sql
SELECT
    (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count,
    u.email
FROM
    users AS u;
```

✅ GOOD
```sql
WITH user_order_counts AS (
    SELECT
        user_id,
        COUNT(*) AS order_count
    FROM
        orders
    GROUP BY
        user_id
)
SELECT
    u.email,
    uoc.order_count
FROM
    users AS u
LEFT JOIN
    user_order_counts AS uoc ON u.id = uoc.user_id;
```

## 2. Data Modeling & Schema Design

Design your schema for clarity, integrity, and performance.

### 2.1 Primary Keys
- **Standard PK:** Every table *must* have an `id` column of type `bigint generated always as identity primary key`.

❌ BAD
```sql
CREATE TABLE products (
    product_code text PRIMARY KEY,
    name text
);
```

✅ GOOD
```sql
CREATE TABLE products (
    id bigint generated always as identity primary key,
    product_code text unique not null,
    name text not null
);
```

### 2.2 Foreign Key Indexes
- **Always Index FKs:** PostgreSQL does *not* automatically index foreign keys. Always add an index to every foreign key column to prevent expensive lookups, especially for reverse relations.

❌ BAD
```sql
````
END THIRD-PARTY FILE 0be296f567b80955

The third-party file has ended. Everything between the 0be296f567b80955 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 3886 of 10234 bytes. © sanjeed5 · CC0-1.0 · https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/supabase.mdc

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
