toolingdxeslint

Essential Developer Tooling and Workflows

· Cosyslabs

Developer tooling encompasses every piece of infrastructure that helps you write, check, test, and ship code faster and with fewer errors. Good tooling automates tedious tasks (formatting, linting, type-checking), catches bugs before they reach production, and creates a consistent experience across the entire team. The best tooling is invisible when working and loud when something is wrong.

Editor Setup: VS Code

VS Code is the dominant editor for web and full-stack development. Essential configuration for TypeScript projects:

// .vscode/settings.json — check into source control
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "explicit"
  },
  "typescript.preferences.importModuleSpecifier": "relative",
  "typescript.tsdk": "node_modules/typescript/lib",
  "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
  "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }
}

Recommended extensions (.vscode/extensions.json):

{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "bradlc.vscode-tailwindcss",
    "ms-vscode.vscode-typescript-next",
    "usernamehw.errorlens",
    "eamodio.gitlens"
  ]
}

Code Formatting: Prettier

Prettier enforces a consistent code style automatically. No more debates about semicolons or quote styles in code review.

// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "printWidth": 100,
  "arrowParens": "avoid"
}
# Format all files
npx prettier --write .

# Check without modifying (for CI)
npx prettier --check .

Linting: ESLint

ESLint catches potential bugs, enforces style conventions, and prevents common patterns like unused variables and missing dependencies in React hooks.

// eslint.config.mjs (flat config, ESLint 9+)
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import reactHooks from "eslint-plugin-react-hooks";

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
    plugins: { "react-hooks": reactHooks },
    rules: {
      ...reactHooks.configs.recommended.rules,
      "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
      "@typescript-eslint/no-explicit-any": "warn",
      "no-console": ["warn", { allow: ["warn", "error"] }],
    },
  }
);

Git Hooks: Husky + lint-staged

Run linting and formatting only on changed files before each commit:

npm install --save-dev husky lint-staged
npx husky init
// package.json
{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{js,json,css,md}": "prettier --write"
  }
}
# .husky/pre-commit
npx lint-staged

TypeScript Configuration

A strict TypeScript config catches the most bugs at compile time:

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "exactOptionalPropertyTypes": true,
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] },
    "skipLibCheck": true
  }
}

CI/CD: GitHub Actions

A minimal CI pipeline that validates code on every PR:

# .github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npx tsc --noEmit          # type check
      - run: npx eslint .              # lint
      - run: npx prettier --check .   # format check
      - run: npm test                  # unit tests
      - run: npm run build             # build check

Debugging Tools

// Structured logging (better than console.log)
// Use pino or winston in production

// Browser debugging
console.table(arrayOfObjects);      // renders arrays as tables
console.time("label"); ...code...; console.timeEnd("label"); // measure duration
console.group("Section"); ...logs...; console.groupEnd();     // collapsible groups
debugger;  // pauses execution in DevTools

// Node.js — use --inspect flag
// node --inspect-brk src/server.ts
// Then open chrome://inspect in Chrome

// VS Code launch.json for debugging
{
  "configurations": [{
    "type": "node",
    "request": "launch",
    "name": "Debug Server",
    "runtimeExecutable": "npx",
    "runtimeArgs": ["tsx", "src/server.ts"],
    "env": { "NODE_ENV": "development" }
  }]
}

Package Management

# npm audit — check for vulnerable dependencies
npm audit
npm audit fix        # auto-fix non-breaking vulnerabilities
npm audit fix --force  # fix breaking changes too (review carefully)

# Check for outdated packages
npx npm-check-updates -u  # upgrade all to latest (review changes)
npm install

# Exact versions in package.json (avoids surprise updates)
npm install --save-exact lodash

Developer Experience Checklist

  • Prettier configured and formatting on save enabled
  • ESLint with TypeScript and React plugins
  • Husky pre-commit hooks running lint-staged
  • TypeScript in strict mode
  • CI pipeline running on every PR
  • npm audit in CI to catch vulnerable dependencies
  • .editorconfig for cross-editor consistency
  • VS Code workspace settings checked in

Tools