# Built-in plugins

> Get accurate results with zero configuration. Built-in plugins detect Next.js, Vite, Jest, Tailwind, ESLint, and many other tools, and tell fallow which files and exports each tool uses.

> Page index of all docs: https://fallow.tools/llms.txt
> Docs MCP server (search and read the docs): https://fallow.tools/docs/mcp
> HTML version of this page: https://fallow.tools/docs/frameworks/built-in/

Built-in plugins give you accurate results without configuration. Without a plugin, fallow can report a route file, a config file, or a tool dependency as unused, because no import reaches it.

Fallow has built-in plugins for popular TypeScript and JavaScript tools. Each plugin tells fallow the conventions of one framework or tool: entry points, config files, used exports, and tooling dependencies.

> **Info:** Most plugins activate automatically when the relevant package is in your `package.json`. Some plugins (ESLint, Vitest) also activate when a config file is present in the workspace root, even without the package. This covers a monorepo that installs the tool at the root and gives the workspace packages their own config files.

#### Frameworks

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Next.js** | `next` |
| **Nuxt** | `nuxt`, `@nuxt/kit` |
| **Pinia** | `@pinia/nuxt` |
| **Remix** | `@remix-run/node`, `@remix-run/react`, `@remix-run/cloudflare`, `@remix-run/cloudflare-pages`, `@remix-run/deno` |
| **SvelteKit** | `@sveltejs/kit` |
| **Gatsby** | `gatsby` |
| **Astro** | `astro` |
| **Angular** | `@angular/core`, `ng-packagr` |
| **Ionic** | `@ionic/angular` |
| **React Router** | `@react-router/dev` |
| **RedwoodSDK** | `rwsdk` (keeps `src/worker.{ts,tsx,js,jsx,mts,mjs}` reachable in `rwsdk/vite` apps) |
| **TanStack Router** | `@tanstack/react-router`, `@tanstack/solid-router`, `@tanstack/start`, `@tanstack/react-start`, `@tanstack/solid-start`, `@tanstack/virtual-file-routes` |
| **React Native** | `react-native` |
| **Expo** | `expo` |
| **Firebase** | `firebase` |
| **NestJS** | `@nestjs/core` |
| **nest-commander** | `nest-commander` (credits the `run` method of each class that extends `CommandRunner`) |
| **AdonisJS** | `@adonisjs/core` |
| **Docusaurus** | `@docusaurus/core` |
| **Nitro** | `nitropack` |
| **Capacitor** | `@capacitor/core`, `@capacitor/cli` |
| **Sanity** | `sanity`, `@sanity/` |
| **VitePress** | `vitepress` |
| **next-intl** | `next-intl` |
| **Relay** | `relay-runtime`, `react-relay`, `relay-compiler` |
| **Electron** | `electron`, `electron-builder`, `@electron-forge/cli`, `electron-vite` |
| **Qwik** | `@builder.io/qwik`, `@builder.io/qwik-city`, `@qwik.dev/core`, `@qwik.dev/router` |
| **i18next** | `i18next`, `react-i18next`, `vue-i18n`, `next-i18next` |
| **Wuchale** | `wuchale`, `@wuchale/vite-plugin`, or `wuchale.config.js` |
| **Convex** | `convex`; the safe in-project directory from `convex.json#functions` becomes the functions entry root when configured |
| **Lit** | `lit`, `lit-element`, `@lit/reactive-element` (native Custom Elements lifecycle methods are credited without a Lit dependency) |
| **Lexical** | `lexical`, `@lexical/` (credits custom node lifecycle methods on `DecoratorNode`, `ElementNode`, `TextNode` subclasses) |
| **Ember** | `ember-source`, `ember-cli`, `@embroider/core`, `@embroider/compat`, `@glimmer/component` |
| **Expo Router** | `expo-router` |
| **Supabase** | `supabase`, or `supabase/config.toml` / `supabase/functions/` present (treats `supabase/functions/*/index.*` as runtime entry roots) |
| **Content Collections** | `@content-collections/core`, `@content-collections/vite`, `@content-collections/next`, `@content-collections/solid-start`, `@content-collections/remix-vite`, `@content-collections/qwik`, `@content-collections/vinxi` |
| **Contentlayer** | `contentlayer`, `contentlayer2`, `next-contentlayer`, `next-contentlayer2`, or `contentlayer.config.{ts,js,mts,mjs}` present |
| **Fumadocs** | `fumadocs-mdx`, `fumadocs-core`, `fumadocs-ui`, or `source.config.*` present |
| **Mintlify** | `mint`, `mintlify`, or `docs.json` / `mint.json` present |
| **Velite** | `velite`, or `velite.config.{ts,mts,cts,js,mjs,cjs}` present |
| **rspress** | `rspress`, `@rspress/` (credits the `@theme` / `@theme-original` virtual modules) |
| **Obsidian** | `obsidian` |
| **Browser extension** | `webextension-polyfill`, `@types/chrome`, `@types/firefox-webext-browser` |
| **WXT** | `wxt`, `@wxt-dev/` |
| **VS Code extension** | `vscode`, `@types/vscode`, `@vscode/test-electron` |

