javascript json 62 lines · 3 tabs

ESLint config that avoids bikeshedding

Shared by codesnips Jan 2026
3 tabs
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  {
    files: ['**/*.{js,ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2022,
      sourceType: 'module',
    },
    rules: {
      'no-console': ['warn', { allow: ['warn', 'error'] }],
      'eqeqeq': ['error', 'smart'],
      'no-var': 'error',
      'prefer-const': 'error',
      'no-unused-vars': 'off',
      '@typescript-eslint/no-unused-vars': [
        'error',
        { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
      ],
      '@typescript-eslint/no-explicit-any': 'warn',
    },
  },
  {
    files: ['**/*.test.{js,ts,tsx}', '**/__tests__/**'],
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      'no-console': 'off',
    },
  },
  // Must stay last: disables every stylistic rule so Prettier wins.
  prettierConfig,
];
3 files · javascript, json Explain with highlit

The point of these files is to stop teams from arguing about whitespace and quotes in code review. In eslint.config.js, the project adopts the modern flat config format and delegates every formatting decision to Prettier via eslint-config-prettier, which is spread last so it turns OFF any stylistic rule ESLint might otherwise enforce. This is the core anti-bikeshedding move: ESLint is left responsible only for correctness (unused variables, undeclared globals, forbidden patterns) while Prettier owns layout. Because formatting is no longer negotiable — it is applied mechanically — pull requests stop accumulating comments about indentation or trailing commas.

The config is built as an array of objects, each scoped by files. A base block sets languageOptions and enables @typescript-eslint rules; a test-specific block relaxes a couple of rules that are noisy in specs. The rules chosen are deliberately opinionated but semantic: no-unused-vars is configured to ignore intentionally-prefixed _args, and eqeqeq is on because == is a real bug source, not a style choice. Crucially there are no quotes, semi, indent, or comma-dangle rules — those belong to Prettier.

The .prettierrc.json tab is intentionally tiny. Prettier's whole philosophy is to have few options, and keeping the file minimal signals that these are the only knobs the team ever touches. Once agreed, nobody relitigates them.

In package.json, the scripts wire the tools together. lint runs ESLint for real problems, format writes Prettier changes, and format:check verifies formatting in CI without modifying files, so a mis-formatted branch fails fast rather than sparking a debate.

The trade-off is giving up fine-grained control over layout, which some developers dislike initially. The payoff is that formatting becomes invisible: editors format on save, CI enforces it, and review energy goes to logic. A common pitfall is enabling ESLint's own stylistic rules alongside Prettier, causing the two to fight; spreading prettierConfig last prevents exactly that. This setup is worth reaching for on any shared codebase where review comments have started drifting toward taste rather than substance.


Related snips

typescript
export interface RetryOptions {
  retries: number;
  baseMs: number;
  maxMs: number;
  signal?: AbortSignal;
  onRetry?: (attempt: number, delay: number, err: unknown) => void;

Exponential backoff with jitter for retries

typescript reliability retry
by codesnips 2 tabs
typescript
import axios, { AxiosError } from 'axios'
import { v4 as uuidv4 } from 'uuid'

const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1',
  timeout: 15000,

Axios API client with interceptors

react axios api
by Maya Patel 1 tab
typescript
import { create } from 'zustand'
import { persist } from 'zustand/middleware'

interface FilterState {
  search: string
  category: string | null

Zustand for lightweight state management

react zustand state-management
by Maya Patel 2 tabs
typescript
import React from "react";

type FallbackProps = {
  error: Error;
  reset: () => void;
};

React Error Boundary + error reporting hook

react frontend error-boundary
by codesnips 3 tabs
javascript
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
  openAnalyzer: true,
});

/** @type {import('next').NextConfig} */

Next.js bundle analyzer for targeted performance work

nextjs performance tooling
by codesnips 4 tabs
typescript
import { Navigate, useLocation } from 'react-router-dom'
import { useAuth } from '@/contexts/AuthContext'

interface ProtectedRouteProps {
  children: React.ReactNode
}

React Router with protected routes

react react-router routing
by Maya Patel 2 tabs

Share this code

Here's the card — post it anywhere.

ESLint config that avoids bikeshedding — share card
Link copied