JavaScript Code Quality

A practical guide for developers and reviewers to keep JavaScript code clean, secure, and high-performing.

What We Cover in the JavaScript Code Analysis​

Here’s what this checklist helps you review before approving a pull request.

✅ Code & Design Quality – correctness, logic, structure, and style
✅ Security & Performance – vulnerabilities, efficiency, and scalability
✅ Operational Readiness – testing, observability, and feature rollouts
✅ Integration & Boundaries – APIs, data handling, and external contract

JavaScript Code Review Checklist

Export this Checklist as Markdown

Use these points as a starting guide to automate code reviews with your agent.

PR goal is clearly explained (what, why, linked issue/ticket).

Scope is focused: one problem or feature per PR.

Branch name, title, and description follow team conventions.

Includes tests, screenshots, or storybook/playwright story if relevant.

Migrations/feature flags/rollback strategy described.

Happy and failure paths covered; no unreachable code.

Guard clauses and conditions are clear; avoid deep if nesting.

Functions are pure where possible; side effects explicit.

Names match behavior—functions do exactly what their name implies.

Avoid null/undefined pitfalls (use ?? and ?. when appropriate).

No dead code, leftover logs, or TODOs without a linked issue.

Inputs/outputs validated (Zod/Yup/manual) at all external boundaries.

XSS: Never inject unsanitized user input into the DOM (innerHTML, dangerouslySetInnerHTML).

Injection: No string-built SQL/command calls—use placeholders/ORM.

Secrets: No API keys or credentials in client or repo; use environment variables.

AuthN/AuthZ: Checks happen on the server; routes/handlers protected.

CSRF: State-changing endpoints protected with tokens or SameSite.

Open redirect / URL validation: Validate next/redirect query params.

Dependencies: No known vulnerabilities (npm audit, Snyk, etc.).

SSR/Edge: Never leak sensitive data to the client.

Headers: Content-Security-Policy, X-Frame-Options, Strict-Transport-Security configured at the server/proxy.

Algorithms and data structures chosen with complexity in mind (O(n) vs O(n²)).

Avoid repeated traversals; use memoization when useful.

Async I/O: Parallelize with Promise.all/allSettled when calls are independent.

Debounce/Throttle heavy UI events (scroll, resize, input).

Minimize unnecessary renders/reflows (state batching, list virtualization).

Bundle: Granular imports, code-splitting, lazy loading of heavy routes/pages.

Assets: Modern image formats, proper sizing, loading="lazy".

Node: Don’t block the event loop—CPU tasks → worker threads/queues.

await used correctly; errors handled (try/catch or Promise.catch).

External calls have timeouts, retries, and cancellation (AbortController).

Guard against race conditions (check state before/after await; use light locks if needed).

In streams/event emitters: remove listeners and close connections.

Matches team style guide (automatic formatter in place).

Prefer immutability; don’t mutate params/props.

Functions are small and cohesive; extract helpers when complexity grows.

Favor early returns over nested if pyramids.

Comments only where they add context (don’t explain the obvious).

Naming: nouns for data, verbs for actions; avoid cryptic abbreviations.

Public functions/utilities have JSDoc or clear contracts.

Use JSDoc/typedefs for public APIs and complex objects.

Defensive type checks (Array.isArray, typeof, in).

Functions always return a predictable type (no “sometimes null, sometimes object”).

If using TypeScript: any is justified and isolated; strict enabled.

Errors carry clear messages and context.

No silent exception swallowing; justified where you must silence.

Log levels are correct (debug/info/warn/error) and never expose sensitive data.

Browser: error boundaries and network error capture;
Node: handle unhandledRejection/uncaughtException with graceful shutdown.

Metrics/tracing for critical paths (latency, error rate).

Validate all payloads (schema-driven).

Preserve versioning/backward compatibility.

Idempotent operations for retries.

Consistent error format (HTTP codes, {code,message,details} shape).

Normalize/sanitize dates, numbers, and locales.

Unit tests cover critical logic (branch conditions included).

Integration tests for endpoints/DB basics.

Essential end-to-end tests for key revenue/risk flows.

Tests are stable, fast, and independent; fixtures/mocks realistic.

Snapshot tests minimal and readable.

Each flag has an owner, scope, and planned lifetime; rollback is simple.

Flagged code is clean; removal is scheduled.

Metrics connected to flag adoption/impact.

await inside loops when Promise.all would be better.

JSON.parse/stringify for deep clone without considering dates/Map/Set.

Direct mutation of req/res/props/state.

Disabling ESLint rules without justification.

Using Date without timezone awareness; toLocaleString without locale.

setInterval/setTimeout left orphaned; clear on unmount/shutdown.

Adding a heavy library for a trivial task (e.g., whole lodash for one function).

Turn this checklist into automated reviews

Let Kody automatically check quality, security and performance in every pull request—cloud or self-hosted, in under 2 minutes.