#### Bundlers

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Vite** | `vite`, `rolldown-vite` |
| **Webpack** | `webpack` |
| **Rspack** | `@rspack/core`, `@rspack/cli` |
| **Rsbuild** | `@rsbuild/core` |
| **Rollup** | `rollup` |
| **Rolldown** | `rolldown` |
| **Tsup** | `tsup` |
| **Tsdown** | `tsdown` |
| **pkg-utils** | `@sanity/pkg-utils` |
| **Parcel** | `parcel`, `@parcel/` |
| **Module Federation** | `@module-federation/enhanced`, `@module-federation/modern-js`, `@module-federation/nextjs-mf`, `@module-federation/node`, `@module-federation/rsbuild-plugin`, `@module-federation/rspack`, `@module-federation/runtime`, `@module-federation/vite`, `@module-federation/webpack-bundler-runtime`, `@originjs/vite-plugin-federation` |

#### Testing

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Vitest** | `vitest` or config file present |
| **Jest** | `jest` |
| **Playwright** | `@playwright/test` |
| **Cypress** | `cypress` |
| **Mocha** | `mocha` |
| **Ava** | `ava` |
| **tap** | `tap` |
| **tsd** | `tsd` |
| **Storybook** | `storybook`, `@storybook/` |
| **Karma** | `karma` |
| **Cucumber** | `@cucumber/cucumber` |
| **WebdriverIO** | `webdriverio`, `@wdio/` |
| **k6** | `k6`, or `*.k6.{js,ts,mjs,cjs,mts,cts}` files present |
| **Stryker** | `@stryker-mutator/core`, `stryker`, or config file present |

#### Linting & Formatting

| Plugin | Enabler packages |
|:-------|:-----------------|
| **ESLint** | `eslint`, `@eslint/js`, or config file present |
| **Biome** | `@biomejs/biome` |
| **Stylelint** | `stylelint` |
| **Prettier** | `prettier` |
| **Oxfmt** | `oxfmt` |
| **Oxlint** | `oxlint` |
| **markdownlint** | `markdownlint`, `markdownlint-cli`, `markdownlint-cli2` |
| **CSpell** | `cspell` |
| **Remark** | `remark`, `remark-cli` |

#### Transpilation

| Plugin | Enabler packages |
|:-------|:-----------------|
| **TypeScript** | `typescript` |
| **Babel** | `@babel/core` |
| **SWC** | `@swc/core`, `@swc/cli` |

#### CSS

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Tailwind** | `tailwindcss`, `@tailwindcss/postcss` |
| **PostCSS** | `postcss` |
| **UnoCSS** | `unocss`, `@unocss/*` |
| **PandaCSS** | `@pandacss/dev` |

#### Database

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Prisma** | `prisma`, `@prisma/client` |
| **Drizzle** | `drizzle-orm` |
| **Knex** | `knex` |
| **TypeORM** | `typeorm` |
| **Kysely** | `kysely`, `kysely-ctl` |

#### Monorepo

| Plugin | Enabler packages |
|:-------|:-----------------|
| **Turborepo** | `turbo` |
| **Nx** | `nx` |
| **Kibana** | a `kibana.jsonc` manifest present |
| **Changesets** | `@changesets/cli` |
| **Syncpack** | `syncpack` |
| **pnpm** | `pnpm-workspace.yaml` or `pnpm-lock.yaml` present |

#### CI/CD & Release

| Plugin | Enabler packages |
|:-------|:-----------------|
| **semantic-release** | `semantic-release` |
| **Commitlint** | `@commitlint/cli` |
| **Commitizen** | `commitizen` |
| **commit-and-tag-version** | `commit-and-tag-version`, `standard-version` |
| **Vercel** | `vercel`, `@vercel/config` |
| **Wrangler** | `wrangler` |
| **OpenNext Cloudflare** | `@opennextjs/cloudflare`, or an `opennextjs-cloudflare` command in a `package.json` script |
| **Sentry** | `@sentry/nextjs`, `@sentry/react`, `@sentry/node`, `@sentry/browser` |
| **Danger** | `danger` |

#### Git Hooks

| Plugin | Enabler packages |
|:-------|:-----------------|
| **husky** | `husky` |
| **lint-staged** | `lint-staged` |
| **lefthook** | `lefthook`, `@evilmartians/lefthook` |
| **simple-git-hooks** | `simple-git-hooks` |

#### Other

