Browse 158 rules, 25 knowledge articles, and 25 prompt templates across security, performance, architecture, and quality.
158 rules
Normalize your database schema to at least 3NF to eliminate data duplication. Denormalized data means the same fact is stored in multiple places — when you update one copy, the others become stale, creating data inconsistencies that are nearly impossible to track down.
Define foreign key constraints for all table relationships. Without foreign keys, the database allows orphaned rows (e.g., an order referencing a deleted customer), corrupting data integrity silently.
Don't pass props through 3+ intermediate components that don't use them. Use context, composition, or state management instead. Prop drilling creates tight coupling between distant components and makes refactoring painful — changing a prop type requires updating every component in the chain.
Always use stable, unique keys in array .map() renders. Missing or unstable keys (like array index) cause React to destroy and recreate DOM nodes, losing component state and causing visual glitches.
Don't use useEffect to sync state that can be computed from existing state or props. Derived values should be calculated during render, not in effects. Effects for derived state cause extra renders, race conditions, and stale UI that flash incorrect data before correcting.
Test what the code does (outputs, side effects), not how it does it (internal method calls, private state). Implementation-coupled tests break every time you refactor, even when behavior is unchanged — making tests a liability instead of a safety net.
Every test must be independent — no shared mutable state, no execution order dependencies. When tests share state, they pass in isolation but fail together (or worse, fail randomly), creating flaky CI that wastes hours of debugging time.
Use factory functions (e.g., `createUser({role: 'admin'})`) instead of static JSON fixtures. Factories let you create exactly the data each test needs with sensible defaults, while fixtures force you to maintain large JSON files where a change to one test's data breaks another test.
Only add "use client" when a component needs hooks, event handlers, or browser APIs. Every unnecessary "use client" directive ships the component and all its dependencies to the browser as additional JavaScript — slowing down page loads, increasing bandwidth costs, and degrading the experience for users on slow connections or low-powered devices.
Every table in the public schema must have Row Level Security enabled with at least one policy per operation. Without RLS, the Supabase API exposes every row to every request — any browser with your anon key or any logged-in user can read, modify, or delete data belonging to other users. A single table missing RLS can leak your entire user base's private data or let one user overwrite another's records.
Dependencies must flow inward: Presentation -> Controller -> Service -> Repository -> Domain. Never import upward across layers. [CWE-1047]
When the same logic appears in three or more places, extract it into a shared function, hook, or module. Duplicated code means that when you fix a bug or change behavior in one copy, the other copies silently remain broken — leading to inconsistent behavior, hard-to-trace bugs, and wasted time tracking down "why does it work here but not there."
Every Server Action must verify authentication as its first operation. Server Actions compile to public HTTP POST endpoints — anyone on the internet can call them directly with a simple fetch request, bypassing your UI entirely. Even if you have middleware or layout-level auth checks, the action itself must independently verify the user because external guards can be misconfigured, incomplete, or bypassed. Without per-action auth, an attacker can invoke privileged operations like deleting data, changing settings, or accessing resources they should never reach.
Always use supabase.auth.getUser() on the server side to verify identity. getSession() reads the JWT from cookies and decodes it without verifying the signature against the auth server — so if an attacker tampers with the token (changing the user ID, role, or email), your server-side code will trust the forged claims as legitimate. This is a complete authentication bypass: the attacker can impersonate any user, escalate privileges, or access data they were never authorized to see.
BeforeMerge scans your pull requests against these rules automatically. Get actionable feedback before code ships to production.