> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nrwl/nx/llms.txt
> Use this file to discover all available pages before exploring further.

# Enforce Module Boundaries

> Use tags and dependency constraints to enforce architectural boundaries between projects in your Nx monorepo, preventing unwanted cross-project imports.

As a monorepo grows, unrestricted dependencies between projects lead to a tangled architecture that becomes difficult to maintain. Nx provides a tag-based constraint system that lets you define and automatically enforce which projects are allowed to depend on each other.

## Two approaches

Nx supports two complementary approaches:

<CardGroup cols={2}>
  <Card title="ESLint (JS/TS projects)" icon="code">
    Enforces boundaries on TypeScript imports and `package.json` dependencies during linting with the `@nx/enforce-module-boundaries` rule.
  </Card>

  <Card title="Conformance (any language)" icon="shield-check">
    Enforces boundaries on the full Nx project graph using `nx conformance:check`. Works for Java, Python, PHP, and any other project type. Requires Nx Enterprise.
  </Card>
</CardGroup>

Both approaches use the same tag-based constraint system.

## Step 1: Tag your projects

Add `tags` to each project's configuration. Tags are arbitrary strings — a common convention is to use prefixes like `scope:` or `type:`.

<Tabs>
  <Tab title="project.json">
    ```jsonc theme={null}
    // client/project.json
    {
      "tags": ["scope:client"]
    }
    ```

    ```jsonc theme={null}
    // admin/project.json
    {
      "tags": ["scope:admin"]
    }
    ```

    ```jsonc theme={null}
    // utils/project.json
    {
      "tags": ["scope:shared"]
    }
    ```
  </Tab>

  <Tab title="package.json">
    ```jsonc theme={null}
    // client/package.json
    {
      "nx": {
        "tags": ["scope:client"]
      }
    }
    ```

    ```jsonc theme={null}
    // admin/package.json
    {
      "nx": {
        "tags": ["scope:admin"]
      }
    }
    ```

    ```jsonc theme={null}
    // utils/package.json
    {
      "nx": {
        "tags": ["scope:shared"]
      }
    }
    ```
  </Tab>
</Tabs>

## Step 2: Configure boundary rules

<Tabs>
  <Tab title="ESLint (flat config)">
    Install the plugin:

    ```bash theme={null}
    nx add @nx/eslint-plugin @nx/devkit
    ```

    Configure the rule in `eslint.config.mjs`:

    ```javascript theme={null}
    // eslint.config.mjs
    import nx from '@nx/eslint-plugin';

    export default [
      ...nx.configs['flat/base'],
      ...nx.configs['flat/typescript'],
      ...nx.configs['flat/javascript'],
      {
        files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
        rules: {
          '@nx/enforce-module-boundaries': [
            'error',
            {
              allow: [],
              depConstraints: [
                {
                  sourceTag: 'scope:shared',
                  onlyDependOnLibsWithTags: ['scope:shared'],
                },
                {
                  sourceTag: 'scope:admin',
                  onlyDependOnLibsWithTags: ['scope:shared', 'scope:admin'],
                },
                {
                  sourceTag: 'scope:client',
                  onlyDependOnLibsWithTags: ['scope:shared', 'scope:client'],
                },
              ],
            },
          ],
        },
      },
    ];
    ```
  </Tab>

  <Tab title="ESLint (legacy .eslintrc.json)">
    ```jsonc theme={null}
    // .eslintrc.json
    {
      "overrides": [
        {
          "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
          "rules": {
            "@nx/enforce-module-boundaries": [
              "error",
              {
                "allow": [],
                "depConstraints": [
                  {
                    "sourceTag": "scope:shared",
                    "onlyDependOnLibsWithTags": ["scope:shared"]
                  },
                  {
                    "sourceTag": "scope:admin",
                    "onlyDependOnLibsWithTags": ["scope:shared", "scope:admin"]
                  },
                  {
                    "sourceTag": "scope:client",
                    "onlyDependOnLibsWithTags": ["scope:shared", "scope:client"]
                  }
                ]
              }
            ]
          }
        }
      ]
    }
    ```
  </Tab>

  <Tab title="Conformance (nx.json)">
    ```bash theme={null}
    nx add @nx/conformance
    ```

    ```jsonc theme={null}
    // nx.json
    {
      "conformance": {
        "rules": [
          {
            "rule": "@nx/conformance/enforce-project-boundaries",
            "options": {
              "depConstraints": [
                {
                  "sourceTag": "scope:shared",
                  "onlyDependOnProjectsWithTags": ["scope:shared"]
                },
                {
                  "sourceTag": "scope:admin",
                  "onlyDependOnProjectsWithTags": ["scope:shared", "scope:admin"]
                },
                {
                  "sourceTag": "scope:client",
                  "onlyDependOnProjectsWithTags": ["scope:shared", "scope:client"]
                }
              ]
            }
          }
        ]
      }
    }
    ```

    Run conformance checks:

    ```bash theme={null}
    npx nx conformance:check
    ```
  </Tab>
</Tabs>

With these rules in place:

* `scope:shared` can only depend on other `scope:shared` projects
* `scope:admin` can depend on `scope:admin` and `scope:shared`
* `scope:client` can depend on `scope:client` and `scope:shared`
* `scope:client` and `scope:admin` **cannot** depend on each other

Violations produce a lint error:

```
A project tagged with "scope:admin" can only depend on projects
tagged with "scope:shared" or "scope:admin".
```

## Tag format reference

<AccordionGroup>
  <Accordion title="Exact string match">
    ```json theme={null}
    {
      "sourceTag": "scope:client",
      "onlyDependOnLibsWithTags": ["scope:util"]
    }
    ```
  </Accordion>

  <Accordion title="Wildcard (*)">
    Allow any project to depend on any other project:

    ```json theme={null}
    {
      "sourceTag": "*",
      "onlyDependOnLibsWithTags": ["*"]
    }
    ```
  </Accordion>

  <Accordion title="Regular expression">
    ```json theme={null}
    {
      "sourceTag": "scope:client",
      "onlyDependOnLibsWithTags": ["/^scope.*/"]
    }
    ```
  </Accordion>

  <Accordion title="Glob pattern">
    ```json theme={null}
    {
      "sourceTag": "scope:*",
      "onlyDependOnLibsWithTags": ["scope:*"]
    }
    ```

    Glob supports `*` only. Use regex for more complex patterns.
  </Accordion>
</AccordionGroup>

<Note>
  Projects without any tags cannot depend on any other projects by default. You must explicitly allow them using the `"*"` wildcard, or add tags to those projects.
</Note>
