Skip to main content
interlace
Plugin: conventionsRules

filename-case

Enforce filename case conventions for consistency across your codebase

Enforce filename case conventions for consistency across your codebase. This rule is part of eslint-plugin-conventions and provides LLM-optimized error messages with fix suggestions.

Quick Summary

AspectDetails
SeverityWarning (code quality)
Auto-Fix๐Ÿ’ก Suggests fixes (requires manual file rename)
CategoryQuality
ESLint MCPโœ… Optimized for ESLint MCP integration
Best ForTeams wanting consistent filename conventions across the codebase

Rule Details

Why This Matters

IssueImpactSolution
๐ŸŽจ ConsistencyMixed naming styles in codebaseEnforce single convention
๐Ÿ“ DiscoverabilityHard to find filesPredictable naming
๐Ÿ”„ Cross-platformCase sensitivity issuesUse lowercase conventions
๐Ÿค Team AlignmentDisagreements on styleAutomated enforcement

Configuration

OptionTypeDefaultDescription
casestring'kebabCase'Case convention: camelCase, kebabCase, pascalCase, snakeCase
ignorearray[]Basenames (exact strings) or RegExps to ignore completely
allowedUppercaseFilesstring[]['README', 'LICENSE', 'CHANGELOG', ...]Uppercase filenames allowed without extension
allowedKebabCasestring[][]Specific files allowed to use kebab-case
allowedSnakeCasestring[][]Specific files allowed to use snake_case
allowedCamelCasestring[][]Specific files allowed to use camelCase
allowedPascalCasestring[][]Specific files allowed to use PascalCase

Case Style Reference

Case StylePatternExample
kebabCaselowercase-wordsuser-service.ts
camelCasecamelCaseWordsuserService.ts
PascalCasePascalCaseWordsUserService.ts
snake_caselowercase_wordsuser_service.ts

Examples

โŒ Incorrect (with kebabCase)

src/
  UserService.ts        โŒ Should be user-service.ts
  myComponent.tsx       โŒ Should be my-component.tsx
  API_Handler.ts        โŒ Should be api-handler.ts

โœ… Correct (with kebabCase)

src/
  user-service.ts       โœ… kebab-case
  user.ts               โœ… a single lowercase word conforms to kebab, camel and snake
  user-service.test.ts  โœ… .test / .spec / .stories / .story / .e2e / .d suffixes are not part of the name
  README.md             โœ… conventional uppercase file (allowedUppercaseFiles)
  .eslintrc.js          โœ… dotfiles are not checked

Configuration Examples

Basic Usage (Default kebab-case)

{
  rules: {
    'conventions/filename-case': 'error'
  }
}

PascalCase for React Components

{
  rules: {
    'conventions/filename-case': ['error', {
      case: 'pascalCase',
      allowedKebabCase: ['index', 'main']
    }]
  }
}

Mixed Convention with Overrides

{
  rules: {
    'conventions/filename-case': ['error', {
      case: 'kebabCase',
      allowedPascalCase: ['App', 'Button', 'Modal'],  // React components
      allowedSnakeCase: ['db_migrations'],            // Legacy
      ignore: [/\.config\./]                          // Config files
    }]
  }
}

Disable Default Uppercase Files

{
  rules: {
    'conventions/filename-case': ['error', {
      case: 'kebabCase',
      allowedUppercaseFiles: []  // Disable all uppercase exceptions
    }]
  }
}

When Not To Use

ScenarioRecommendation
๐Ÿ›๏ธ Legacy codebaseUse ignore for existing files
โš›๏ธ React componentsConsider pascalCase or add to allowedPascalCase
๐Ÿงช Test filesUsually follows source file convention
๐Ÿ“ฆ Generated filesAdd to ignore patterns

Comparison with Alternatives

Featurefilename-caseeslint-plugin-unicornManual enforcement
Multiple casesโœ… 4 optionsโœ… YesโŒ No
Per-file overrideโœ… Flexibleโš ๏ธ LimitedโŒ No
LLM-Optimizedโœ… YesโŒ NoโŒ No
ESLint MCPโœ… OptimizedโŒ NoโŒ No

Further Reading

Known Limitations

  • A name with several dot-separated parts (user.controller.ts, vitest.config.ts) is checked as one name, dots included, so it conforms to no case; add such names to ignore.
  • An allowed<Case>Case entry exempts a name only when the name is written in that case.

Use this rule

npm install -D oxlint-plugin-conventions
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-conventions"],  "rules": {    "conventions/filename-case": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-conventions'],    rules: {      'conventions/filename-case': 'error',    },  },});

oxlint-plugin-conventions re-exports eslint-plugin-conventions/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it โ€” or follow the AI-code-security benchmarks behind these rules.