| Plugin | Enabler packages |
|:-------|:-----------------|
| **GraphQL Codegen** | `@graphql-codegen/cli` |
| **TypeDoc** | `typedoc` |
| **openapi-ts** | `openapi-typescript` |
| **Plop** | `plop` |
| **SVGO** | `svgo` |
| **SVGR** | `@svgr/core`, `@svgr/cli`, `@svgr/webpack`, `@svgr/rollup`, `@svgr/vite` |
| **size-limit** | `size-limit` (credits `@size-limit/*` and `size-limit-*` presets and plugins) |
| **c8** | `c8` |
| **nyc** | `nyc` |
| **MSW** | `msw` |
| **nodemon** | `nodemon` |
| **PM2** | `pm2` |
| **dependency-cruiser** | `dependency-cruiser` |
| **Hardhat** | `hardhat` |
| **Bun** | `bun-types`, `@types/bun` |
| **Deno** | `deno.json` or `deno.jsonc` present |
| **napi-rs** | A `napi` field with `targets` in `package.json`, plus `optionalDependencies` |
| **Varlock** | `varlock`, `@varlock/`, or `.env.schema` present |
| **OpenCode** | `opencode.json`, `.opencode/`, or `@opencode-ai/` (credits auto-loaded plugin files and `opencode.json` plugin dependencies) |

### Plugins with deep config parsing {#plugins-with-deep-config-parsing}

These plugins do more than detect a package. They parse your config files with the Oxc AST parser and extract entry points, dependencies, aliases, and other settings automatically:

