@black-bytes/eslint-config
v0.2.0
Published
Black Bytes ESLint config - base and react
Downloads
361
Keywords
Readme
@black-bytes/eslint-config
Reusable ESLint flat-config presets for Black Bytes projects.
Installation
Add the package alongside its peer dependencies in your project:
yarn add -D @black-bytes/eslint-config eslint typescript
# or
npm install -D @black-bytes/eslint-config eslint typescriptWhen consuming a local build, point to the workspace directory:
yarn add -D file:/path/to/eslint-configUsage
Reference the presets from your eslint.config.js (or eslint.config.mjs) file together with your usual flat-config helpers.
For example:
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import blackBytesEslintConfig from '@black-bytes/eslint-config'
export default defineConfig([
globalIgnores(['<ignored-directories-or-files>']),
{
files: ['**/*.{ts,tsx}'],
extends: [
blackBytesEslintConfig.base,
blackBytesEslintConfig.react,
blackBytesEslintConfig.next, // only for Next.js projects
// additional presets or plugin configs
],
// additional options
},
])Import a single preset when you only need one of them:
import { defineConfig } from 'eslint/config'
import { base as baseConfig } from '@black-bytes/eslint-config'
export default defineConfig([
baseConfig,
// project-specific overrides
])All presets assume ESLint's Project Service is enabled, so TypeScript projects get typed linting out of the box.
Available presets
base: Core JavaScript/TypeScript rules, including stylistic and import guidelines.react: React, React Hooks, and JSX accessibility rules layered on top of the base expectations.next: Next.js-specific rules (core-web-vitals preset). Use only in Next.js projects, layered on top ofbaseandreact. Disablesimport/no-default-exportbecause Next.js requires default exports for pages, layouts, and routes.
Mandatory best practices
General
- Isolate type definitions: Declare shared types in dedicated
*.types.tsfiles. This prevents circular fixes issues in the linter config and keeps domain models discoverable.
:warning: this is important to avoid linter conflicts
// ui.types.ts
export interface IButtonProps {
label: string
onClick: () => void
}
export type TButtonVariant = 'primary' | 'ghost'- Apply consistent TS naming: Prefix interfaces with
Iand exported type aliases withTto distinguish structural contracts from concrete types at a glance. Example:IUser,IPermission,TRole,TButton.
export interface IUser {
// ...
}
export type TRole = {
// ...
}- Eliminate magic numbers: Lift numeric literals into constant maps, then export the derived union type via
keyof typeof(in a separate file). This ensures consumers reuse the same source of truth.
// constants/metrics.ts
export const METRICS_THRESHOLDS = {
warning: 50,
critical: 75,
} as const
// types/metrics.types.ts
export type TMetricThreshold = keyof typeof METRICS_THRESHOLDSReact
- Avoid inline handlers: Do not allocate arrow functions inside JSX props. Extract them into named callbacks so React can leverage referential equality and avoid redundant renders.
// discouraged
<Button onClick={() => doSomethingCool()} />
// required
const handleClick = () => doSomethingCool()
return <Button onClick={handleClick} />- Pre-compute derived props: Keep logical expressions and computed values out of JSX props. Materialize them in variables before rendering to improve readability and memoization.
// discouraged
<Card disabled={noData || isLoading} />
<Badge className={getClassName('badge', noData || isLoading)} />
// required
const isDisabled = noData || isLoading
const badgeClassName = getClassName('badge', isDisabled)
return (
<>
<Card disabled={isDisabled} />
<Badge className={badgeClassName} />
</>
)Next.js
- Default exports for app structure: The
nextpreset disablesimport/no-default-exportbecause Next.js requires default exports for pages, layouts, routes, and similar app structure files. Use the preset only in Next.js projects, layered on top ofbaseandreact.
