wispbit Rules
No important tag in CSS
Do not use the !important declaration in CSS styles. Bad: `css .element { color: red !important; margin-top: 10px !important; } `
css
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
HTTP conventions in 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: `python Wrong status code for permission error @app.route('/resource') def get_resource(): if not user.is_authenticated: return jsonify({"error": "Permission denied"}), 401 if not user.has_permission('read_resource'): return jsonify({"error": "Permission denied"}), 401 # Wrong code # ... ` Good: `python Correct status codes for different scenarios @app.route('/resource') def get_resource(): if not user.is_authenticated: return jsonify({"error": "Authentication required"}), 401 if not user.has_permission('read_resource'): return jsonify({"error": "Permission denied"}), 403 # Correct code # ... `
python
flask
quart
Avoid getter methods in Go
Avoid using "getter" methods in Go code. Instead, expose fields directly when appropriate, following Go's idiomatic approach to visibility. Bad: `go type Person struct { name string age int } func (p *Person) GetName() string { return p.name } func (p *Person) GetAge() int { return p.age } // Usage name := person.GetName() ` Good: `go type Person struct { Name string Age int } // Usage name := person.Name `
golang
Early returns in Go
Use early returns to reduce nesting levels. Prefer checking error conditions or guard clauses first and returning early, rather than wrapping the main logic in deep conditional blocks. Bad: `go func processData(data []string) (string, error) { if len(data) > 0 { if isValid(data) { result := "" for _, item := range data { if item != "" { // More nested code here result += transform(item) } } return result, nil } else { return "", errors.New("invalid data") } } else { return "", errors.New("empty data") } } ` Good: `go func processData(data []string) (string, error) { if len(data) == 0 { return "", errors.New("empty data") } if !isValid(data) { return "", errors.New("invalid data") } result := "" for _, item := range data { if item == "" { continue } result += transform(item) } return result, nil } `
golang
Inline error assignment in Go
Use inline error assignment with the := operator when checking for errors. Bad: `go var err error result, err = someFunction() if err != nil { return err } ` Good: `go if result, err := someFunction(); err != nil { return err } `
golang
Structured logging in Go
Always use structured logging with field-based approaches instead of string formatting when logging in Go. Bad: `go logger.Info(fmt.Sprintf("User %s logged in from IP %s with status %d", username, ipAddress, statusCode)) ` Good: `go logger.Info("User authentication", "username", username, "ip", ipAddress, "status", statusCode, ) `
golang
Avoid unnecessary else blocks in Go
Avoid unnecessary else blocks when the if block ends with a return statement, break, continue, or similar control flow statements. Bad: `go func processValue(value int) string { if value > 10 { return "high" } else { return "low" } } ` `go func checkItems(items []string) { for _, item := range items { if len(item) > 5 { fmt.Println("Long item:", item) continue } else { fmt.Println("Short item:", item) } } } ` Good: `go func processValue(value int) string { if value > 10 { return "high" } return "low" } ` `go func checkItems(items []string) { for _, item := range items { if len(item) > 5 { fmt.Println("Long item:", item) continue } fmt.Println("Short item:", item) } } `
golang
Use structured logger in Go
Use the structured logger for all logging operations instead of fmt.Print or log package functions. Bad: `go import ( "fmt" "log" ) func processOrder(order Order) error { fmt.Println("Processing order:", order.ID) if err := validateOrder(order); err != nil { log.Printf("Error validating order %s: %v", order.ID, err) return err } return nil } ` Good: `go import ( "github.com/yourproject/logger" ) func processOrder(order Order) error { logger.Info("Processing order", "orderID", order.ID) if err := validateOrder(order); err != nil { logger.Error("Failed to validate order", "orderID", order.ID, "error", err) return err } return nil } `
golang
Use Zap logger in Go
Use Zap for all logging in Go code. Bad: `go func processOrder(order Order) error { fmt.Printf("Processing order %s\n", order.ID) if err := validateOrder(order); err != nil { log.Printf("Error validating order: %v", err) return err } fmt.Println("Order processed successfully") return nil } ` Good: `go func processOrder(order Order) error { logger := zap.L().With(zap.String("orderID", order.ID)) logger.Info("Processing order") if err := validateOrder(order); err != nil { logger.Error("Failed to validate order", zap.Error(err)) return err } logger.Info("Order processed successfully") return nil } `
golang
Mark fields as deprecated in GraphQL
When removing fields from a GraphQL schema, follow a progressive deprecation process: 1. First, mark the field to be removed as deprecated using the @deprecated directive 2. Introduce the new alternative field in the same operation 3. Only remove deprecated fields after they have been deprecated for a sufficient time period Bad: `graphql // Before type User { id: ID! oldEmail: String! } // After (directly removing the field) type User { id: ID! } ` Good: `graphql // Step 1: Mark as deprecated and introduce alternative type User { id: ID! oldEmail: String! @deprecated(reason: "Use 'email' field instead") email: String! } // Step 2: Only later, remove the deprecated field type User { id: ID! email: String! } `
graphql
Check for duplicates in Markdown
Check documentation for duplicate adjacent words, which are typically typos. Bad: ` prefix adds a prefix to the the column names which is useful for merging the result ` Good: ` prefix adds a prefix to the column names which is useful for merging the result `
markdown
Use code highlighting in Markdown
Specify the appropriate language for code blocks to enable proper syntax highlighting. For CLI commands use bash, and for Python code use py or python. Bad: `markdown transformers chat Qwen/Model-Name --torch_dtype auto ` Good: markdown `bash transformers chat Qwen/Model-Name --torch_dtype auto ` ` `
markdown
Prefer Image in NextJS
Always use Next.js <Image> component instead of HTML <img> tag. Bad: `jsx function ProfileCard() { return ( <div className="card"> <img src="/profile.jpg" alt="User profile" width={200} height={200} /> <h2>User Name</h2> </div> ) } ` Good: `jsx import Image from "next/image" function ProfileCard() { return ( <div className="card"> <Image src="/profile.jpg" alt="User profile" width={200} height={200} priority={false} /> <h2>User Name</h2> </div> ) } `
nextjs
Do not rename columns
When renaming columns in PostgreSQL, follow a safe migration pattern to avoid breaking changes to applications: 1. Create a new column 2. Update application code to write to both the old and new columns 3. Backfill data from the old column to the new column 4. Update application code to read from the new column instead of the old one 5. Once all deployments are complete, stop writing to the old column 6. Drop the old column in a later migration Bad: `sql ALTER TABLE users RENAME COLUMN some_column TO new_name; `
postgresql
prisma
supabase
mysql
drizzle
migrations
Do not rename tables
When renaming tables, use a multi-step approach instead of direct renaming to prevent downtime. 1. Create a new table 2. Write to both tables 3. Backfill data from the old table to the new table 4. Move reads from the old table to the new table 5. Stop writing to the old table 6. Drop the old table Bad: `sql ALTER TABLE users RENAME TO customers; `
postgresql
prisma
supabase
mysql
drizzle
migrations
Avoid aliases for new routes in PHP
Only use route aliases for backward compatibility with renamed or moved routes. Do not add aliases to newly created routes. Bad: `php // Adding an alias to a new route Route::put('/api/users/{id}') ->alias('/api/user/{id}'); // Another framework example $router->map('GET', '/products/{productId}', 'ProductController::show') ->alias('product.show.alt'); ` Good: `php // New route without an alias Route::put('/api/users/{id}'); `
php
Prefer switch statements in PHP
Use switch statements when handling multiple attribute types. Bad: `php foreach ($attributes as $attribute) { if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { // Handle relationship attribute } if ($attribute->getAttribute('type') === Database::VAR_STRING) { // Handle string attribute } } ` Good: `php foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); switch ($attributeType) { case Database::VAR_RELATIONSHIP: // Handle relationship attribute break; case Database::VAR_STRING: // Handle string attribute break; } } `
php
Add indexes for foreign keys in PostgreSQL
When adding a foreign key constraint in PostgreSQL, always add a corresponding index. Bad: `sql ALTER TABLE orders ADD CONSTRAINT fk_orders_user_id FOREIGN KEY (user_id) REFERENCES users(id); ` Good: `sql ALTER TABLE orders ADD CONSTRAINT fk_orders_user_id FOREIGN KEY (user_id) REFERENCES users(id); CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders (user_id); `
postgresql
prisma
supabase
drizzle
migrations
Always have id, created_at, updated_at columns in PostgreSQL
All CREATE TABLE statements must include id, created_at, and updated_at columns. Bad: `sql CREATE TABLE users ( email VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(100) NOT NULL ); ` Good: `sql CREATE TABLE users ( id SERIAL PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(100) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL, updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL ); `
postgresql
prisma
supabase
drizzle
migrations
Column naming standards in PostgreSQL
Maintain consistent naming conventions for new columns. Bad `sql -- Bad: Column named uuid instead of id ALTER TABLE users ADD COLUMN uuid UUID PRIMARY KEY DEFAULT gen_random_uuid(); ` `sql -- Bad: Column named camelCase instead of snake_case ALTER TABLE users ADD COLUMN firstName VARCHAR(255); ` `sql -- Bad: Column foreign key ends with uuid instead of id ALTER TABLE orders ADD COLUMN user_uuid UUID REFERENCES users(id); ` Good `sql -- Good: Consistent naming ALTER TABLE users ADD COLUMN id UUID PRIMARY KEY DEFAULT gen_random_uuid(); ALTER TABLE users ADD COLUMN first_name VARCHAR(255); ALTER TABLE orders ADD COLUMN user_id UUID REFERENCES users(uuid); `
postgresql
prisma
supabase
drizzle
migrations
Index naming standards in PostgreSQL
For indexes, use the following naming standards: - idx_tablename_columnname for single column indexes, - idx_tablename_col1_col2 for multi-column indexes Bad `sql -- Bad: Inconsistent and unclear index names CREATE INDEX email_index ON users(email); CREATE INDEX user_orders ON orders(user_id); CREATE INDEX idx_prod_cat_stat ON products(category, status); ` Good `sql -- Good: Consistent index naming CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_products_category_status ON products(category, status); `
postgresql
prisma
supabase
drizzle
migrations
Limit non unique indexes in PostgreSQL
Limit non-unique indexes to a maximum of three columns in PostgreSQL databases: Bad: `sql CREATE INDEX index_users_on_multiple_columns ON users (column_a, column_b, column_c, column_d); ` Good: `sql CREATE INDEX CONCURRENTLY index_users_on_selective_columns ON users (column_d, column_b); `
postgresql
prisma
supabase
drizzle
migrations
Only concurrent indexes in PostgreSQL
When creating indexes in PostgreSQL, always use the CONCURRENTLY option to prevent blocking writes during index creation. Bad: `sql CREATE INDEX idx_users_email ON users(email); ` Good: `sql CREATE INDEX CONCURRENTLY idx_users_email ON users(email); `
postgresql
prisma
supabase
drizzle
migrations
Always use JSONB in PostgreSQL
Always use jsonb instead of json data type when creating columns in PostgreSQL databases. Bad: `sql ALTER TABLE users ADD COLUMN properties json; ` Good: `sql ALTER TABLE users ADD COLUMN properties jsonb; `
postgresql
prisma
supabase
drizzle
migrations
Use check constraints for setting NOT NULL columns in PostgreSQL
When adding a NOT NULL constraint to an existing column in PostgreSQL, use a check constraint first to avoid blocking reads and writes while every row is checked. Bad: `sql -- This can cause performance issues with large tables ALTER TABLE users ALTER COLUMN some_column SET NOT NULL; ` Good: `sql -- Step 1: Add a check constraint without validation ALTER TABLE users ADD CONSTRAINT users_some_column_null CHECK (some_column IS NOT NULL) NOT VALID; -- Step 2: In a separate transaction, validate the constraint ALTER TABLE users VALIDATE CONSTRAINT users_some_column_null; -- Step 3: Add the NOT NULL constraint and remove the check constraint ALTER TABLE users ALTER COLUMN some_column SET NOT NULL; ALTER TABLE users DROP CONSTRAINT users_some_column_null; `
postgresql
prisma
supabase
drizzle
migrations
Split foreign keys in PostgreSQL
When adding foreign keys in Postgres migrations, split the operation into two steps to avoid blocking writes on both tables: 1. First create the foreign key constraint without validation 2. Then validate existing data in a separate migration Bad: `sql -- In a single migration ALTER TABLE users ADD CONSTRAINT fk_users_orders FOREIGN KEY (order_id) REFERENCES orders (id); ` Good: `sql -- In first migration: add without validating ALTER TABLE users ADD CONSTRAINT fk_users_orders FOREIGN KEY (order_id) REFERENCES orders (id) NOT VALID; -- In second migration: validate existing data ALTER TABLE users VALIDATE CONSTRAINT fk_users_orders; `
postgresql
prisma
supabase
drizzle
migrations
Split unique constraints in PostgreSQL
When adding unique constraints in PostgreSQL, create the unique index concurrently first before adding the constraint to avoid blocking reads and writes. Bad: `sql -- Creates a unique constraint directly, which blocks reads and writes ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email); ` Good: `sql -- First create a unique index concurrently (non-blocking) CREATE UNIQUE INDEX CONCURRENTLY users_email_unique_idx ON users (email); -- Then add the constraint using the existing index ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE USING INDEX users_email_unique_idx; `
postgresql
prisma
supabase
drizzle
migrations
Ensure removed column is ignored in Prisma
When creating a migration to remove a column from the database, ensure that the schema has the @ignore attribute on that column in the Prisma schema. Search for the .prisma schema in the codebase to verify this. `sql ALTER TABLE "User" DROP COLUMN "createdAt"; ALTER TABLE "User" DROP COLUMN "updatedAt"; ` `prisma model User { id Int @id @default(autoincrement()) email String @unique password String remarks String? createdAt DateTime @default(now()) @ignore updatedAt DateTime @updatedAt @ignore } `
postgresql
prisma
migrations
Avoid duplicate words in Python
Check all text elements (comments, docstrings, and string literals) for duplicate adjacent words for typos or duplicates. Bad: `python This function validates the the input parameters def validate_input(data): ... ` Good: `python This function validates the input parameters def validate_input(data): ... `
python
Self documenting code in Python
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: `python Join the test directory with the base directory test_dir = os.path.join(BASE_DIR, test_case.identifier) ` Good: `python test_dir = os.path.join(BASE_DIR, test_case.identifier) `
python
Avoid print in Python tests
Avoid using print() statements in test files. Bad: `python def test_example(): result = some_function() print(result) # Debugging statement left in the code assert result == expected_value ` Good: `python def test_example(): result = some_function() assert result == expected_value `
python
Consistent error classes in Python
Use consistent naming conventions for error classes in Python. Bad: `python class PublicAPiError(Exception): # Inconsistent casing in "APi" - should be either "Api" or "API" pass class UnauthorizedHTtpError(Exception): # Inconsistent casing in "HTtp" - should be either "Http" or "HTTP" pass ` Good: `python class PublicApiError(Exception): # Consistent Pascal casing with "Api" pass class UnauthorizedHttpError(Exception): # Consistent Pascal casing with "Http" pass `
python
Python DRY
Avoid duplicating code in Python. Extract repeated logic into reusable functions, classes, or constants. You may have to search the codebase to see if the function or class is already defined. Bad: `python Duplicated class definitions class User: def __init__(self, id: str, name: str): self.id = id self.name = name class UserProfile: def __init__(self, id: str, name: str): self.id = id self.name = name Magic numbers repeated page_size = 10 items_per_page = 10 ` Good: `python Reusable class and constant class User: def __init__(self, id: str, name: str): self.id = id self.name = name PAGE_SIZE = 10 `
python
Avoid duplicate variable reassignment in Python
Avoid assigning a variable to itself or reassigning a variable with the same value. Bad: `python Redundant self-assignment x = 10 x = x # Unnecessary reassignment Duplicate assignment with the same value y = "hello" ... some code ... y = "hello" # Unnecessary reassignment with identical value ` Good: `python Single, clear assignment x = 10 Only reassign when the value changes y = "hello" ... some code ... y = "updated value" # Value actually changes `
python
Early returns in Python
Use early returns to reduce nesting levels. Instead of wrapping large code blocks in conditional statements, return early when conditions are not met. Bad: `python def process_user(user): if user is not None: if user.is_active: # Many lines of processing code result = perform_complex_operation(user) return result return None ` Good: `python def process_user(user): if user is None: return None if not user.is_active: return None # Now we can work with user without nesting # Many lines of processing code result = perform_complex_operation(user) return result `
python
No unused code in python
Do not leave commented-out code blocks in Python files. If code is no longer needed, remove it entirely rather than commenting it out. Bad: `python def calculate_total(items): total = 0 for item in items: total += item.price # Old calculation method that we might need later # subtotal = 0 # for item in items: # if item.type != 'tax': # subtotal += item.price # tax = calculate_tax(subtotal) # total = subtotal + tax return total ` Good: `python def calculate_total(items): total = 0 for item in items: total += item.price return total `
python
Unnecessary else blocks in Python
Avoid unnecessary else blocks when the if block ends with a return statement, break, continue, or similar control flow statements. Bad: `python def process_value(value): if value > 10: return "high" else: return "low" ` `python def check_items(items): for item in items: if len(item) > 5: print("Long item:", item) continue else: print("Short item:", item) ` Good: `python def process_value(value): if value > 10: return "high" return "low" ` `python def check_items(items): for item in items: if len(item) > 5: print("Long item:", item) continue print("Short item:", item) `
python
Avoid unncecessary try except in Python
When using try-except blocks in Python, keep the try block focused only on the code that can raise the expected exception. Bad: `python try: # Large block of code with many potential errors user_data = get_user_data() process_data(user_data) save_to_db(user_data) except (NetworkError, DBError): logger.error("Operation failed") ` Bad: `python try: # Contains only one potential error but still # has a block of code unrelated to the exception url = "https://google.com" url += "/?search=hello" response = requests.get(url) data = response.json() print(data) except NetworkError as e: logger.error(f"Error: {e}") ` Bad: `python Try except blocks are nested into each other try: response = client.beta.chat.completions.parse( model="some-model", messages=[ {"role": "system", "content": "hello"}, {"role": "user", "content": "how are you"}, ], ) try: json.loads(response.choices[0].message.parsed) except json.JSONDecodeError as e: logger.error(f"Decode failed: {e}") except requests.RequestException as e: logger.error(f"Error: {e}") ` Good: `python try: # Only one function that could have an error user_data = get_user_data() except NetworkError: logger.error("Failed to fetch user data") return Cannot raise an exception so it doesn't need to be handled process_data(user_data) try: # Only one potential error save_to_db(user_data) except DBError: logger.error("Failed to save to database") return ` Good: `python url = "https://google.com" url += "/?search=hello" Network call is a separate try except block try: response = requests.get(url) response.raise_for_status() except RequestException as e: logger.error(f"Error: {e}") Getting response in json is a separate try except block try: data = response.json() except JSONDecodeError as e: logger.error(f"Error: {e}") ` Good: `python Blocks that were nested before are now unnested into separate blocks try: response = client.beta.chat.completions.parse( model="some-model", messages=[ {"role": "system", "content": "hello"}, {"role": "user", "content": "how are you"}, ], ) except requests.RequestException as e: logger.error(f"Error: {e}") try: json.loads(response.choices[0].message.parsed) except json.JSONDecodeError as e: logger.error(f"Decode failed: {e}") `
python
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
Early returns in Ruby
Use early returns to reduce nesting levels. Prefer checking error conditions or guard clauses first and returning early, rather than wrapping the main logic in deep conditional blocks. Bad `ruby def process_data(data) if data.present? if valid?(data) result = "" data.each do |item| if item.present? # More nested code here result += transform(item) end end { success: result } else { error: "invalid data" } end else { error: "empty data" } end end ` Good `ruby def process_data(data) return { error: "empty data" } if data.empty? return { error: "invalid data" } unless valid?(data) result = "" data.each do |item| next if item.blank? result += transform(item) end { success: result } end `
ruby
rails
External API error handling in Ruby
When making external API requests, implement proper error handling with descriptive logging to help with debugging issues. Bad: `ruby def fetch_external_data response = HTTParty.get("https://api.example.com/data") JSON.parse(response.body) end ` Good: `ruby def fetch_external_data response = HTTParty.get("https://api.example.com/data") if response.success? JSON.parse(response.body) else Rails.logger.error("API request failed: status=#{response.code}, message=#{response.message}, body=#{response.body}") nil end end `
ruby
rails
Avoid unnecessary else blocks in Ruby
Avoid unnecessary else blocks when the if block ends with a return statement, break, next, or similar control flow statements. Bad: `ruby def process_value(value) if value > 10 return "high" else return "low" end end ` `ruby def check_items(items) items.each do |item| if item.length > 5 puts "Long item: #{item}" next else puts "Short item: #{item}" end end end ` Good: `ruby def process_value(value) if value > 10 return "high" end "low" end ` `ruby def check_items(items) items.each do |item| if item.length > 5 puts "Long item: #{item}" next end puts "Short item: #{item}" end end `
ruby
rails
Check character boundaries in Rust
When truncating strings, ensure you check character boundaries to prevent panics with multi-byte UTF-8 characters. Bad: `rust // This can cause a panic if truncation happens in the middle of a multi-byte character let mut value = some_string; value.truncate(limit); ` Good: `rust // Check character boundaries before truncating let mut value = some_string; let mut index = limit; while !value.is_char_boundary(index) { index -= 1; } value.truncate(index); `
rust
Use triple slash for documentation in Rust
Use triple slashes (///) for documenting Rust functions and methods. Bad: `rust // This function processes tenant requests fn process_tenant_request() { // implementation } ` Good: `rust /// This function processes tenant requests fn process_tenant_request() { // implementation } `
rust
Prefer logging instead of panicking in Rust
Use logging instead of panicking for recoverable errors. For operations that might fail but don't compromise the entire application state, log the error and provide a fallback rather than panicking. Bad: `rust let top = editor.row_for_block(decorations.prompt_block_id, cx).unwrap(); let bottom = editor.row_for_block(decorations.end_block_id, cx).unwrap(); ` Good: `rust let scroll_target_range = maybe!({ let top = editor.row_for_block(decorations.prompt_block_id, cx)?.0 as f32; let bottom = editor.row_for_block(decorations.end_block_id, cx)?.0 as f32; Some((top, bottom)) }); if scroll_target_range.is_none() { log::error!("bug: failed to find blocks for scrolling to inline assist"); } // Use a fallback value when the operation fails let scroll_target_range = scroll_target_range.unwrap_or_else(|| { // fallback calculation }); `
rust
Shell script best practices
Follow these shell script best practices when writing or modifying bash scripts: 1. Use #!/usr/bin/env bash instead of #!/bin/bash for better portability Bad: `bash !/bin/bash echo "Hello World" ` Good: `bash !/usr/bin/env bash echo "Hello World" ` 2. Use ${variable} syntax for all variable references Bad: `bash name="Alice" echo "Hello $name" ` Good: `bash name="Alice" echo "Hello ${name}" ` 3. Use double quotes around variable expansions to prevent word splitting and globbing Bad: `bash files=$(ls) for file in $files; do rm $file done ` Good: `bash files=$(ls) for file in "${files}"; do rm "${file}" done ` 4. Use [[ and ]] instead of [ and ] for conditional expressions Bad: `bash if [ -z "$input" ] || [ "$input" = "exit" ]; then echo "Exiting..." exit 0 fi ` Good: `bash if [[ -z "${input}" || "${input}" = "exit" ]]; then echo "Exiting..." exit 0 fi ` 5. Use printf '%s\n' instead of echo for output with special characters Bad: `bash output="Text with special chars: * & $HOME" echo $output ` Good: `bash output="Text with special chars: * & $HOME" printf '%s\n' "${output}" ` 6. Use readonly for constants that should not be modified Bad: `bash CONFIG_PATH="/etc/app/config.json" LOG_DIR="/var/log/app" ` Good: `bash readonly CONFIG_PATH="/etc/app/config.json" readonly LOG_DIR="/var/log/app" ` 7. Use | as delimiter in sed commands when replacing paths containing slashes Bad: `bash sed -i "s/${source_path}/${target_path}/" "${config_file}" ` Good: `bash sed -i "s|${source_path}|${target_path}|" "${config_file}" `
shell
Split check constraints
When adding check constraints in migrations, split the operation into two steps to avoid blocking writes during the table scan: 1. First create the check constraint without validation 2. Then validate existing data in a separate migration Bad: `sql -- In a single migration ALTER TABLE users ADD CONSTRAINT ck_users_age_positive CHECK (age >= 0); ` Good: `sql -- In first migration: add without validating ALTER TABLE users ADD CONSTRAINT ck_users_age_positive CHECK (age >= 0) NOT VALID; -- In second migration: validate existing data ALTER TABLE users VALIDATE CONSTRAINT ck_users_age_positive; `
postgresql
prisma
supabase
mysql
drizzle
migrations
Change column types safely in SQLAlchemy
When changing a column type that requires a table rewrite, follow these steps: 1. Create a new column with the desired type 2. Write to both columns during the transition period 3. Backfill data from the old column to the new column 4. Move reads from the old column to the new column 5. Stop writing to the old column 6. Drop the old column Bad: `python def upgrade(): # Directly changing a column type can cause table locks op.alter_column('users', 'some_column', type_=sa.String(50), existing_type=sa.Integer()) def downgrade(): op.alter_column('users', 'some_column', type_=sa.Integer(), existing_type=sa.String(50)) ` Good: `python Migration 1: Add new column def upgrade(): # Adding a new column first op.add_column('users', sa.Column('some_column_new', sa.String(50))) def downgrade(): op.drop_column('users', 'some_column_new') ` `python Migration 2: Complete the transition (after backfilling data) def upgrade(): # After ensuring all data is migrated op.drop_column('users', 'some_column') op.alter_column('users', 'some_column_new', new_column_name='some_column') def downgrade(): op.alter_column('users', 'some_column', new_column_name='some_column_new') op.add_column('users', sa.Column('some_column', sa.Integer())) `
postgresql
mysql
sqlalchemy
migrations
alembic
Ensure index is not already covered in SQLAlchemy
Ensure that individual column indexes in SQLAlchemy are not covered by existing composite indexes. Bad: `python class User(Base): __tablename__ = "users" __table_args__ = ( Index("email_username_idx", "email", "username"), ) id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] = mapped_column(String(255), index=True) # covered by email_username_idx username: Mapped[str] = mapped_column(String(100)) status: Mapped[str] = mapped_column(String(20)) ` Good: `python class User(Base): __tablename__ = "users" # Only composite index needed - covers both email and email+username queries __table_args__ = ( Index("email_username_idx", "email", "username"), ) id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] = mapped_column(String(255)) username: Mapped[str] = mapped_column(String(100)) status: Mapped[str] = mapped_column(String(20)) `
postgresql
sqlalchemy
alembic
migrations
Limit non unique indexes in SQLAlchemy
Limit non-unique indexes to a maximum of three columns in PostgreSQL databases: Bad: `python def upgrade(): with op.get_context().autocommit_block(): op.create_index( 'index_users_on_multiple_columns', 'users', ['column_a', 'column_b', 'column_c', 'column_d'], postgresql_concurrently=True ) ` Good: `python def upgrade(): # Limit to most selective columns for better performance with op.get_context().autocommit_block(): op.create_index( 'index_users_on_selective_columns', 'users', ['column_d', 'column_b'], postgresql_concurrently=True ) `
postgresql
sqlalchemy
alembic
migrations
Only concurrent indexes in SQLAlchemy
When creating or dropping indexes in PostgreSQL using SQLAlchemy migrations, always use the postgresql_concurrently=True option within an autocommit block. This prevents blocking writes during index operations. For upgrade(): Bad: `python def upgrade(): op.create_index('idx_users_email', 'users', ['email']) ` Good: `python def upgrade(): with op.get_context().autocommit_block(): op.create_index('idx_users_email', 'users', ['email'], postgresql_concurrently=True) ` For downgrade(): Bad: `python def downgrade(): op.drop_index('idx_users_email', 'users') ` Good: `python def downgrade(): with op.get_context().autocommit_block(): op.drop_index('idx_users_email', 'users', postgresql_concurrently=True) `
postgresql
sqlalchemy
migrations
alembic
Add check constraints safely in SQLAlchemy
When adding check constraints that could affect large tables, create the constraint with NOT VALID first to avoid blocking writes during the validation scan. Bad: `python def upgrade(): # Directly creating a check constraint blocks writes during table scan op.create_check_constraint( 'ck_users_age_positive', 'users', 'age >= 0' ) ` Good: `python Migration 1: Create check constraint without validation def upgrade(): # Create the check constraint without validating existing data (non-blocking) op.create_check_constraint( 'ck_users_age_positive', 'users', 'age >= 0', postgresql_not_valid=True ) ` `python Migration 2: Validate existing data def upgrade(): op.execute('ALTER TABLE users VALIDATE CONSTRAINT ck_users_age_positive') `
postgresql
sqlalchemy
alembic
migrations
Add foreign keys safely in SQLAlchemy
When adding foreign keys in SQLAlchemy migrations, split the operation into two steps to avoid blocking writes on both tables: 1. First create the foreign key constraint without validation 2. Then validate existing data in a separate migration Bad: `python def upgrade(): # Directly creating a foreign key constraint can block writes on both tables op.create_foreign_key( 'fk_users_orders', 'users', 'orders', ['order_id'], ['id'] ) ` Good: `python Migration 1: Add foreign key without validation def upgrade(): # Create the foreign key constraint without validating existing data op.create_foreign_key( 'fk_users_orders', 'users', 'orders', ['order_id'], ['id'], postgresql_not_valid=True ) ` `python Migration 2: Validate existing data def upgrade(): op.execute('ALTER TABLE users VALIDATE CONSTRAINT fk_users_orders') `
postgresql
sqlalchemy
alembic
migrations
Add unique constraints safely in SQLAlchemy
When adding unique constraints that could affect large tables, create the unique index concurrently first to avoid blocking reads and writes during the migration. Bad: `python def upgrade(): # Directly creating a unique constraint can block reads and writes op.create_unique_constraint('users_email_unique', 'users', ['email']) ` Good: `python Migration 1: Create unique index concurrently def upgrade(): # Create the unique index concurrently (non-blocking) op.create_index( 'users_email_unique_idx', 'users', ['email'], unique=True, postgresql_concurrently=True ) ` `python Migration 2: Add constraint using existing index def upgrade(): # Add the unique constraint using the existing index op.create_unique_constraint( 'users_email_unique', 'users', ['email'], postgresql_using_index='users_email_unique_idx' ) `
postgresql
sqlalchemy
alembic
migrations
Verify query patterns are covered by an index in SQLAlchemy
Ensure that SQLAlchemy query patterns are covered by appropriate database indexes. Bad: `python queries.py def get_user_by_email(session: Session, email: str): # Will perform full table scan - no index on email return session.scalar(select(User).where(User.email == email)) models.py class User(Base): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] = mapped_column(String(255)) # No index status: Mapped[str] = mapped_column(String(50)) created_at: Mapped[datetime] = mapped_column(DateTime) ` Good: `python queries.py def get_user_by_email(session: Session, email: str): # Is covered by an index return session.scalar(select(User).where(User.email == email)) models.py class User(Base): __tablename__ = 'users' id: Mapped[int] = mapped_column(primary_key=True) email: Mapped[str] = mapped_column(String(255), index=True) status: Mapped[str] = mapped_column(String(50)) created_at: Mapped[datetime] = mapped_column(DateTime) `
postgresql
sqlalchemy
alembic
migrations
Prefer tailwind design tokens
Use Tailwind's predefined design tokens instead of arbitrary values. Do not use custom pixel values, color codes, or arbitrary numbers in your Tailwind CSS classes. 1. Use Tailwind's spacing scale instead of arbitrary pixel values 2. Use Tailwind's color palette instead of custom color codes 3. Use Tailwind's z-index scale instead of arbitrary z-index values 4. Use Tailwind's percentage-based positioning values instead of arbitrary percentages Bad: `html <div class="mt-[37px] text-[#3366FF] z-[9999] top-[37%] w-[142px]"> Custom content </div> ` Good: `html <div class="mt-10 text-blue-600 z-50 top-1/3 w-36">Custom content</div> `
nextjs
tailwind
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