React Standards
by Convext
Code standards and best practices for React projects
Rules (60)
Angular
Standalone components are the default (Angular 17+). NgModules are legacy. Use Signals for reactive state. Deferrable views for lazy loading.
`ng generate` for scaffolding. `ng build --configuration production`. Schematics for custom generators.
Observables for async. Use async pipe in templates. Unsubscribe or use takeUntilDestroyed. Signals for simple state.
Injectable services for business logic. `providedIn: 'root'` for singletons. Inject with constructor or inject().
Config
Config in env vars, not code. Never commit .env. Commit .env.example. Never hardcode secrets.
Database
Passwords: bcrypt. API keys: encrypt. PII: field-level encryption. Never log sensitive data.
Dependencies
Use latest stable versions. Fix breaking changes—don't avoid upgrades. Check official registries.
Express
Middleware order matters. Error handlers last with 4 params. Use helmet, cors, compression.
Wrap async handlers or use express-async-errors. Central error handler. Return proper status codes.
Router for route groups. Mount with `app.use('/api', router)`. Keep routes thin, logic in services.
Formatting
Prettier for JS/TS/CSS/HTML/JSON. Minimal config. Run on save. Pre-commit hook. CI check.
Git
Small, focused commits. Use: feat/fix/refactor/test/docs/chore. Each commit independently deployable.
Javascript
`const` by default, `let` for reassignment. Never `var` (hoisting bugs).
async/await for all async code. Easier to read, proper try/catch, works with loops.
TypeScript, not JS. Enable `strict: true`, `noImplicitAny`, `strictNullChecks`.
ESLint + @typescript-eslint recommended rules. No `any`, no unused vars. Run in CI.
Linting
Biome: fast all-in-one linter+formatter. Replaces ESLint+Prettier. Single config. Rust-based.
Llm Behavior
You wrote every line. No 'pre-existing issues'—only issues you haven't fixed yet.
No excuses: 'pre-existing', 'unrelated', 'tedious', 'for now'. Recognize and continue working.
User and tests define done. Don't redefine scope or declare partial progress as complete.
Nestjs
Constructor injection. @Injectable() on services. Custom providers for factories. Scope: DEFAULT unless needed.
Feature modules for domain boundaries. CoreModule for singletons. SharedModule for reusable providers.
ValidationPipe with class-validator DTOs. Guards for auth. Interceptors for transforms. Exception filters.
Nextjs
App Router over Pages Router (Next.js 13+). Server Components by default. 'use client' only when needed.
Fetch in Server Components. Use `cache: 'force-cache'` or `revalidate`. generateStaticParams for static paths.
Server Actions for mutations. `'use server'` directive. Form actions. Revalidate with revalidatePath/revalidateTag.
next/image for optimized images. next/link for client navigation. Automatic prefetching.
Package Manager
package-lock.json (commit it). `npm ci` in CI. Audit for vulnerabilities. Scripts for common tasks.
yarn.lock (commit it). Workspaces for monorepos. `yarn install --frozen-lockfile` in CI. Yarn Berry for PnP.
pnpm: fast, disk-efficient. pnpm-lock.yaml. Workspaces for monorepos. Strict node_modules by default.
Rails
Rails.application.credentials for secrets. `rails credentials:edit`. Environment-specific credentials. Never commit master.key.
React
TanStack Query for server state. Auto caching/revalidation. useQuery for reads, useMutation for writes.
Functional components + hooks only. No class components. Hooks enable reuse without HOCs.
TanStack Query or SWR for fetching. Auto caching, revalidation, loading/error states. Not useEffect+fetch.
Server Components for data fetching. Actions for mutations. use() hook for promises. Optimistic updates. React Compiler for auto-memoization.
Zustand for simple global state. No boilerplate. Hooks-based. Persist middleware for storage.
Context for static data, Zustand/Jotai for simple state, Redux Toolkit for complex. No deep prop drilling.
Security
Force SSL, redirect HTTP→HTTPS, secure cookies (Secure/HttpOnly/SameSite), HSTS headers.
Auth: bcrypt/argon2 for passwords, rate limiting, secure sessions/tokens. Authz: check permissions on every request, use policy objects or middleware.
Allowlists, not denylists. Validate type/length/format. Sanitize HTML. Parameterized queries only.
Svelte
$: for reactive statements. Stores for shared state. Runes ($state, $derived) in Svelte 5. Two-way binding with bind:.
SvelteKit for routing, SSR, API routes. +page.svelte for pages. +layout.svelte for shared UI. Load functions for data.
Testing
Test real instances. Mocking the class under test hides bugs.
Fix failures immediately. No skipping, no "pre-existing issues." Own the codebase state—a test suite with ignored tests can't be trusted.
Jest for unit/integration tests. `describe`/`it` blocks. Mock with jest.mock(). Snapshot testing sparingly.
Test public interfaces, inputs/outputs. Tests must survive refactoring. Don't test private methods.
Vitest for Vite-based projects. Jest-compatible API. Native ESM. Use @testing-library for components.
Cypress for E2E tests. Commands for reusable actions. cy.intercept() for network. Avoid flaky selectors.
Playwright for multi-browser E2E. Auto-wait for elements. Trace viewer for debugging. Parallel execution.
1) Write failing test 2) Minimum code to pass 3) Refactor. Every line has a reason.
Mock only: external HTTP APIs, time, filesystem side effects, third-party services. Use real implementations for internal services, database, and business logic.
Mocha with Chai assertions. describe/it blocks. Sinon for mocking. async/await in tests.
One logical concept per test. Multiple asserts OK if same concept. Clear test names describing behavior.
Use consistent test data setup: fixtures for stable reference data, factories for dynamic scenarios. Avoid inline object creation scattered throughout tests.
Typescript
Zod schemas for runtime validation. Infer types from schemas. Composable. Works with React Hook Form.
Vue
Composition API over Options API. `<script setup>` for SFCs. Composables for reusable logic. ref/reactive for state.
Pinia over Vuex. Define stores with `defineStore`. Composable pattern. DevTools integration.
Named routes, navigation guards. Lazy-load routes with dynamic imports. Use route meta for permissions.
Workflow
Verify changes locally: run app, run tests, check for errors. CI catches environment issues, not basic bugs.
Format → Lint → Test before every commit. Never rely on CI for basic checks.
Language Standards (1)
Use this Ruleset
Sign in to adopt or fork this ruleset
Sign in with GitHubStatistics
- Rules
- 60
- Standards
- 1
- Projects using
- 1
- Created
- Jan 15, 2026