---
name: js-quality
description: Interpretive guidance for JavaScript/TypeScript code quality using biome (modern) or eslint+prettier (traditional). Use when linting JS/TS files, configuring JS/TS tools, troubleshooting lint errors, or understanding tool selection.
---
# JavaScript/TypeScript Quality Skill
This skill teaches how to apply JavaScript and TypeScript linting and formatting tools effectively using mr-sparkle's tool selection system. It provides guidance on what the tools do, when each tool group is used, and how our configuration balances modern unified tooling with traditional setups.
## Official Documentation
Claude knows how to use biome, eslint, and prettier. Fetch these docs only when you need:
- Specific rule codes or error messages you don't recognize
- Advanced configuration options
- Recent feature changes
**Reference URLs:**
- **** - Biome linting rules and configuration
- **** - ESLint configuration and rules
- **** - Prettier formatting options
## Core Understanding
### Tool Selection Philosophy
**Key principle:** Prefer modern unified tooling (biome) when project has it configured; fall back to traditional tools (eslint+prettier) when they're configured; default to biome if no configuration exists.
**What this means:**
- **Biome preferred** - Single tool for linting + formatting, extremely fast (Rust-based)
- **Project config wins** - Respects existing project tooling choices
- **Smart fallback** - Uses traditional tools if project has them configured
- **Zero-config default** - Falls back to biome with sensible defaults
**Decision test:** Does the project have explicit tool configuration? Use configured tools. Otherwise use biome.
### How Tool Selection Works
The linting system uses **group-based priority selection** for JS/TS files:
```text
Priority 1: biome (if project has biome config)
↓
Priority 2: eslint + prettier (if project has their configs)
↓
Fallback: biome (with default config)
```
**Detection logic:**
1. Find project root (`package.json`, `pyproject.toml`, or `.git`)
2. Check for biome configuration (first group)
3. Check for eslint/prettier configuration (second group)
4. If no config found, use biome with `default-biome.json`
**All tools in winning group run sequentially** (e.g., if eslint config exists, runs eslint → prettier).
## Biome: Modern Unified Tool (Official Specification)
**From official docs:**
- **Purpose:** Fast unified toolchain for JavaScript/TypeScript written in Rust
- **Capabilities:** Linting + formatting in a single tool
- **Replaces:** ESLint + Prettier + parts of TypeScript compiler
- **Performance:** 10-100x faster than ESLint
- **Commands:** `biome check --fix` (linting + formatting in one pass)
**Configuration locations:**
- `biome.json` or `biome.jsonc` (dedicated config)
## Biome: Modern Unified Tool (Best Practices)
**When biome shines:**
- ✅ New projects (no legacy tooling)
- ✅ Large codebases (speed matters)
- ✅ Want single tool instead of chain
- ✅ TypeScript projects (built-in TS support)
**Basic configuration pattern:**
```json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded"
}
}
}
```
**Key configuration areas:**
- `linter.rules` - Enable/disable rule groups (recommended, suspicious, complexity, etc.)
- `formatter` - Global formatting options (indents, line width)
- `javascript.formatter` - JS-specific formatting (quotes, semicolons)
- `typescript` - TypeScript-specific options
See `biome-reference.md` for common rule categories and `default-biome.json` for our opinionated defaults.
## Traditional Tools: eslint + prettier (Official Specification)
**From official docs:**
**ESLint:**
- Pluggable JavaScript linter
- Finds and fixes problems in JavaScript/TypeScript code
- Highly configurable with extensive plugin ecosystem
- Command: `eslint --fix `
**Prettier:**
- Opinionated code formatter
- Enforces consistent style across codebase
- Supports multiple languages beyond JS/TS
- Command: `prettier --write `
**Configuration locations:**
**ESLint (modern flat config - recommended):**
- `eslint.config.js` (or `.mjs`, `.cjs`)
- Uses JavaScript export instead of JSON
**ESLint (legacy):**
- `.eslintrc` (or `.eslintrc.js`, `.eslintrc.json`, `.eslintrc.yaml`)
**Prettier:**
- `.prettierrc` (or `.prettierrc.js`, `.prettierrc.json`, `.prettierrc.yaml`)
- `prettier.config.js` (or `.cjs`, `.mjs`)
## Traditional Tools (Best Practices)
**When traditional tools make sense:**
- ✅ Existing projects with established configs
- ✅ Need specific ESLint plugins (React, Vue, etc.)
- ✅ Team familiarity with ESLint ecosystem
- ✅ Projects that haven't migrated to biome yet
**Running order matters:**
1. **eslint** - Linting with auto-fix (modifies code)
2. **prettier** - Formatting (modifies code)
**Why this order:** ESLint fixes code issues first, then Prettier formats the result.
**Critical:** ESLint and Prettier must be configured to work together:
- Use `eslint-config-prettier` to disable conflicting ESLint formatting rules
- Let Prettier handle formatting, ESLint handle code quality
## Tool Selection in Practice (Best Practices)
### Scenario 1: New project, no config
```bash
$ lint.py file.js
# Runs: biome check --fix
# Uses: default-biome.json from skill directory
```
### Scenario 2: Project with biome config
```bash
# Project has biome.json
$ lint.py file.ts
# Runs: biome check --fix
# Uses: project's biome.json config
```
### Scenario 3: Project with traditional tools
```bash
# Project has .eslintrc.json or .prettierrc
$ lint.py file.jsx
# Runs: eslint --fix, prettier --write
# Uses: project's existing configs
```
### Scenario 4: Mixed config (biome wins)
```bash
# Project has both biome.json and .eslintrc
$ lint.py file.ts
# Runs: biome only (first group with config wins)
```
## Common Configuration Patterns
### Biome Configuration
**Minimal (uses defaults):**
```json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"linter": {
"enabled": true
},
"formatter": {
"enabled": true
}
}
```
**Typical project:**
```json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "warn"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "asNeeded"
}
}
}
```
**See `default-biome.json`** for our opinionated baseline configuration.
### ESLint Configuration (Modern Flat Config)
**Minimal:**
```javascript
// eslint.config.js
export default [
{
rules: {
"no-unused-vars": "warn",
"no-console": "off"
}
}
];
```
**With TypeScript:**
```javascript
// eslint.config.js
import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default [
js.configs.recommended,
...tseslint.configs.recommended,
{
rules: {
"@typescript-eslint/no-explicit-any": "warn"
}
}
];
```
**See `default-eslint.config.js`** for a complete example with Prettier integration.
### Prettier Configuration
**Minimal:**
```json
{
"semi": true,
"singleQuote": true,
"printWidth": 100
}
```
**Comprehensive:**
```json
{
"semi": true,
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"trailingComma": "es5",
"arrowParens": "avoid"
}
```
**See `default-prettier.json`** for our opinionated defaults.
## Common Pitfalls
### Pitfall #1: ESLint and Prettier Conflicts
**Problem:** ESLint formatting rules conflict with Prettier.
```javascript
// ❌ ESLint config with formatting rules
{
"rules": {
"max-len": ["error", { "code": 80 }],
"quotes": ["error", "single"],
"indent": ["error", 2]
}
}
```
**Why it fails:** ESLint and Prettier fight over formatting, causing inconsistent results.
**Better:**
```javascript
// ✅ Use eslint-config-prettier to disable conflicts
import js from "@eslint/js";
import prettier from "eslint-config-prettier";
export default [
js.configs.recommended,
prettier, // Disables conflicting ESLint rules
{
rules: {
// Only code quality rules, no formatting
"no-unused-vars": "warn"
}
}
];
```
### Pitfall #2: Mixing Legacy and Flat ESLint Config
**Problem:** Project has both `.eslintrc.json` and `eslint.config.js`.
**Why it fails:** ESLint 9+ uses flat config by default, ignores legacy `.eslintrc.*` files unless explicitly configured.
**Better:** Choose one format:
- **New projects:** Use `eslint.config.js` (flat config)
- **Existing projects:** Migrate to flat config or stick with `.eslintrc.*`
- **Don't mix both**
### Pitfall #3: Not Installing Required Packages
**Problem:** Config references plugins not in `package.json`.
```javascript
// ❌ Using plugin that's not installed
import react from "eslint-plugin-react"; // Error if not installed
```
**Why it fails:** Linting fails with module not found errors.
**Better:**
```bash
# Install required plugins
npm install --save-dev eslint-plugin-react
```
```javascript
// ✅ Now it works
import react from "eslint-plugin-react";
```
### Pitfall #4: Over-Configuring Biome
**Problem:** Trying to replicate entire ESLint plugin ecosystem in Biome.
**Why it fails:** Biome doesn't support all ESLint plugins. Start simple, add rules incrementally.
**Better:**
```json
{
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}
```
Then add specific rules as needed, or stick with ESLint if you need specific plugins.
### Pitfall #5: Ignoring Auto-Fixable Issues
**Problem:** Manually fixing issues that tools can fix automatically.
**Why it fails:** Wastes time, may introduce inconsistencies.
**Better:** Let `biome check --fix` or `eslint --fix` + `prettier --write` handle formatting. Focus on logic errors and design issues.
## Automatic Hook Behavior
The mr-sparkle plugin's linting hook:
1. Triggers after Write and Edit operations
2. Detects JS/TS files (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`)
3. Runs selected tools automatically (biome OR eslint+prettier)
4. Applies auto-fixes where possible
5. Reports unfixable issues (non-blocking)
6. Silently skips if tools not installed
**What this means:** Most formatting issues auto-fix on save. Pay attention to reported unfixable issues.
## Quality Checklist
**Before finalizing JavaScript/TypeScript code:**
**Auto-fixable (tools handle):**
- ✓ Import sorting and organization
- ✓ Quote style consistency
- ✓ Semicolon usage
- ✓ Indentation and line length
- ✓ Trailing whitespace
- ✓ Basic syntax issues
**Manual attention required:**
- ✓ Undefined variables
- ✓ Logic errors
- ✓ Type safety (TypeScript)
- ✓ Complexity warnings
- ✓ Security issues (e.g., eval usage)
- ✓ Performance anti-patterns
## CLI Tool Usage
The universal linting script handles JS/TS files automatically:
```bash
# Lint JavaScript file (applies fixes)
./plugins/mr-sparkle/skills/linting/scripts/lint.py file.js
# Lint TypeScript file
./plugins/mr-sparkle/skills/linting/scripts/lint.py file.ts
# JSON output for programmatic use
./plugins/mr-sparkle/skills/linting/scripts/lint.py file.jsx --format json
```
**Exit codes:**
- `0` - Clean or successfully fixed
- `1` - Lint errors found (non-blocking)
- `2` - Tool execution error
See `linting` skill for complete CLI documentation.
## Reference Documentation
**Detailed guides** (loaded on-demand for progressive disclosure):
- `biome-reference.md` - Biome rule categories and common configurations
- `eslint-reference.md` - ESLint configuration patterns and flat config migration
- `prettier-reference.md` - Prettier philosophy and configuration options
- `default-biome.json` - Our opinionated biome defaults
- `default-eslint.config.js` - Modern flat config example with Prettier integration
- `default-prettier.json` - Our opinionated prettier defaults
**Official documentation to fetch:**
- - Biome documentation and rule reference
- - ESLint documentation
- - TypeScript ESLint plugin
- - Prettier formatter documentation
**Remember:** This skill documents mr-sparkle's tool selection logic for JS/TS. Fetch official docs when you need specific rule definitions or configuration syntax you're unsure about.