

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# Clean Code & Refactoring — Cursor Rules2# Comprehensive rules for writing clean, maintainable, and readable code34## Project Context5You are working on a codebase where code quality, readability, and maintainability are6first-class priorities. Code is read far more often than it is written. Every function,7class, and module should clearly communicate its intent. The codebase should be easy8for any developer to understand, modify, and extend.910## Core Principles11- Code should read like well-written prose12- Every function should do one thing and do it well13- Make the code express the intent — minimize the need for comments14- Leave the codebase better than you found it (Boy Scout Rule)15- Optimize for readability first, performance second (unless profiling says otherwise)1617## Naming1819### Rules20- Names should reveal intent — a reader should know what it does without reading the body21- Use domain language from the business (Ubiquitous Language from DDD)22- Be consistent — if you call it `fetch` in one place, don't call it `get` in another23- Avoid abbreviations unless universally understood (`id`, `url`, `http`)24- Avoid noise words: `data`, `info`, `temp`, `stuff`, `handler` (when everything is a handler)25- Name length should correlate with scope size — short names for small scopes, descriptive for large2627### Examples28```29// BAD30const d = new Date(); // What is d?31function proc(lst) { ... } // proc? lst?32const flag = user.age > 18; // What flag?33const temp = calculateTotal(items); // Why temp?3435// GOOD36const registrationDate = new Date();37function filterActiveUsers(users) { ... }38const isEligibleForAdultContent = user.age > 18;39const orderTotal = calculateTotal(items);40```4142### Specific Guidelines43- **Booleans**: `is`, `has`, `should`, `can` prefix (`isActive`, `hasPermission`)44- **Functions**: verb + noun (`calculateTotal`, `sendNotification`, `validateEmail`)45- **Classes**: noun or noun phrase (`UserRepository`, `PaymentProcessor`)46- **Collections**: plural nouns (`users`, `orderItems`, `pendingTasks`)47- **Callbacks/handlers**: `on` or `handle` prefix (`onSubmit`, `handleClick`)48- **Factories**: `create` or `build` prefix (`createUser`, `buildQuery`)4950## Functions5152### Rules53- Functions should do ONE thing54- Functions should be short — if you need to scroll, it's too long55- Aim for 1-3 parameters; 4+ parameters usually means you need an options object56- No side effects that aren't obvious from the function name57- Prefer pure functions when possible (same input = same output, no side effects)58- Functions should operate at one level of abstraction5960### Extract Until You Drop61```ts62// BAD — mixed levels of abstraction, doing too many things63function processOrder(order) {64 // Validate65 if (!order.items.length) throw new Error('Empty order');66 if (!order.user) throw new Error('No user');67 if (order.items.some(i => i.quantity <= 0)) throw new Error('Invalid quantity');6869 // Calculate70 let total = 0;71 for (const item of order.items) {72 const price = item.price * item.quantity;73 const discount = item.quantity >= 10 ? price * 0.1 : 0;74 total += price - discount;75 }76 const tax = total * 0.08;77 total += tax;7879 // Save80 db.orders.insert({ ...order, total, tax, status: 'pending' });81 emailService.send(order.user.email, `Order confirmed: $${total}`);82}8384// GOOD — each function does one thing at one level of abstraction85function processOrder(order) {86 validateOrder(order);87 const { total, tax } = calculateOrderTotal(order.items);88 const savedOrder = saveOrder(order, total, tax);89 notifyCustomer(order.user, savedOrder);90}9192function validateOrder(order) {93 if (!order.items.length) throw new OrderError('Order must contain at least one item');94 if (!order.user) throw new OrderError('Order must have an associated user');95 if (order.items.some(item => item.quantity <= 0)) {96 throw new OrderError('All items must have a positive quantity');97 }98}99100function calculateOrderTotal(items) {101 const subtotal = items.reduce((sum, item) => sum + calculateItemPrice(item), 0);102 const tax = subtotal * TAX_RATE;103 return { total: subtotal + tax, tax };104}105106function calculateItemPrice(item) {107 const basePrice = item.price * item.quantity;108 const discount = item.quantity >= BULK_THRESHOLD ? basePrice * BULK_DISCOUNT_RATE : 0;109 return basePrice - discount;110}111```112113## Conditionals114115### Simplify Complex Conditions116```ts117// BAD — what does this check?118if (user.age >= 18 && user.country === 'US' && !user.isBanned && user.emailVerified) {119120// GOOD — extracted to a named function or variable121const isEligibleForService = user.age >= 18122 && user.country === 'US'123 && !user.isBanned124 && user.emailVerified;125126if (isEligibleForService) {127```128129### Use Early Returns (Guard Clauses)130```ts131// BAD — deeply nested132function getDiscount(user) {133 if (user) {134 if (user.isPremium) {135 if (user.yearsActive > 5) {136 return 0.2;137 } else {138 return 0.1;139 }140 } else {141 return 0;142 }143 } else {144 return 0;145 }146}147148// GOOD — flat with early returns149function getDiscount(user) {150 if (!user) return 0;151 if (!user.isPremium) return 0;152 if (user.yearsActive > 5) return 0.2;153 return 0.1;154}155```156157### Avoid Negative Conditions158```ts159// BAD160if (!isNotFound) { ... }161if (!disableValidation) { ... }162163// GOOD164if (isFound) { ... }165if (enableValidation) { ... }166```167168## Error Handling169170### Rules171- Don't use exceptions for control flow172- Throw specific, descriptive error types173- Handle errors at the appropriate level (don't catch and ignore)174- Provide context in error messages: what happened, why, and what was attempted175- Never swallow errors silently — at minimum, log them176177```ts178// BAD179try {180 doSomething();181} catch (e) {182 // silently ignored183}184185// BAD186throw new Error('error');187188// GOOD189throw new OrderNotFoundError(`Order ${orderId} not found for user ${userId}`);190```191192## Comments193194### When Comments Are Needed195- Explaining WHY, not WHAT (the code shows what; comments explain why)196- Legal or compliance requirements197- Warnings about consequences: `// WARNING: This clears the entire cache`198- TODO/FIXME with ticket numbers: `// TODO(JIRA-123): Replace with batch API`199- Complex regex or algorithm explanation200- Public API documentation (JSDoc, docstrings)201202### When to Avoid Comments203- Explaining WHAT the code does — rename the code instead204- Commented-out code — delete it, Git has history205- Journal comments (`// Added by John on 2024-01-15`) — Git has blame206- Redundant comments: `count++; // increment count`207- Closing brace comments: `} // end if` — your function is too long208209## Code Smells to Watch For210- **Long methods** (20+ lines) — break into smaller functions211- **Long parameter lists** (4+ params) — use an options object or builder212- **Deep nesting** (3+ levels) — use early returns and extraction213- **Duplicated code** — extract shared logic into functions/modules214- **Primitive obsession** — use value objects (`Money`, `EmailAddress`, `DateRange`)215- **God classes** — split into focused, single-responsibility classes216- **Feature envy** — a function that uses another class's data more than its own217- **Magic numbers** — extract to named constants: `const MAX_LOGIN_ATTEMPTS = 5;`218- **Boolean parameters** — split into two functions or use an enum/options object219220## Refactoring Techniques221- **Extract function**: Pull a block of code into a named function222- **Extract variable**: Name a complex expression223- **Rename**: Make intent clearer (most impactful refactoring)224- **Inline**: Remove unnecessary indirection225- **Replace conditional with polymorphism**: Replace switch/if chains with classes226- **Introduce parameter object**: Group related parameters227- **Replace magic number with constant**: Name the meaning228229## File Organization230- Keep files short — if a file has 300+ lines, consider splitting231- Group related code together232- Put the public API at the top of the file233- Private/helper functions below234- One concept per file (one class, one module, one concern)235- Consistent ordering within files across the codebase236237## Common Pitfalls238- Premature abstraction — don't DRY code that happens to look similar but serves different purposes239- Over-engineering — simple problems need simple solutions (YAGNI)240- Inconsistent style within a codebase — agree on conventions and follow them241- Refactoring without tests — always have tests before refactoring242- Big bang refactors — refactor incrementally, commit often243- Naming things after their type: `userList`, `nameString` — just use `users`, `name`244- Mixing abstraction levels in the same function245- Writing code to impress rather than to communicate246
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/tailwindcss/.cursorrules · 16 | .cursorrules | lint-formatstylearchui+3 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 16 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-14-app-router/.cursorrules · 16 | .cursorrules | teststyletypestesting-strategy+3 | 71/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-app-router/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-typescript/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/survivorforge-cursor-rules-rules-clean-code-cursorrules)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.