Ultracite Code Standards
This project uses Ultracite, a zero-config Biome preset that enforces strict code quality standards through automated formatting and linting.
Quick Reference
- •Format code:
npx ultracite fix - •Check for issues:
npx ultracite check - •Diagnose setup:
npx ultracite doctor
Biome (the underlying engine) provides extremely fast Rust-based linting and formatting. Most issues are automatically fixable.
Core Principles
Write code that is accessible, performant, type-safe, and maintainable. Focus on clarity and explicit intent over brevity.
Type Safety & Explicitness
- •Use explicit types for function parameters and return values when they enhance clarity
- •Prefer
unknownoveranywhen the type is genuinely unknown - •Use const assertions (
as const) for immutable values and literal types - •Leverage TypeScript's type narrowing instead of type assertions
- •Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Modern JavaScript/TypeScript
- •Use arrow functions for callbacks and short functions
- •Prefer
for...ofloops over.forEach()and indexedforloops - •Use optional chaining (
?.) and nullish coalescing (??) for safer property access - •Prefer template literals over string concatenation
- •Use destructuring for object and array assignments
- •Use
constby default,letonly when reassignment is needed, nevervar
Async & Promises
- •Always
awaitpromises in async functions - don't forget to use the return value - •Use
async/awaitsyntax instead of promise chains for better readability - •Handle errors appropriately in async code with try-catch blocks
- •Don't use async functions as Promise executors
React & JSX
- •Use function components over class components
- •Call hooks at the top level only, never conditionally
- •Specify all dependencies in hook dependency arrays correctly
- •Use the
keyprop for elements in iterables (prefer unique IDs over array indices) - •Nest children between opening and closing tags instead of passing as props
- •Don't define components inside other components
- •Use semantic HTML and ARIA attributes for accessibility:
- •Provide meaningful alt text for images
- •Use proper heading hierarchy
- •Add labels for form inputs
- •Include keyboard event handlers alongside mouse events
- •Use semantic elements (
<button>,<nav>, etc.) instead of divs with roles
Error Handling & Debugging
- •Remove
console.log,debugger, andalertstatements from production code - •Throw
Errorobjects with descriptive messages, not strings or other values - •Use
try-catchblocks meaningfully - don't catch errors just to rethrow them - •Prefer early returns over nested conditionals for error cases
Code Organization
- •Keep functions focused and under reasonable cognitive complexity limits
- •Extract complex conditions into well-named boolean variables
- •Use early returns to reduce nesting
- •Prefer simple conditionals over nested ternary operators
- •Group related code together and separate concerns
Security
- •Add
rel="noopener"when usingtarget="_blank"on links - •Avoid
dangerouslySetInnerHTMLunless absolutely necessary - •Don't use
eval()or assign directly todocument.cookie - •Validate and sanitize user input
Performance
- •Avoid spread syntax in accumulators within loops
- •Use top-level regex literals instead of creating them in loops
- •Prefer specific imports over namespace imports
- •Avoid barrel files (index files that re-export everything)
- •Use proper image components (e.g., Next.js
<Image>) over<img>tags
Framework-Specific Guidance
Next.js:
- •Use Next.js
<Image>component for images - •Use
next/heador App Router metadata API for head elements - •Use Server Components for async data fetching instead of async Client Components
React 19+:
- •Use ref as a prop instead of
React.forwardRef
Solid/Svelte/Vue/Qwik:
- •Use
classandforattributes (notclassNameorhtmlFor)
Testing
- •Write assertions inside
it()ortest()blocks - •Avoid done callbacks in async tests - use async/await instead
- •Don't use
.onlyor.skipin committed code - •Keep test suites reasonably flat - avoid excessive
describenesting
When Biome Can't Help
Biome's linter will catch most issues automatically. Focus your attention on:
- •Business logic correctness - Biome can't validate your algorithms
- •Meaningful naming - Use descriptive names for functions, variables, and types
- •Architecture decisions - Component structure, data flow, and API design
- •Edge cases - Handle boundary conditions and error states
- •User experience - Accessibility, performance, and usability considerations
- •Documentation - Add comments for complex logic, but prefer self-documenting code
Most formatting and common issues are automatically fixed by Biome. Run npx ultracite fix before committing to ensure compliance.