@kubit-ui-web/eslint-plugin-kubit
v0.0.9
Published
A lightweight ESLint plugin with custom rules for Kubit projects. Framework-agnostic, compatible with OxLint.
Maintainers
Readme
Kubit ESLint Plugin
A lightweight, composable ESLint plugin for TypeScript and React projects
Zero-config presets with all the rules from eslint-config-kubit, now as a proper ESLint plugin.
Compatible with OxLint and ESLint flat config.
Installation | Quick Start | Configs | Rules | Migration | Contributing
Why this plugin?
@kubit-ui-web/eslint-plugin-kubit replaces eslint-config-kubit with a better architecture:
| eslint-config-kubit (old) | @kubit-ui-web/eslint-plugin-kubit (new) |
| ------------------------------------- | -------------------------------------------------- |
| Opaque function that hides everything | Transparent, composable flat configs |
| ~15 plugins bundled as dependencies | All plugins bundled — one install, zero setup |
| Incompatible with OxLint | Use only what OxLint doesn't cover |
| isReact flag controls rule loading | Pick recommended or recommended-react |
| Must override to disable rules | Cherry-pick configs: base, typescript, react |
Requirements
- Node.js: >= 20.19.0
- ESLint: >= 9.0.0
Installation
All ESLint plugins come bundled — one install, zero extra setup:
# Using pnpm (recommended)
pnpm add -D eslint @kubit-ui-web/eslint-plugin-kubit
# Using npm
npm install --save-dev eslint @kubit-ui-web/eslint-plugin-kubitThat's it. All plugins (TypeScript, React, a11y, Prettier, Perfectionist, Jest, etc.) are included as direct dependencies and installed automatically.
Quick Start
TypeScript project (no React)
// eslint.config.js
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [
eslint.configs.recommended,
...tseslint.configs.recommended,
kubit.configs.recommended,
];React + TypeScript project
// eslint.config.js
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [
eslint.configs.recommended,
...tseslint.configs.recommended,
kubit.configs["recommended-react"],
];Minimal (only Kubit custom rules)
For projects using OxLint for standard rules:
// eslint.config.js
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [kubit.configs["kubit-rules"]];Available Configs
| Config | Description | Use case |
| ----------------------- | ------------------------------- | -------------------------- |
| recommended | All rules without React | ESLint only |
| recommended-react | All rules with React + a11y | ESLint only |
| oxlint | Only rules OxLint doesn't cover | ESLint + OxLint |
| kubit-rules | Only 2 Kubit custom rules | OxLint with minimal ESLint |
| base | General JS/ES6 rules | Cherry-pick |
| typescript | TypeScript-specific rules | Cherry-pick |
| react | React + a11y rules | Cherry-pick |
| compat | Browser compatibility | Optional |
Composing configs
You can mix and match individual configs:
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [
// Only TypeScript + kubit custom rules (no base JS rules)
kubit.configs.typescript,
kubit.configs["kubit-rules"],
];Overriding rules
All rules are visible and overridable:
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [
kubit.configs.recommended,
{
rules: {
// Override any rule from the preset
complexity: ["warn", { max: 10 }],
"@typescript-eslint/no-explicit-any": "off",
"no-console": "off",
// Configure kubit rules with your aliases
"kubit/no-index-import": [
"error",
{
aliases: {
"@/components": "./src/components/*",
"@/utils": "./src/utils/*",
},
},
],
},
},
];Custom Rules
Import & Export Rules
| Rule | Description | Auto-fix |
| -------------------------------------------------------------------------- | ------------------------------------------------ | -------- |
| kubit/no-index-import | Disallow imports from index/barrel files | ✅ |
| kubit/no-relative-import-paths | Enforce absolute import paths | ✅ |
| kubit/enforce-named-exports | Disallow default exports for better tree-shaking | - |
React / JSX Rules
| Rule | Description | Auto-fix |
| ---------------------------------------------------------- | ------------------------------------- | -------- |
| kubit/jsx-pascal-case | Enforce PascalCase for JSX components | - |
| kubit/no-multi-comp | One component per file | - |
| kubit/jsx-sort-props | Enforce sorted JSX props | ✅ |
| kubit/no-inline-styles | Disallow inline style={{}} in JSX | - |
Architecture Rules
| Rule | Description | Auto-fix |
| ---------------------------------------------------------------------------- | ------------------------------------------------------ | -------- |
| kubit/no-public-field-interface | Enforce behavior-only interfaces (methods, not fields) | - |
| kubit/no-framework-in-core | Prohibit framework imports inside /core/ | - |
| kubit/no-cross-boundary-import | Enforce architectural layer boundaries | - |
Using with OxLint
All 10 kubit rules work natively in OxLint via the jsPlugins feature.
Option A: ESLint config (only rules OxLint doesn't cover)
// eslint.config.js
const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
module.exports = [kubit.configs.oxlint];Option B: OxLint config (load kubit rules directly in OxLint)
Use the ready-made .oxlintrc.json presets from the oxlint/ directory.
Each preset already includes jsPlugins with a relative path, so the kubit plugin loads automatically:
// .oxlintrc.json
{
"extends": [
"./node_modules/@kubit-ui-web/eslint-plugin-kubit/oxlint/recommended.json",
],
}Or pick individual configs:
// .oxlintrc.json
{
"extends": [
"./node_modules/@kubit-ui-web/eslint-plugin-kubit/oxlint/base.json",
"./node_modules/@kubit-ui-web/eslint-plugin-kubit/oxlint/typescript.json",
"./node_modules/@kubit-ui-web/eslint-plugin-kubit/oxlint/architecture.json",
],
}Option C: Manual jsPlugins setup
Add the plugin directly to your .oxlintrc.json:
// .oxlintrc.json
{
"jsPlugins": [
{
"name": "kubit",
"specifier": "./node_modules/@kubit-ui-web/eslint-plugin-kubit/lib/index.js",
},
],
"rules": {
"kubit/no-index-import": "error",
"kubit/enforce-named-exports": "error",
"kubit/no-framework-in-core": "error",
"kubit/no-cross-boundary-import": "error",
"kubit/jsx-pascal-case": "error",
"kubit/no-multi-comp": "error",
"kubit/jsx-sort-props": [
"error",
{ "callbacksLast": true, "shorthandFirst": true, "reservedFirst": true },
],
"kubit/no-inline-styles": "error",
"kubit/no-public-field-interface": "error",
},
}OxLint presets
| Preset | Contents |
| -------------------------- | --------------------------------------------- |
| oxlint/recommended.json | Everything below combined |
| oxlint/base.json | JS quality + import/jest + kubit import rules |
| oxlint/typescript.json | TS rules + no-public-field-interface |
| oxlint/react.json | React + a11y + JSX kubit rules |
| oxlint/architecture.json | Layer boundaries + framework isolation |
Comparison: what each config includes
| Rule category | recommended | oxlint | kubit-rules |
| ------------------- | ------------- | -------- | ------------- |
| Kubit custom rules | 10 | 10 | 2 |
| Prettier formatting | 1 | 1 | - |
| JS code quality | ~25 | - | - |
| Import rules | 3 | - | - |
| Perfectionist | 3 | 3 | - |
| Jest | 2 | - | - |
| TypeScript | 11 | 3 | - |
| React + a11y | ~60 | - | - |
| Total rules | ~60+ | ~20 | 2 |
Migrating from eslint-config-kubit
See the full Migration Guide for step-by-step instructions.
TL;DR:
- const eslintFlatConfig = require("eslint-config-kubit");
- module.exports = eslintFlatConfig({ isReact: false, tsConfigPath: "..." });
+ const kubit = require("@kubit-ui-web/eslint-plugin-kubit");
+ module.exports = [kubit.configs.recommended];Development
pnpm install
pnpm test
pnpm test:watch
pnpm test:coverage
pnpm lintContributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
This project uses Changesets for automatic version management and publishing.
Documentation
License
Apache License 2.0 - see LICENSE for details.
Made with care by the Kubit Team
