Sharable ESLint configuration preset for Poupe UI projects with TypeScript, Vue.js, and Tailwind CSS support.
✅ Includes:
- eslint recommended rules
- stylistic recommended formatting rules
- typescript-eslint integration
- unicorn rules
- perfectionist rules for import/export and union type sorting
- vue recommended rules with TypeScript support
- tsdoc rules for TypeScript documentation
- markdownlint rules for Markdown files
- jsonc rules for JSON and package.json files
- css rules for CSS files with Tailwind CSS support
- Poupe UI recommended rules
Note
This preset uses the new ESLint flat config format and requires ESLint v9+ and Node.js v18.20.8+.
Install dependencies:
pnpm install -D eslint typescript @poupe/eslint-configCreate eslint.config.mjs in your project root:
// @ts-check
import poupeConfig from '@poupe/eslint-config';
export default poupeConfig;For Nuxt.js applications (with @nuxt/eslint):
// @ts-check
import { forNuxt } from '@poupe/eslint-config/nuxt';
import withNuxt from './.nuxt/eslint.config.mjs';
export default withNuxt(...forNuxt({
rules: {
// custom rule overrides
},
}));For Nuxt modules (with @nuxt/eslint-config):
// @ts-check
import { createConfigForNuxt } from '@nuxt/eslint-config/flat';
import { forNuxtModules } from '@poupe/eslint-config/nuxt';
export default createConfigForNuxt({
features: {
tooling: true, // Enables rules for module authors
stylistic: true, // Enables formatting rules
},
}, ...forNuxtModules());Custom configuration:
// @ts-check
import { defineConfig } from '@poupe/eslint-config';
export default defineConfig({
rules: {
// rule overrides
},
});This configuration includes advanced CSS linting with Tailwind CSS v4 syntax support. The CSS configuration uses an intelligent filtering system that:
- Applies CSS-specific rules from
@eslint/css - Supports Tailwind CSS v4 syntax including theme functions and modifiers
- Automatically disables JavaScript-specific rules for CSS files
- Keeps relevant cross-language rules (like
filename-casefrom unicorn)
The filtering system categorizes plugins and rules to ensure only appropriate rules apply to CSS files. See AGENT.md for implementation details.
This configuration automatically lints the following file types:
- JavaScript:
.js,.mjs,.cjs - TypeScript:
.ts,.tsx - Vue.js:
.vue(Single File Components) - JSON/JSONC:
.json,.jsonc,package.json - Markdown:
.md - CSS:
.css(with Tailwind CSS v4 syntax support)
This package uses its own ESLint configuration for validation, ensuring quality and serving as a real-world test case.
This configuration includes eslint-plugin-perfectionist which automatically
organizes your imports and exports. The sorting happens automatically when you
run eslint --fix or save files with ESLint auto-fix enabled in your editor:
// Before
import { z } from 'zod';
import React from 'react';
import { useState, useEffect } from 'react';
import { Button } from './components/Button';
import axios from 'axios';
import type { User } from '../types';
import { config } from './config';
// After (automatically fixed by ESLint)
import type { User } from '../types';
import axios from 'axios';
import React from 'react';
import { z } from 'zod';
import { config } from './config';
import { Button } from './components/Button';
import { useEffect, useState } from 'react';The configuration also includes automatic sorting of TypeScript union types with
perfectionist/sort-union-types. Union members are sorted in natural order,
and you can use comments to create logical groups:
// Before
type Status = 'error' | 'loading' | 'success' | 'idle';
// After (automatically fixed by ESLint)
type Status = 'error' | 'idle' | 'loading' | 'success';
// With comment-based grouping
type Status =
// Active states
| 'loading'
| 'processing'
// Inactive states
| 'error'
| 'idle'
| 'success';// @ts-check
import { defineConfig } from '@poupe/eslint-config';
export default defineConfig({
rules: {
// Disable specific rules
'unicorn/filename-case': 'off',
// Customize rule severity and options
'@typescript-eslint/no-unused-vars': ['warn', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
},
});// @ts-check
import { configs, withConfig } from '@poupe/eslint-config';
// Import only specific configurations
export default withConfig(
configs.javascript,
configs.typescript,
configs.stylistic,
configs.vue,
// Add custom overrides
{
rules: {
'vue/multi-word-component-names': 'off',
},
},
);In addition to the rules from included plugins, this configuration adds these custom rules:
- Enforces explicit return types on exported functions
- Requires consistent type imports (
import type) - Disables
@ts-comment directives
- Enforces multi-word component names
- Requires
defineEmitsanddefinePropstype declarations - Ensures proper
v-modelusage patterns
- Enforces camelCase naming convention
- Allows
i,j,kas loop counters and array indices - Requires explicit radix in
parseInt - Prevents console statements in production code
- Single quotes for strings
- Semicolons required
- 1tbs (one true brace style)
- 2-space indentation for web files
- 80-character line limit for Markdown
If you're migrating from a legacy .eslintrc configuration:
-
Remove old config files: Delete
.eslintrc,.eslintrc.js,.eslintrc.json, etc. -
Update dependencies:
pnpm remove eslint-config-* eslint-plugin-* pnpm install -D eslint@^9 typescript @poupe/eslint-config
-
Create new config: Add
eslint.config.mjsas shown in Getting Started -
Update scripts: ESLint v9 automatically finds
eslint.config.mjs{ "scripts": { "lint": "eslint .", "lint:fix": "eslint . --fix" } } -
Handle breaking changes:
- Some rules have been renamed or moved to different plugins
- The flat config uses different property names (
filesinstead ofoverrides) - Plugin names are now used as object keys instead of strings
The examples/ directory contains working examples demonstrating how to use
this ESLint configuration in different scenarios:
- playground-standard - Basic JavaScript/TypeScript projects
- playground-nuxt - Nuxt.js applications
- playground-nuxt-module - Nuxt module development
This project uses pnpm workspaces. You can run commands on all examples:
# Install dependencies for all workspaces
pnpm install
# Lint all examples
pnpm -r --filter "./examples/*" lint
# Fix lint issues in all examples
pnpm -r --filter "./examples/*" lint:fix
# Run a specific example
pnpm --filter "@poupe/eslint-config-playground-standard" lintEnsure you've installed the package and are using the correct import path:
pnpm install -D @poupe/eslint-configFor Nuxt applications, make sure to use the appropriate helper:
- Use
forNuxt()for Nuxt applications - Use
forNuxtModules()for Nuxt module development
This should not happen with the default configuration. If it does, ensure you're using the latest version and report an issue.
These warnings help the CSS filtering system learn about new rules. They're informational and don't affect functionality.
To debug ESLint configuration issues:
# Show resolved configuration for a specific file
eslint --print-config path/to/file.js
# Enable ESLint debug output
DEBUG=eslint:* eslint .
# Debug specific aspects
DEBUG=eslint:eslint eslint .For AI assistants working with this codebase, refer to AGENT.md for detailed guidance and conventions.
src/
├── configs/ # Individual ESLint rule configurations
├── core/ # Core utilities and type definitions
├── config.ts # Main configuration builder
├── configs.ts # Configuration presets
├── index.ts # Main entry point
└── nuxt.ts # Nuxt-specific configurations
- Make changes to configuration files in
src/configs/ - Run
pnpm buildto compile the package - Test with
pnpm lint(self-linting) - Test in examples:
pnpm -r --filter "./examples/*" lint
MIT