Skip to content

Stacks & add-ons

A stack is your primary framework. An add-on layers extra rules onto any stack. You select one base stack and any number of add-ons — the installer and mocg() both speak this vocabulary.

Base stacks

StackFlagDetected fromExtra plugins installed
Node / TypeScript(default)always the basenone — all bundled
NestJSnest: true@nestjs/core, @nestjs/common@darraghor/eslint-plugin-nestjs-typed
Reactreact: truereact, react-domeslint-plugin-react, -react-hooks
Next.jsnext: truenext@next/eslint-plugin-next, eslint-plugin-react, -react-hooks, -react-refresh
Vuevue: truevue, nuxteslint-plugin-vue, vue-eslint-parser
  • Node is always present. Every other stack builds on it.
  • NestJS replaces the base call internally (it is Node + Nest rules), so you don't combine nest with raw Node.
  • React, Vue, and Next.js layer onto the Node base.
  • Next.js is React + Next rules, so it supersedes the React stack: a Next project (which depends on react and react-dom too) resolves to next only, and the React layer is applied exactly once.

Next.js

The Next.js stack is React + Next. createNextConfig() composes the React config and layers the official @next/eslint-plugin-next on top — applying its core-web-vitals rule set (which already includes recommended, plus the warn→error upgrades for no-html-link-for-pages and no-sync-scripts). It deliberately uses the plugin directly rather than eslint-config-next, which would re-bundle its own copies of eslint-plugin-react, -react-hooks, and typescript-eslint and clash with this package's tuning.

js
import { mocg } from 'eslint-config-mocg';

// Zero-config — `next` is auto-detected and supersedes the React stack.
export default mocg();

The stack supports both routers: it allows the non-component exports that the App Router (metadata, generateMetadata, generateStaticParams, …) and the Pages Router (getStaticProps, getServerSideProps, …) legitimately export, so react-refresh/only-export-components doesn't flag them. It also relaxes jsdoc/require-jsdoc for Route Handlers (route.ts) and middleware.ts, and ignores Next build artifacts (.next/, out/, next-env.d.ts).

The React Compiler rules are reused as-is for Next — there is no separate next-compiler. Opt in via the eslint-config-mocg/react-compiler export (see below).

React Compiler (opt-in)

The React stack does not enable the React Compiler rules by default, and eslint-plugin-react-compiler is an optional peer — it is not auto-installed. Enable it explicitly only if you run the React Compiler:

js
import { mocg } from 'eslint-config-mocg';
import reactCompiler from 'eslint-config-mocg/react-compiler';

const config = await mocg();

export default [...config, ...reactCompiler];
bash
npm i -D eslint-plugin-react-compiler

Vue: JS vs. TypeScript SFCs

Vue single-file components can be parsed for plain JS or type-aware TS. Opt into the TypeScript parser chain with vueTs:

js
mocg({ vue: true, vueTs: true });

Remember to include *.vue in your tsconfig.json and ESLint file globs, and add a *.vue type shim (declare module '*.vue') so import App from './App.vue' type-resolves under the TypeScript parser. PascalCase is enforced on SFC filenames only (not directories), and Prettier — not eslint-plugin-vue — owns SFC formatting.

Add-ons

Add-onFlagDetected fromBundled?
Vite (React Fast Refresh)vite: trueviteneeds eslint-plugin-react-refresh
Vitestvitest: truevitest✅ ships with the package
Jestjest: truejest, @jest/globalsneeds eslint-plugin-jest
Zodzod: truezod✅ ships with the package
i18nexti18n: truei18next, react-i18next, vue-i18nneeds eslint-plugin-i18next
Tailwind CSStailwind: truetailwindcssneeds eslint-plugin-better-tailwindcss

Bundled add-ons require no extra install — their plugins ship as dependencies of this package.

Vite Fast Refresh

Fast Refresh is a bundler/HMR concern, so the React stack itself is pristine — it no longer bakes in the Vite preset. Instead, the vite add-on supplies react-refresh's vite preset (allowConstantExport) and is auto-enabled whenever a project depends on vite. So a mocg() Vite + React project keeps Fast Refresh linting with no change. The only consumers that need to act are those who import the eslint-config-mocg/react subpath directly (not via mocg()): add eslint-config-mocg/vite alongside it.

Putting it together

js
import { mocg } from 'eslint-config-mocg';

// A NestJS service tested with Vitest, using Zod schemas:
export default mocg({
  nest: true,
  vitest: true,
  zod: true,
});
js
// A React app with Tailwind and i18n — everything auto-detected:
export default mocg();

Each flag may be true (force on), false (force off), or omitted (auto-detect). See How it works.

Internal tooling — Master of Code Global