| Plugin | What it extracts |
|:-------|:-----------------|
| **ESLint** | Plugin imports, shared configs, custom rule paths, import resolver packages |
| **Vitest** | Reporters, coverage provider, typecheck checker, browser provider from `vitest.config.ts` |
| **Vite** | Entry points, `resolve.alias` mappings, plugin imports from `vite.config.ts` and from named configs such as `vite.config.lib.ts`. The SWC plugins in the `plugins` option of `@vitejs/plugin-react-swc` and the Babel plugins and presets in the `babelOptions` of `@wyw-in-js/vite` count as used dependencies |
| **Jest** | Setup files, transform paths, module mappers, and test patterns from `jest.config.*`, `jest-*.config.*`, and `jest.*.config.*`. See [Jest configs](https://fallow.tools/docs/frameworks/built-in/#jest-configs) |
| **tsd** | Declaration test directory from `package.json#tsd.directory` |
| **Storybook** | Story globs, addon imports from `.storybook/main.ts`. Fallow resolves each `stories` pattern against the `.storybook/` directory, as Storybook does. See [Storybook stories](https://fallow.tools/docs/frameworks/built-in/#storybook-stories) |
| **Tailwind** | Content paths, plugin imports from `tailwind.config.js` |
| **Webpack** | Entry points including descriptor/context forms, `resolve.alias` mappings, loader/plugin imports from `webpack.config.js`. An `entry` value that names a package instead of a file credits that dependency, with the resource query included (`webpack-hot-middleware/client?reload=true` credits `webpack-hot-middleware`). A glob-shaped value stays an entry pattern. Fallow also reads a config under `config/`, `build/` or `webpack/` when it exports a webpack configuration; see [config directories](https://fallow.tools/docs/frameworks/built-in/#webpack-config-directories). Inline loader requests (`!raw-loader!./file.js`) resolve to their resource; see [inline loader requests](https://fallow.tools/docs/frameworks/built-in/#webpack-inline-loader-requests) |
| **TypeScript** | Path aliases, project references from `tsconfig.json` |
| **Babel** | Plugin and preset imports from `babel.config.js` |
| **Rollup** | Entry points, plugin imports from `rollup.config.js` and from named configs such as `rollup.config.esm.js` |
| **Rolldown** | Entry points, external deps, plugin imports from `rolldown.config.ts` |
| **PostCSS** | Plugin imports from `postcss.config.js` |
| **Nuxt** | Modules, plugins, server routes, `alias`, `imports.dirs`, `components`, `srcDir` from `nuxt.config.ts`. Fallow reads the config of each root separately: the project root and every workspace root. The custom `components:` or `imports:` shape of one app decides the [`autoImports`](https://fallow.tools/docs/configuration/overview/#autoimports) verdict for that root only. See [local layers](https://fallow.tools/docs/frameworks/built-in/#nuxt-local-layers) |
| **SvelteKit** | `kit.alias` mappings, param matchers from `svelte.config.js` |
| **Next.js** | App Router convention exports (`page`, `layout`, `loading`, `error`, `route`), route segment config, Pages Router exports, middleware, proxy, instrumentation, `mdx-components`, `transpilePackages`. The packages in `experimental.swcPlugins` count as used dependencies |
| **NestJS** | The schematics package that `collection` names in `nest-cli.json` counts as a used dependency |
| **Rsbuild** | Entry points, plugin imports from `rsbuild.config.ts`. A `source.entry` value that names a package credits that dependency, with the resource query included. A glob-shaped value stays an entry pattern. `root` applies to a relative entry, the same way `context` applies for Rspack |
| **Rspack** | Entry points, plugin imports from `rspack.config.js`. An `entry` value that names a package credits that dependency, with the resource query included. A glob-shaped value stays an entry pattern. `context` applies to a relative entry. An entry without an extension matches the source file or the directory index |
| **Remark** | Plugin imports from `.remarkrc.js` |
| **Angular** | Styles, scripts, main, polyfills from `angular.json` build targets. The ng-packagr `lib.entryFile` in `ng-package.json` or `ng-package.prod.json` (default `src/public_api.ts`, resolved relative to the config directory) becomes a library public API entry point. Fallow also scans nested secondary-entry-point configs in the package subtree. `@Component({ templateUrl, styleUrl })` decorator references create graph edges. Standalone `.html` templates and inline `template:` literals both add synthetic `<template>` complexity findings (`@if`/`@for`/`@switch`/`@defer`, `*ngIf`, bound attributes, interpolations). To suppress them, use `<!-- fallow-ignore-file complexity -->` (external) or `// fallow-ignore-next-line complexity` above the `@Component` decorator (inline) |
| **Nx** | Executor references, main entry points, tsconfig paths, and the commands of `nx:run-commands` targets from `project.json`. See [Nx run-commands targets](https://fallow.tools/docs/frameworks/built-in/#nx-run-commands-targets) |
| **GraphQL Codegen** | Plugin imports and `documents` globs from `codegen*.{ts,js,cjs,mjs}` and `graphql.config.*`. Each `documents` glob is an entry pattern, because the codegen run reads these files without an import |
| **TypeORM** | `migrations` globs from a `DataSource` config. See [TypeORM migrations](https://fallow.tools/docs/frameworks/built-in/#typeorm-migrations) |
| **Kibana** | For each `kibana.jsonc` with `"type": "plugin"`: `public/index` when `plugin.browser`, `server/index` when `plugin.server`, `common/index`, and the index of each `plugin.extraPublicDirs` directory. Scout Playwright configs and global setup files. `setup`, `start` and `stop` on classes that implement `Plugin`, `PrebootPlugin` or `AsyncPlugin` |
| **Hardhat** | Plugin imports and side-effect requires from `hardhat.config.ts` |
| **Contentlayer** | `contentDirPath`, same-file `defineDocumentType` `filePathPattern` entries, and config imports from `contentlayer.config.*` |
| **Velite** | `defineCollection` `pattern` globs joined to the top-level `root` (default `content`), generated `.velite` output, a non-default `output.data` dir, and config imports from `velite.config.*` |
| **UnoCSS** | Preset and transformer imports from `uno.config.ts` |
| **Wuchale** | Adapter imports from `wuchale.config.js`; static custom JavaScript config files referenced from `@wuchale/vite-plugin` in `vite.config.*` |
| **Module Federation** | `exposes` targets, `remotes` aliases and `shared` packages from `module-federation.config.*` and from a Federation plugin call in a webpack, rspack, rsbuild, vite or `next.config.*` file. Remotes from literal runtime calls such as `registerRemotes` and `loadRemote`. See [Module Federation](https://fallow.tools/docs/frameworks/built-in/#module-federation) |

> **Tip:** Run `fallow list --plugins` to see which plugins are active in your project.

**$ fallow list --plugins**

```bash
Active plugins:
  - nextjs
  - vite
  - vitest
  - playwright
  - storybook
  - oxlint
  - typescript
  - tailwind
  - drizzle
```

> **Info:** If your framework is not in the list, write a [custom plugin](https://fallow.tools/docs/frameworks/custom-plugins/). Custom plugins support any internal or third-party tool, with declarative JSON or TOML.

## Jest configs

The Jest plugin reads every Jest config in a package:

- `jest.config.*`
- `jest-*.config.*`, for example `jest-integration.config.ts`
- `jest.*.config.*`, for example `jest.e2e.config.ts`

Each config adds its own test patterns. A config with its own `testMatch` or `testRegex` does not remove the default test patterns of the other configs.

Fallow converts a simple `testRegex` to a glob:

| `testRegex` | Glob |
|:------------|:-----|
| `\.integration-spec\.ts$` | `**/*.integration-spec.ts` |
| `test/integration/.*\.integration-spec\.ts$` | `test/integration/**/*.integration-spec.ts` |

When fallow cannot convert a regex, add the test files to `entry`.

A `--config` file that a script passes to `jest` is also an entry point, for example `jest --config ./jest-integration.config.ts`.

## Nx run-commands targets

Fallow reads the `command` and `commands` of each `nx:run-commands` target in a `project.json` file as a script. For example, `tsx scripts/seed.ts` makes `scripts/seed.ts` an entry point, and `jest --config ./jest-integration.config.ts` makes the Jest config an entry point.

- Fallow replaces the `{projectRoot}` and `{workspaceRoot}` tokens.
- Fallow also reads a command in the `configurations` of the target.
- A command that calls another target of the same project, such as `nx ts-node -- src/run.ts`, uses the command of that target.
- Fallow reads a target only when it runs in the project directory, for example with `cwd` set to `{projectRoot}`. A target without `cwd` in a nested project runs from the workspace root, so Fallow skips it. Fallow also skips a target with a `cwd` that points to a different directory, because its relative paths can point to the wrong files.

## TypeORM migrations

Fallow reads the `migrations` option of a `DataSource` config in `data-source.{ts,js}`, `*.data-source.{ts,js}`, `*.datasource.{ts,js}`, and `ormconfig.{ts,js,json}`. Each glob becomes an entry pattern, because TypeORM loads the migration files at runtime without an import.

```typescript
// src/data-source.ts
export const dataSource = new DataSource({
  type: "postgres",
  migrations: [`${isJest ? "src/" : "dist/"}migrations/*.{ts,js}`],
});
```

When a template selects between two paths, fallow uses the path that starts with `src/`. When no path starts with `src/`, fallow changes a `dist/` path to the same path under `src/`.

Fallow does not read the `entities` and `subscribers` options. TypeORM uses only the decorated classes of these files. An entry point for each file would also hide the other unused exports and members of the file.

## Classes and enums that a library reads by reflection

Some libraries read every member of a class or an enum. Project code does not name these members, so fallow counts them as used in these cases:

- **ORM entities.** An entity class that you pass to `getRepository`, `getCustomRepository`, `getTreeRepository`, `getMongoRepository`, or `createQueryBuilder` uses all of its members. The type argument of a repository getter, as in `getRepository<Order>()`, counts too.
- **ORM find calls.** An entity class that you pass to `find`, `findBy`, `findOne`, `findOneBy`, `findOneOrFail`, `findOneByOrFail`, `findAndCount`, or `findAndCountBy` uses all of its members. This applies only when the file imports from `typeorm`, `@nestjs/typeorm`, or a `@mikro-orm/` package.
- **GraphQL enums.** An enum that you pass to `registerEnumType` from `@nestjs/graphql` or `type-graphql` uses all of its values.

An entity class that code uses only as a type can still have unused properties. See [Entity properties that code uses only as a type](https://fallow.tools/docs/analysis/debugging/#entity-properties-that-code-uses-only-as-a-type).

## Webpack config directories

Fallow also reads a webpack config that lives under `config/`, `build/` or `webpack/` instead of the package root. Rspack and rsbuild configs stay at the package root; they do not have this directory rule.

A file under `config/` or `webpack/` counts as a webpack config when it exports a webpack configuration: an object with a webpack config key other than `name` or `dependencies` (also returned from a function), an array of configurations, or a `webpack-merge` call (`merge`, `mergeWithCustomize`, `mergeWithRules`, or the imported package). A helper file such as `config/webpack.paths.js` does not export a configuration, so fallow still reports it as unused when nothing imports it.

`build/` also holds build output, so fallow reads a narrower name there: only `webpack.<target>.{ts,js,mjs,cjs}`, such as `build/webpack.prod.js`, and only when it passes the same export check. Fallow never reads `build/webpack.config.*`, because that name is more likely to be a compiled or stale copy.

Fallow probes these directories beside a root config, so `build/webpack.prod.js` is read together with a root `webpack.config.js`.

Entries resolve like the bundler resolves them:

- Rspack reads `context`, and rsbuild reads `root`. A relative entry, and a Module Federation `exposes` target, resolve against that directory.
- An entry without an extension, such as `./lib` or `./src/app`, matches the source file (`./lib.ts`) or the directory index (`./lib/index.ts`). This also applies when `context` or `root` is set.
- A Module Federation `exposes` target and the `remotes` scope of a webpack config in `config/`, `build/` or `webpack/` resolve against the package root, the same as webpack does without `context`.

## Webpack inline loader requests

An import can name its loaders inline, such as `require('!raw-loader?esModule=false!./shim.js')`. Fallow reads these requests in every project, also when the webpack plugin is not active:

- The request resolves to its resource, the last segment (`./shim.js`). The `!`, `!!` and `-!` prefixes and the `?options` of each loader do not change the target.
- Each loader package, such as `raw-loader`, counts as a used dependency. A loader in `devDependencies` is not reported as a dev dependency that production code uses.
- A loader replaces the exports of its resource. A loader import therefore uses every value export of the resource, `default` included, and fallow does not report these exports as unused. A type export of the resource (a type alias or an interface) follows the same rule as a type export of a file that a [dynamic import pattern](https://fallow.tools/docs/analysis/dead-code/#dynamic-import-resolution) matches: only an import that names it uses it.
- A text loader returns the text, the bytes or a URL of the file: `raw-loader`, `file-loader`, `url-loader`, `text-loader` and similar. The resource counts as used, but its own imports do not. They do not keep other files in use, and they are not production imports. A loader that runs the file, such as `worker-loader`, `css-loader` or `babel-loader`, keeps the imports of the resource.
- A text loader import does not run the resource, so it does not cross an [architecture boundary](https://fallow.tools/docs/analysis/boundaries/), it does not carry server code into a `"use client"` file for [`client-server-leak`](https://fallow.tools/docs/cli/security/), and a re-export through a loader is not a client or server origin of a [mixed client/server barrel](https://fallow.tools/docs/frameworks/react/#mixed-client-server-barrel). A package file behind a text loader (`raw-loader!pkg/notes.txt`) is read at build time: the package is a used dependency, but not a dev dependency that production code imports.
- A worker loader runs the resource in another thread: `worker-loader`, `sharedworker-loader`, `worklet-loader`, `workerize-loader`, `comlink-loader`, `service-worker-loader` and similar. The import loads the same way as `new Worker(new URL('./work.js', import.meta.url))`. A cycle through the import is reported by default, and [`circularDependencies.ignoreLazyImports`](https://fallow.tools/docs/configuration/overview/#config-fields) skips it. [`fallow list --entry-weight`](https://fallow.tools/docs/cli/list/) counts the resource as out-of-thread code, not as startup code.
- A `!` is also valid in a file name. A request without a prefix, such as `./we!rd.js` or `pkg/a!b.js`, resolves as a plain path first when that file exists, also an installed package file. When the file does not exist, for example in a clone without installed packages, fallow reads the request the way webpack does: webpack splits every request on `!`, so `pkg/a!b.js` is the loader `pkg/a` for `b.js`.
- Only inline loaders change an import. A loader that a rule in `module.rules` of a webpack config applies, such as `{ test: /\.worker\.js$/, use: 'worker-loader' }`, gives no worker or text loader semantics. The rule conditions (`test`, `include`, `exclude`, `issuer`, `resourceQuery`, the `oneOf` order) use JavaScript regular expressions and computed paths, and many projects build the rules in code, for example with `webpack-merge`, in the `webpack` function of `next.config.js`, or in Storybook `webpackFinal`. A static read would miss or misapply rules, and a misapplied text loader rule would hide the imports of every file that it matches. The configured loader packages still count as used dependencies.
- When the resource does not resolve, the unresolved import shows the full request, so an `ignoreUnresolvedImports` entry must use the full request.

## Module Federation

With Module Federation, fallow keeps exposed modules out of the unused-file report, does not report remote imports as unlisted dependencies, and does not report shared packages as unused dependencies.

Fallow reads `exposes`, `remotes`, and `shared` from `module-federation.config.{ts,js,mjs,cjs,mts,cts}`. It also reads them from a Federation plugin call in a webpack, rspack, rsbuild, vite or `next.config.*` file. Fallow recognizes these plugin calls: `ModuleFederationPlugin`, `NextFederationPlugin`, `moduleFederationPlugin`, `pluginModuleFederation` and `federation`. Fallow reads such a call wherever it is in the config program. A call counts only when its first argument is an object that declares `exposes`, `remotes`, or `shared`.

- `exposes`: each target becomes a runtime entry point. The exposed module, and everything it reaches, stays out of `unused-file`. Its exports follow [`includeEntryExports`](https://fallow.tools/docs/configuration/overview/#includeentryexports), like the exports of any other entry point. A target that names a bare module request instead of a local path (`"./utils": "shared-utils"`) credits that dependency, but only in the package that owns the config.
- `remotes`: fallow treats each alias and its subpaths as provided by the remote container, so it does not report `import("checkout/Button")` as an unlisted dependency. The alias holds only under the directory of the config that declared it. A sibling workspace package that declares no remote still reports the dependency.
- `shared`: each package that the option names counts as used, so it does not report as an unused dependency. Fallow reads the object form (`shared: { react: { singleton: true } }`), the array form (`shared: ['react', 'react-dom']`), an object element in the array form, and the `import` and `packageName` fields of an entry descriptor. A key with a trailing `/` credits the same package. A relative key shares a project module and credits no package. The credit applies only to the package that owns the config (the nearest `package.json` at or above the config), so a sibling workspace that declares the same package and does not use it still reports it. A `shared` entry for a package that `package.json` does not declare creates no finding. A `shared` value that fallow cannot read gives no credit and records no diagnostic.

Fallow reads a plugin call in these positions:

- A nested plugin array, and a plugin list that a variable holds.
- A tool-specific key such as `tools.rspack.plugins`.
- A hook body, such as an rsbuild `appendPlugins` hook or a Next.js `webpack(config)` hook.
- A helper module that the bundler config imports with a relative `import` or `require`, such as `config/module-federation.js`. Fallow reads the helper one import deep, inside the project root, as if the call was in the config. The diagnostics and the trace sources name the helper file.

Fallow also reads the plugin options through one step of indirection:

- An `export const` in the same file (`export const mfConfig = { ... }`), and a plain `const` (`const mfConfig = { ... }`). The program must have one binding of that name, and no code may write to the binding or to one of its members.
- A TypeScript non-null assertion on the binding, such as `new ModuleFederationPlugin(mfConfig!)`.
- A computed callee, such as `new container['ModuleFederationPlugin']({ ... })`.
- A relative `import` of a sibling config file, including a default import and a named import.
- A relative `require` of a sibling config file, one step deep. A `require` of a package stays silent.
- An object spread over a same-file binding (`{ ...base }`) and `Object.assign({}, base)`.
- The array form of `exposes`. A string element is both the public name and the module request. An object element uses the object reader.
- `exposes` targets and the `remotes` scope of a webpack config under `config/`, `build/` or `webpack/`, resolved against the package root, as webpack does without `context`. See [config directories](https://fallow.tools/docs/frameworks/built-in/#webpack-config-directories).

Every config reader that resolves an options object, not only Module Federation, follows `export const config = { ... }; export default config` the same way.

Fallow does not read:

- The array form of `remotes`. A bundler derives the request scope of an element from the whole container location, so the alias is not a bare specifier.
- A value that is not a static object literal, an unreadable `require` of a package, and an array element that holds glob syntax, a nested array, or a value that is not a string.
- A spread over a binding fallow cannot resolve. This records a `plugin-config-unreadable` diagnostic with the `spread` reason for each Federation key the readable part does not declare. When the options declare no Federation key at all, a bare `federation(...)` call records nothing, because other libraries use that name too.

### Runtime remotes

A remote can also come from a call to the Federation runtime. Fallow reads these calls in a file that imports them from `@module-federation/runtime` or `@module-federation/enhanced/runtime`, by name, by a renamed import, or through a namespace import. A local function with the same name registers nothing.

- `registerRemotes([{ name: 'checkout', entry }])` registers `checkout`, and a literal `alias` when the object has one.
- `loadRemote('checkout/Button')` registers `checkout`. A scoped name keeps two segments (`@scope/remote`).
- `init({ remotes })` and `createInstance({ remotes })` register the remotes that their `remotes` option names. Fallow also reads the `registerRemotes` and `loadRemote` methods of the instance that they return.

A remote from a runtime call follows the same rule as a `remotes` entry: the alias and its subpaths are provided only inside the workspace that holds the file. Fallow also reads these calls in the `<script>` blocks of a `.vue` or `.svelte` file. The blocks count as one file, so an import in one block covers a call in another.

Fallow reads only a static literal argument. A call whose argument is not a static literal, such as ``loadRemote(`${scope}/${module}`)``, records a `plugin-config-unreadable` diagnostic on the source file, with the function name as `key` and the reason `dynamic-argument`.

### Trace the Federation source

`--trace-file` and `--trace-dependency` name the Federation config when it is the reason for the result:

- `--trace-file` on a file that an `exposes` entry makes an entry point lists each config that exposes it.
- `--trace-dependency` on a `remotes` alias lists each config that declares the alias, and says that a remote container provides the name, not an npm package.

The human output adds one `Source:` line for each config. The JSON output has a `sources` array with `{ kind, plugin, config, key }` entries, for example `{ "kind": "module-federation", "plugin": "webpack", "config": "packages/cart/webpack.config.js", "key": "exposes" }`. For a remote that only a runtime call names, `config` is the source file and `key` is the function name. A trace with no Federation involvement has no `sources` array. The MCP `trace_file` and `trace_dependency` tools have the same field.

### Limits and diagnostics

Fallow reads the config syntactically. It fetches no remote container and validates nothing about the remote. Fallow does not check the availability of the remote, its exports, its versions, or its shared singletons.

When fallow cannot read a declaration in full, it adds a `plugin-config-unreadable` entry to `workspace_diagnostics[]` and prints a warning on stderr. The entry names the plugin, the key, and the reason, with the config file in `path`. For a runtime call, `path` is the source file.

- `reason` is `not-object-literal`, `array-form`, `spread`, `unreadable-entries` or `dynamic-argument`. For a runtime call, `key` is `registerRemotes`, `loadRemote`, `init` or `createInstance`. More values can come later, so do not treat this list as closed.
- The plugin is `module-federation` for a standalone config file and for a runtime call. It is `webpack`, `rspack`, `rsbuild`, `vite` or `nextjs` when fallow read the options from the config of that plugin.
- Two unreadable keys in one file give two entries.
- The entry has `degrades_analysis`, so both CI integrations that fallow ships report it under degraded inputs.

```text
fallow: Plugin 'module-federation': `exposes` in 'module-federation.config.ts' is not a static object literal, so the targets are not registered as entry points. Name the exposed files in `dynamicallyLoaded`.
fallow: Plugin 'webpack': `remotes` in 'webpack.config.js' uses the array form, which is not read yet, so the aliases are not treated as provided by a remote container. Name the aliases in `ignoreDependencies`, or declare them as the keys of an object literal, whose values may be computed.
```

For an exposed file that fallow cannot see, use [`dynamicallyLoaded`](https://fallow.tools/docs/configuration/overview/#dynamicallyloaded). For a file that is a project entry point of its own, use [`entry`](https://fallow.tools/docs/configuration/overview/#entry). Put a remote alias in [`ignoreDependencies`](https://fallow.tools/docs/configuration/overview/#ignoredependencies). Note that `ignoreDependencies` also hides unused-dependency findings for that name.

## Nuxt local layers

Nuxt lets a project extend other Nuxt codebases, called layers. Fallow scans a local layer the same way it scans the project root.

A directory is a local layer when it holds a `nuxt.config` file (`ts`, `js`, `mjs`, `cjs`, `mts` or `cts`), and either:

- A `nuxt.config` names it in `extends`, as a relative path. This includes the project root config and the config of any local layer already found, so a layer chain (a layer that itself extends another local layer) resolves too.
- It sits under `layers/<name>`, beside the root config. Fallow scans every `layers/<name>` directory that has a `nuxt.config`, without an `extends` entry.

A local layer without a `nuxt.config` is not a layer, so its files keep reporting as unused when nothing references them.

For each local layer:

- Its convention files (pages, layouts, components, composables, utils, server, plugins) are entry points, the same as the project root.
- Its root files (`app.vue`, `app.config.*`) are always used.
- With [`autoImports`](https://fallow.tools/docs/configuration/overview/#autoimports) on, its components and composables are auto-import sources. An unreferenced layer component then reports as `unused-file`.
- Its own `nuxt.config` takes part in the `autoImports` surface classification, alongside the root config. The advisory that fallow prints for a custom `components:` or `imports:` shape names the config file that decided that surface.

`#layers/<name>/` resolves to a local layer by its `$meta.name`:

- A `layers/<name>` directory without a `$meta.name` resolves by its directory name.
- An `extends` layer without a `$meta.name` gets no alias, so an import through `#layers/<name>/` stays unresolved.

A remote layer (a `github:` or `gh:` reference) or a package layer (an npm name) stays a dependency reference only. Fallow does not scan its files.

Fallow reads the `modules` of a package layer, so a module that the layer registers is active for the app. For example, with `extends: ['docus']`, or another package layer that lists `@nuxt/content` in its own `modules`, the `components/content/` files and the `content.config.*` file of the app stay entry points. Fallow reads the `nuxt.config` of the layer from the nearest `node_modules/<name>`. `docus` activates `@nuxt/content` also when it is not installed. Fallow does not follow the `extends` of a package layer. A local layer that registers `@nuxt/content` also marks the `content.config.*` file of the app as used.

## Nuxt auto-import scope

With [`autoImports`](https://fallow.tools/docs/configuration/overview/#autoimports) on, an auto-import name marks as used only the files of the app that renders or calls it, and of the layers that this app extends. In a monorepo, a `<Card />` in one app does not keep the unused `Card.vue` of another app. A run with `autoImports` on can therefore report more unused files than before.

- A layer that an app extends by a relative path outside the app, or by the package name of a workspace, shares its names with that app in both directions. The app uses the components and Pinia stores of the layer. A layer layout can render a component that the app overrides.
- Two apps that extend the same layer do not see the names of each other.

These component files stay entry points, because fallow cannot see how they render:

- Files in `components/global/` and `*.global.vue` files. A string reference such as `resolveComponent('Name')` can render a global component.
- Files in `components/content/` of the project and of each local layer, when `@nuxt/content` is in `modules`. Markdown content renders these components, and fallow does not read Markdown.

`nuxt-og-image` renders the template that a string names, so no import or template tag reaches the file. A `defineOgImage('Docs.takumi')` or `defineOgImageComponent('Docs')` call marks the matching file as used, under an `OgImage/`, `og-image/`, `OgImageCommunity/`, or `OgImageTemplate/` components directory. The name match is the one that `nuxt-og-image` uses: dot segments join in PascalCase, and the renderer suffix (`.satori`, `.browser`, `.takumi`) and the directory prefix do not count. A template that no call names with a static string still reports as unused.

## Storybook stories

Storybook reads each `stories` pattern in `.storybook/main` relative to the directory of that config file. Fallow does the same, so a pattern such as `../src/**/*.mdx` matches the story files that Storybook loads.

- A pattern can point into another workspace of the project. For example, a central docs app with `apps/docs/.storybook` and `stories: ["../../../packages/ui/src/**/*.docs.tsx"]` marks the matching files in `packages/ui` as used.
- Fallow drops a pattern that leaves the project root.
- Storybook reads a leading `/` as an absolute filesystem path. A pattern such as `/src/**` outside the project therefore marks nothing as used.
- A `@(ts|tsx)` group, as in the Storybook config template, matches like `{ts,tsx}`. A nested `@(..)` group matches too. Other extglob forms, such as `!(..)`, match nothing.
- Fallow reads the object form `{ directory, files, titlePrefix }`. `directory` resolves against the `.storybook/` directory, and `files` applies under it. Without `files`, the Storybook default `**/*.@(mdx|stories.@(js|jsx|mjs|ts|tsx))` applies.
- Fallow also reads the `.storybook/main` config of a workspace when the root package uses Storybook too.

## See also

- [Custom plugins](https://fallow.tools/docs/frameworks/custom-plugins/): Support internal frameworks with external plugin files.
- [fallow list](https://fallow.tools/docs/cli/list/): Inspect active plugins, entry points, and project metadata.
