Browse 225 rules, 42 knowledge articles, and 28 prompt templates across security, performance, architecture, and quality.
225 rules
Adding 'use client' to large components or pages ships unnecessary JavaScript to the browser. Push interactivity to the smallest leaf components.
Business logic belongs in service classes, not in route handlers, server actions, or components. Use the ServiceResult<T> pattern. [CWE-1086]
Database access belongs in repository classes, not in services or route handlers. Repositories abstract the data source behind a typed interface. [CWE-1057]
Split large repository interfaces into focused, role-specific contracts so consumers only depend on the methods they use
Use factory classes (ServiceFactory, RepositoryFactory) for dependency wiring instead of direct instantiation or imports in consuming code.
Domain entities should be pure TypeScript classes/interfaces with no framework dependencies like Supabase, React, or Next.js
Build in dependency order: Domain, Interface, Repository, Service, Controller, Presentation. Top-down builds couple UI to data.
Audit and minimize third-party scripts (analytics, chat widgets, ad trackers). Each third-party script adds DNS lookups, TLS handshakes, and JavaScript execution that blocks the main thread — a single chat widget can add 500ms+ to page load and degrade Core Web Vitals scores.
Store all environment-specific configuration (API URLs, database connections, feature flags) in environment variables, never in source code. Hardcoded config means your staging code talks to production databases, your API keys are in git history, and deploying to a new environment requires code changes.
Sanitize and escape all user-provided input before rendering in HTML, executing in SQL, or passing to system commands. Unsanitized input is the entry point for XSS, SQL injection, and command injection attacks — the three most exploited vulnerability classes in web applications.
Never use eval(), new Function(), or vm.runInScript() with user-provided input. These functions execute arbitrary code with the full privileges of your Node.js process — an attacker can read files, access databases, or take over the entire server.
Set security headers on all HTTP responses: Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security. Missing headers leave your app vulnerable to XSS, clickjacking, MIME sniffing, and protocol downgrade attacks.
Never merge user-controlled objects into application objects using Object.assign, spread, or deep-merge without validation. Prototype pollution lets an attacker inject __proto__ properties that modify the behavior of every object in your application — enabling denial of service, authentication bypass, or remote code execution.
Lazy-load images, components, and data that are below the initial viewport fold. Loading everything upfront makes the user wait for content they haven't scrolled to yet — increasing Time to Interactive and burning mobile data on content the user may never see.
Serve images in modern formats (WebP/AVIF), at appropriate dimensions, and with width/height attributes. Unoptimized images are typically the largest assets on a page — a single uncompressed hero image can be larger than all your JavaScript combined, destroying load times on mobile.
When the same combination of Tailwind utilities appears in 3+ places, extract it to a component or @apply directive. Duplicated utility strings mean a design change (like spacing or color) requires finding and updating every copy — miss one and you have an inconsistent UI.
Use Tailwind's responsive prefixes (sm:, md:, lg:) and theme tokens instead of arbitrary pixel values. Arbitrary values ([w-347px]) bypass the design system, creating inconsistent spacing/sizing that doesn't adapt to different screen sizes.
Every <img> must have a meaningful alt attribute. Without alt text, screen readers either skip the image entirely or read the raw filename ("DSC_0042.jpg"), leaving visually impaired users completely unable to understand the content.
Use semantic HTML elements (<nav>, <main>, <article>, <button>) instead of generic <div> and <span> with click handlers. Screen readers and assistive technology rely on semantic elements to understand page structure — a <div onClick> looks like nothing to a blind user.
Minimize use of arbitrary values like [w-347px], [color:#1a2b3c]. Arbitrary values bypass Tailwind's design tokens, making the design system meaningless and creating one-off values that are impossible to maintain consistently.
Each commit should contain exactly one logical change. Commits that mix refactoring, bug fixes, and features together make git bisect useless, code review painful, and reverting a single change impossible without losing everything else in the commit.
Pin exact versions for all dependencies in production (no ^, ~, or * ranges). Unpinned dependencies silently pull in new versions that can introduce breaking changes, security vulnerabilities, or performance regressions — and you won't know until production breaks.
Never commit API keys, passwords, tokens, or credentials to version control. Once a secret is in git history, it is permanently exposed — even deleting the file doesn't remove it from history, and anyone who cloned the repo has a copy forever.
CI must run the full test suite and block deployment on failure. Without gate checks, a broken commit reaches production, users experience bugs, and you spend hours debugging under pressure instead of catching it in CI for free.
BeforeMerge scans your pull requests against these rules automatically. Get actionable feedback before code ships to production.