Code review prompts and rules
We've compiled code review prompts used by engineers building quality software around the world.
Each rule is reviewed against our internal global evaluation dataset.
Works with any AI tool. Any language. Any codebase.
HTTP conventions in Express API endpoints
Ensure that for any new endpoint, the status code is matched with the correct purpose: - Use 401 Unauthorized for authentication failures (when credentials are missing or invalid) - Use 403 Forbidden for authorization failures (when user is authenticated but lacks required permissions) - Use 404 Not Found for resources that don't exist - Use 400 Bad Request for invalid request parameters - Use 500 Internal Server Error for server-side errors Bad: `typescript // Wrong status code for permission error app.get("/resource", (req: Request, res: Response) => { if (!req.user) { return res.status(401).json({ error: "Permission denied" }) } if (!hasPermission(req.user, "read_resource")) { return res.status(401).json({ error: "Permission denied" }) // Wrong code } // Resource handling... }) ` Good: `typescript // Correct status codes for different scenarios app.get("/resource", (req: Request, res: Response) => { if (!req.user) { return res.status(401).json({ error: "Authentication required" }) } if (!hasPermission(req.user, "read_resource")) { return res.status(403).json({ error: "Permission denied" }) // Correct code } // Resource handling... }) `
typescript
expressjs
Enforce component design system in React
All design system components must use forwardRef pattern, CVA for variants, and follow the established component structure. Bad: `typescript interface ButtonProps { className?: string variant?: string size?: string children: React.ReactNode } const Button = ({ className, variant, size, children, ...props }: ButtonProps) => { let baseClasses = "inline-flex items-center justify-center rounded-md text-sm font-medium" if (variant === "destructive") { baseClasses += " bg-red-500 text-white" } else { baseClasses += " bg-blue-500 text-white" } if (size === "sm") { baseClasses += " h-9 px-3" } else { baseClasses += " h-10 px-4 py-2" } return ( <button className={${baseClasses} ${className}} {...props}> {children} </button> ) } ` Good: `typescript import { cva, type VariantProps } from "class-variance-authority" import { clx } from "../utils" const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", }, }, defaultVariants: { variant: "default", size: "default", }, } ) export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {} const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, ...props }, ref) => { return ( <button className={clx(buttonVariants({ variant, size }), className)} ref={ref} {...props} /> ) } ) Button.displayName = "Button" export { Button, buttonVariants } `
nextjs
react
typescript
Check for duplicate components
Favor existing components over creating new ones. Before creating a new component, check if an existing component can satisfy the requirements through its props and parameters. Bad: `tsx // Creating a new component that duplicates functionality export function FormattedDate({ date, variant }) { // Implementation that duplicates existing functionality return <span>{/ formatted date /}</span> } ` Good: `tsx // Using an existing component with appropriate parameters import { DateTime } from "./DateTime" function Page() { return <DateTime date={date} variant={variant} noTrigger={true} /> } `
nextjs
react
typescript
Internal links in React
When linking between internal sites, use rel="noopener" instead of rel="noopener noreferrer". Bad: `jsx // For internal links, don't use noreferrer <Link to="/dashboard" rel="noopener noreferrer">Dashboard</Link> // Or with anchor tags <a href="/about" rel="noopener noreferrer">About Us</a> ` Good: `jsx // For internal links, only use noopener <Link to="/dashboard" rel="noopener">Dashboard</Link> // Or with anchor tags <a href="/about" rel="noopener">About Us</a> // For external links, noreferrer can be appropriate <a href="https://external-site.com" rel="noopener noreferrer" target="_blank">External Site</a> `
react
typescript
No random numbers in React
Do not generate non-deterministic values like random IDs during render in React components. This causes hydration errors because the server-rendered HTML will not match what the client generates. Avoid using functions like Math.random(), Date.now(), uuid(), or any other source of randomness directly in your render function or JSX. Instead: - Generate IDs in useEffect hooks - Use stable IDs based on props or state - Use refs to store generated values - Use libraries that support SSR (like uuid with specific configuration) Bad: `tsx function UserCard() { // This will generate different values on server and client const id = user-${Math.random()} return ( <div id={id}> <input aria-labelledby={label-${Math.floor(Math.random() * 1000)}} /> </div> ) } ` Good: `tsx function UserCard({ userId }) { // Using stable props for IDs const id = user-${userId} // For dynamic IDs, use useEffect and useState const [randomId, setRandomId] = useState(null) useEffect(() => { // Generate random values after mounting setRandomId(label-${Math.floor(Math.random() * 1000)}) }, []) return <div id={id}>{randomId && <input aria-labelledby={randomId} />}</div> } `
nextjs
react
typescript
No unused components
Do not leave commented-out components. Either remove unused components entirely or implement them properly. Bad: `tsx function MyComponent() { return ( <div> <Header /> {/* <Sidebar> <Navigation /> </Sidebar> */} <MainContent /> </div> ) } ` Good: `tsx function MyComponent() { return ( <div> <Header /> <MainContent /> </div> ) } `
nextjs
react
typescript
Always return empty arrays in Typescript
When defining methods that return collections like arrays, always return an empty array instead of undefined when no items exist. Bad: `typescript function getUserNames(): string[] | undefined { if (users.length === 0) { return undefined } return users.map((user) => user.name) } ` Good: `typescript function getUserNames(): string[] { if (users.length === 0) { return [] } return users.map((user) => user.name) } `
typescript
react
Annotate skipped tests in Typescript
When skipping tests, always add a comment explaining why the test is being skipped. Bad: `typescript describe.skip("enqueueExecution", () => { // test code }) ` Good: `typescript // Test was skipped because it was flaky describe.skip("enqueueExecution", () => { // test code }) `
typescript
Avoid console.log in Typescript tests
Avoid using console.log statements in test files. Bad: `typescript describe("Example test", () => { it("should test something", () => { const result = someFunction() console.log(result) // Debugging statement left in the code expect(result).toBe(expectedValue) }) }) ` Good: `typescript describe("Example test", () => { it("should test something", () => { const result = someFunction() expect(result).toBe(expectedValue) }) }) `
typescript
Avoid duplicate words in Typescript
Check all text elements (comments, docstrings, and string literals) for duplicate adjacent words for typos or duplicates. Bad: `typescript // This function validates the the input parameters function validateInput() { ... } ` Good: `typescript // This function validates the input parameters function validateInput() { ... } `
typescript
react
Self documenting code in Typescript
Avoid unnecessary explanatory comments for code that is self-documenting. Comments should only be used when they add context that the code itself cannot convey. Bad: `typescript // Use the test-specific directory path testDir = join(BASE_DIR, testCase.identifier) ` Good: `typescript testDir = join(BASE_DIR, testCase.identifier) `
typescript
Self documenting string operations in Typescript
Replace magic numbers with self-documenting expressions when dealing with string operations. Bad: `typescript // Magic number - unclear what it represents const position = url.indexOf("/", 12) ` Good: `typescript // Self documenting expression const prefix = "rsc://React/" const position = url.indexOf("/", prefix.length) `
typescript
Check error types in Typescript
Always check the error type in catch blocks and handle specific error types explicitly. Bad: `typescript try { // Some operation } catch (error) { // Converting all errors to a specific type without checking throw new CredentialNotFoundError(id, type) } ` Good: `typescript try { // Some operation } catch (error) { // Check specific error type first if (error instanceof EntityNotFoundError) { throw new CredentialNotFoundError(id, type) } // Pass through other errors throw error } `
typescript
Consistent error classes in Typescript
Use consistent naming conventions for error classes. Bad: `typescript abstract class PublicAPiError extends Error { // Inconsistent casing in "APi" - should be either "Api" or "API" } class UnauthorizedHTtpError extends Error { // Inconsistent casing in "HTtp" - should be either "Http" or "HTTP" } ` Good: `typescript abstract class PublicApiError extends Error { // Consistent Pascal casing with "Api" } class UnauthorizedHttpError extends Error { // Consistent Pascal casing with "Http" } // Or alternatively: abstract class PublicAPIError extends Error { // Consistent uppercase for the acronym "API" } class UnauthorizedHTTPError extends Error { // Consistent uppercase for the acronym "HTTP" } `
typescript
Dev dependencies in typescript
Place CLI tool dependencies in the devDependencies section of package.json instead of dependencies when they are only used for local development, scripts, or tooling. Bad: `json { "dependencies": { "@eslint/eslintrc": "^3", "@tailwindcss/postcss": "^4.1.6", "@types/node": "^20" } } ` Good: `json { "devDependencies": { "@eslint/eslintrc": "^3", "@tailwindcss/postcss": "^4.1.6", "@types/node": "^20" } } `
typescript
react
nextjs
Typescript DRY
Avoid duplicating code in TypeScript. Extract repeated logic into reusable functions, types, or constants. You may have to search the codebase to see if the method or type is already defined. Bad: `typescript // Duplicated type definitions interface User { id: string name: string } interface UserProfile { id: string name: string } // Magic numbers repeated const pageSize = 10 const itemsPerPage = 10 ` Good: `typescript // Reusable type and constant type User = { id: string name: string } const PAGE_SIZE = 10 `
typescript
nextjs
react
Avoid duplicate assignment in Typescript
Avoid assigning values to the same variable multiple times in succession without using the variable in between. Bad: `typescript let count = 0 count = 1 // Duplicate assignment without using the initial value count = 2 // Another duplicate assignment ` Good: `typescript let count = 2 // Direct assignment to final value `
typescript
No unused code in typescript
Do not leave commented-out code blocks. Delete unused code instead of commenting it out. Bad: `typescript function calculateTotal(items: Item[]): number { let total = 0 // Old implementation // for (let i = 0; i < items.length; i++) { // const item = items[i]; // total += item.price * item.quantity; // if (item.discounted) { // total -= item.discountAmount; // } // } // New implementation for (const item of items) { total += item.price item.quantity (item.discounted ? 0.9 : 1) } return total } ` Good: `typescript function calculateTotal(items: Item[]): number { let total = 0 for (const item of items) { total += item.price item.quantity (item.discounted ? 0.9 : 1) } return total } `
typescript
Promise all async loops in Typescript
Use Promise.all when processing multiple async operations in loops. Bad: `typescript async function processItems(items: string[]) { const results = [] for (const item of items) { // Sequential execution - slower const result = await fetchData(item) results.push(result) } return results } ` Good: `typescript async function processItems(items: string[]) { // Parallel execution - faster const results = await Promise.all( items.map(async (item) => { return await fetchData(item) }) ) return results } `
typescript
Query standards for Tanstack Query
When using TanStack Query (React Query), always configure cache and refetching behavior explicitly: 1. Set appropriate staleTime based on how frequently the data changes 2. Configure all refetching flags explicitly to prevent unnecessary network requests Bad: `tsx const { data } = useQuery({ queryKey: ["resource", id], queryFn: () => fetchResource(id), refetchOnMount: false, // Missing staleTime and other refetching settings }) ` Good: `tsx const { data } = useQuery({ queryKey: ["resource", id], queryFn: () => fetchResource(id), refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false, staleTime: 5 60 1000, // 5 minutes }) `
typescript
react
nextjs
Use union types in Typescript
Use union types with specific interfaces for mutually exclusive properties instead of a single interface with multiple optional properties. Bad: `typescript interface ConfigOptions { fileConfig?: { path: string encoding?: string } dbConfig?: { connectionString: string poolSize?: number } properties?: Record<string, any> } ` Good: `typescript interface FileConfigOptions { fileConfig: { path: string encoding?: string } properties?: Record<string, any> } interface DbConfigOptions { dbConfig: { connectionString: string poolSize?: number } properties?: Record<string, any> } type ConfigOptions = FileConfigOptions | DbConfigOptions `
typescript
Avoid unnecessary else blocks in Typescript
Avoid unnecessary else blocks when the if block ends with a return statement, break, continue, or similar control flow statements. Bad: `typescript function processValue(value: number): string { if (value > 10) { return "high" } else { return "low" } } ` `typescript function checkItems(items: string[]): void { for (const item of items) { if (item.length > 5) { console.log("Long item:", item) continue } else { console.log("Short item:", item) } } } ` Good: `typescript function processValue(value: number): string { if (value > 10) { return "high" } return "low" } ` `typescript function checkItems(items: string[]): void { for (const item of items) { if (item.length > 5) { console.log("Long item:", item) continue } console.log("Short item:", item) } } `
typescript
Avoid unnecessary try catch in Typescript
When using try-catch blocks in Typescript, keep the try block focused only on the code that can raise the expected exception. Bad: `typescript async function doSomething() { try { // Large block of code with multiple potential error sources await fetchData() await processData() await saveResults() } catch (error) { console.error(Error: ${(error as Error).message}) process.exit(1) } } ` Good: `typescript async function doSomething() { // Let errors propagate with their full stack trace // or handle specific errors at appropriate points await fetchData() await processData() await saveResults() } // If you need top-level error handling: async function main() { try { await doSomething() } catch (error) { console.error("Unexpected error:", error) process.exit(1) } } `
typescript
Prefer with syntax in Typescript
Use the newer with syntax for JSON imports instead of the deprecated assert syntax for Node.js compatibility. Bad: `javascript import data from "./data.json" assert { type: "json" } ` Good: `javascript import data from "./data.json" with { type: "json" } `
typescript
javascript
Prefer Composition API over Options API in Vue components
Favor the Composition API (<script setup> or setup() function) instead of the Options API when writing new Vue components. Bad – Options API component `vue <script> export default { name: "Counter", data() { return { count: 0, } }, methods: { increment() { this.count++ }, }, mounted() { console.log(The initial count is ${this.count}.) }, } </script> <template> <button @click="increment">Count is: {{ count }}</button> </template> ` Good – Composition API component (<script setup>) `vue <script setup lang="ts"> import { ref, onMounted } from "vue" const count = ref(0) function increment() { count.value++ } onMounted(() => { console.log(The initial count is ${count.value}.) }) </script> <template> <button @click="increment">Count is: {{ count }}</button> </template> `
vue
typescript
javascript
Validate redirect URLs
Always validate redirect URLs to prevent open redirect vulnerabilities. When validating external URLs, parse them with the URL constructor and compare origins exactly rather than using string operations. Bad: `javascript // Vulnerable to subdomain attacks (e.g., example.com.attacker.com) const isRedirectSafe = (redirectUrl) => { return ( redirectUrl.startsWith("/") || redirectUrl.startsWith(window.location.origin) ) } ` Good: `javascript const isRedirectSafe = (redirectUrl) => { // Allow local redirects if (redirectUrl.startsWith("/")) { return true } try { // Validate external URLs by checking exact origin match const url = new URL(redirectUrl) return url.origin === window.location.origin } catch { return false } } `
vue
typescript