ESLint plugin for enforcing styling conventions in Next.js + Vanilla Extract projects.
npm install --save-dev @napolab/eslint-plugin typescript
# or
pnpm add -D @napolab/eslint-plugin typescript
# or
yarn add -D @napolab/eslint-plugin typescript- ESLint >= 8.0.0
- TypeScript >= 4.0.0
Add the plugin to your ESLint configuration:
// eslint.config.js
import napolabPlugin from "@napolab/eslint-plugin";
export default [
{
plugins: {
"@napolab": napolabPlugin,
},
rules: {
"@napolab/enforce-styling": "error",
"@napolab/no-container-wrapper-names": "error",
"@napolab/no-child-selectors": "error",
"@napolab/max-style-name-words": "error",
"@napolab/enforce-layout-component-name": "error",
"@napolab/enforce-page-component-name": "error",
"@napolab/prefer-array-at": "error",
},
},
];| Rule | Description | TDD |
|---|---|---|
| enforce-styling | Enforce that component files import styles from their corresponding CSS files | ✅ |
| no-container-wrapper-names | Forbid generic container/wrapper names in *.css.ts files |
✅ |
| no-child-selectors | Forbid child selectors in Vanilla Extract style definitions | ✅ |
| max-style-name-words | Enforce maximum word count in style names to encourage component decomposition | ✅ |
| Rule | Description | TDD |
|---|---|---|
| prefer-array-at | Enforce using .at() method instead of array bracket notation for accessing elements | ✅ |
| Rule | Description | TDD |
|---|---|---|
| enforce-layout-component-name | Enforce that layout.tsx files export a component named Layout |
✅ |
| enforce-page-component-name | Enforce that page.tsx files export a component named Page |
✅ |
This plugin enforces consistent styling patterns for Next.js applications using Vanilla Extract:
- Flexible Configuration: Use the
enforce-stylingrule to configure different style patterns for different file types - Consistent Imports: All style imports use namespace imports (
import * as styles) - Clear Naming: Avoid generic names like
containerorwrapperin favor of more descriptive names - Component Granularity: Enforce component decomposition when style names become too complex (3+ words)
- Type Safety: All rules use proper type guards for safe type narrowing
This plugin is developed using:
- TDD (Test-Driven Development): All rules follow Red-Green-Refactor cycles
- KISS Principle: Keep implementations simple and focused
- DRY Principle: Abstracted
enforce-stylingrule to avoid code duplication - SOLID Principles: Single responsibility, open/closed, and other design principles
- YAGNI Principle: Only implement what's actually needed
src/
├── app/
│ ├── layout.tsx # imports from ./layout.css
│ ├── layout.css.ts # layout styles
│ ├── page.tsx # imports from ./styles.css
│ ├── styles.css.ts # page styles
│ └── dashboard/
│ ├── layout.tsx # imports from ./layout.css
│ ├── layout.css.ts # dashboard layout styles
│ ├── page.tsx # imports from ./styles.css
│ └── styles.css.ts # dashboard page styles
└── components/
└── button/
├── index.tsx # imports from ./styles.css
└── styles.css.ts # button component styles
MIT
Issues and pull requests are welcome at GitHub Repository.