npm package: @gcolotti/frontend-config
Description: Shared ESLint and Prettier config package with a setup CLI for React, TypeScript, and Tailwind projects.
Author: Guillermo Colotti
Latest version: 0.3.3

# `@gcolotti/frontend-config`

Shared ESLint and Prettier config package with a setup CLI for React, TypeScript, and Tailwind projects.

This package gives you:

- shared configs you can import from `@gcolotti/frontend-config`
- a CLI that installs the local lint/format toolchain
- managed wrapper files in the consumer project
- optional local overrides only when you actually need them

## Quick Start

If the package is not installed yet:

```sh
npx @gcolotti/frontend-config --install
```

If you prefer to keep it as a dev dependency first:

```sh
npm install -D @gcolotti/frontend-config
npm exec gcolotti-frontend-config -- --install
```

After setup, the consumer project keeps `@gcolotti/frontend-config` in `devDependencies`, plus the local ESLint/Prettier toolchain.

## What The CLI Generates

On a clean install, the CLI creates:

- `eslint.config.mjs`
- `prettier.config.mjs`
- `.prettierignore`
- `.vscode/settings.json`
- `.vscode/extensions.json`

It also adds these scripts to `package.json` when missing:

- `frontend-config:install`
- `frontend-config:update`
- `lint`
- `format`
- `format:check`

The generated config files are managed wrappers:

- `eslint.config.mjs` imports `@gcolotti/frontend-config/eslint`
- `prettier.config.mjs` imports `@gcolotti/frontend-config/prettier`

By default, the wrappers do not create local override files.

## Public Config Exports

The package exposes these shared configs:

- `@gcolotti/frontend-config/eslint`
- `@gcolotti/frontend-config/eslint/no-type-aware`
- `@gcolotti/frontend-config/prettier`

Type-aware linting is enabled by default in `@gcolotti/frontend-config/eslint`.

If you want the generated wrapper to opt out explicitly:

```sh
npx @gcolotti/frontend-config --install --no-type-aware
```

## Install And Update Flow

First-time setup:

```sh
npx @gcolotti/frontend-config --install
```

Update managed files later:

```sh
npx @gcolotti/frontend-config --update
```

Or, once the package is installed locally:

```sh
npm run frontend-config:install
npm run frontend-config:update
```

`--update` refreshes managed wrappers and editor files, but preserves:

- `*.overrides.mjs`
- `*.legacy.*`
- existing conflicting editor values in `.vscode/settings.json`

## Conflict Handling

If the CLI finds an existing config, it classifies it before writing anything:

- `managed`: already generated by this package, so it can be refreshed
- `simple-adoptable`: safe to preserve as a local override
- `complex-conflicting`: too dynamic or legacy to adopt automatically

When a simple config is detected and you choose to preserve it:

```sh
npx @gcolotti/frontend-config --install --adopt
```

When you want to replace a previous config but still get a local override stub:

```sh
npx @gcolotti/frontend-config --install --replace
```

If you want to leave an existing config alone:

```sh
npx @gcolotti/frontend-config --install --skip-existing
```

In non-interactive environments, the CLI aborts on conflicts and tells you which explicit flag to use.

## Overrides

Override files are only generated when there is a conflict and you choose `--adopt` or `--replace`:

- `eslint.config.overrides.mjs`
- `prettier.config.overrides.mjs`

That keeps clean installs minimal while still giving you a safe place for local customizations when needed.

## Legacy Backups

When the CLI adopts or replaces an existing config, it creates timestamped backup files before writing the managed wrapper.

Examples:

- `eslint.config.legacy.20260329182256.mjs`
- `prettier.config.legacy.20260329182256.mjs`
- `eslint.package-json.legacy.20260329182256.json`

These files are intentional. They let you recover the previous config if you want to compare, merge, or roll back manual settings after switching to the managed setup.

The CLI does not delete legacy backups automatically, and `--update` leaves them in place.

## What Gets Installed In The Consumer

The CLI ensures these local `devDependencies` exist in the target project:

- `@gcolotti/frontend-config`
- `eslint`
- `prettier`
- `typescript`
- `tailwindcss`
- `@eslint/js`
- `typescript-eslint`
- `eslint-plugin-react`
- `eslint-plugin-react-hooks`
- `eslint-plugin-jsx-a11y`
- `eslint-plugin-simple-import-sort`
- `eslint-plugin-unused-imports`
- `prettier-plugin-tailwindcss`
- `globals`

This package does not install your app framework or runtime packages such as `react`, `next`, `vite`, or `laravel`.

When the target project uses Tailwind CSS v3, the CLI also installs `eslint-plugin-tailwindcss`.
When it detects Tailwind CSS v4 or newer, it skips that plugin to avoid npm peer dependency conflicts.

## Editor Integration

For VS Code and Cursor workspaces, the CLI also manages:

- `.vscode/settings.json`
- `.vscode/extensions.json`

It adds:

- `editor.formatOnSave: true`
- `editor.codeActionsOnSave.source.fixAll.eslint: "explicit"`
- Prettier as the default formatter for JavaScript, TypeScript, and JSON files
- ESLint and Prettier extension recommendations

## Prettier Defaults

The shared Prettier config enforces:

- `singleQuote: true`
- `semi: false`
- Tailwind class sorting through `prettier-plugin-tailwindcss`
- `tabWidth: 2` for JavaScript and TypeScript source files, including `js`, `jsx`, `ts`, `tsx`, `mjs`, `cjs`, `mts`, and `cts`

## Tailwind Rules

These Tailwind rules are enforced as `error`:

- `tailwindcss/no-unnecessary-arbitrary-value`
- `tailwindcss/classnames-order`
- `tailwindcss/enforces-shorthand`

Tailwind v3 keeps the extra Tailwind ESLint rules because it matches the current `eslint-plugin-tailwindcss` peer dependency range. For Tailwind v4+, the shared config now skips those plugin-powered rules automatically so the package can install cleanly without peer dependency conflicts.

## License

MIT. See [LICENSE](./LICENSE).