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

---
id: 51a6f0b2-ba15-4f64-8e00-111c51e4aca6
---

# no-parent-imports

> Prevent importing files from outside the extension point root directory.

The `no-parent-imports` rule prevents importing files from outside the extension point root directory using relative paths.

## Rule details

Extension points are self-contained architectural units. Each extension point (e.g., *Settings*, *Pages*) is built and deployed independently, which means all code for an extension must live within its root directory. Files outside this boundary are not included when the extension is packaged for deployment.

This rule prevents relative imports (`../`) that escape your extension point's directory. While these imports work during local development (when your full project structure is available), they fail at runtime because the referenced files don't exist in the deployed extension package.

## Example

As an example, consider the following project structure:

<Card>
  <Tree>
    <Tree.Folder name="project" defaultOpen>
      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="app" defaultOpen>
          <Tree.Folder name="settings">
            <Tree.File name="Config.tsx" />
          </Tree.Folder>

          <Tree.Folder name="cards" defaultOpen>
            <Tree.File name="Widget.tsx" />
          </Tree.Folder>

          <Tree.Folder name="shared" defaultOpen>
            <Tree.File name="utils.ts" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree>
</Card>

<Tabs>
  <Tab title="Widget.tsx">
    ```tsx wrap highlight={1} theme={null}
    import { formatData } from '../shared/utils';

    function Widget() {
      const data = formatData(props.data);
      return <Text>{data}</Text>;
    }
    ```
  </Tab>

  <Tab title="Config.tsx">
    ```tsx wrap highlight={1} theme={null}
    import { CONSTANTS } from '../../lib/constants';

    function Config() {
      return <Text>{CONSTANTS.APP_NAME}</Text>;
    }
    ```
  </Tab>
</Tabs>

Because `Widget.tsx` imports from `../shared/utils.ts`, the app card will work locally, as the `utils.ts` file is available within the development environment. However, once built and deployed, the `shared/` directory won't be included in either the `cards/` or `settings/` builds, and `utils.ts` will no longer be available to either one.

### Solving with npm workspaces (recommended)

If you need to share code between multiple extension points, use [npm workspaces](/apps/developer-platform/add-features/ui-extensions/tools/code-sharing-with-npm-workspaces):

1. Create a shared workspace `package` directory at the root of your project:

<Card>
  <Tree>
    <Tree.Folder name="project" defaultOpen>
      <Tree.File name="hsproject.json" />

      <Tree.Folder name="packages" defaultOpen>
        <Tree.Folder name="shared-utils" defaultOpen>
          <Tree.File name="package.json" />

          <Tree.File name="tsconfig.json" />

          <Tree.Folder name="src" defaultOpen>
            <Tree.File name="format.ts" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>

      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="app" defaultOpen>
          <Tree.Folder name="cards" defaultOpen>
            <Tree.File name="Widget.tsx" />
          </Tree.Folder>

          <Tree.Folder name="settings">
            <Tree.File name="Config.tsx" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree>
</Card>

2. Configure your root `package.json`:

```json theme={null}
{
  "name": "my-ui-extensions-app",
  "workspaces": [
    "packages/*"
  ]
}
```

3. In your UI extension code, import from the shared package:

```tsx theme={null}
// In: src/app/cards/Widget.tsx
import { formatData } from '@my-app/shared-utils'; // ✓ Using workspace package

function Widget() {
  const data = formatData(props.data);
  return <Text>{data}</Text>;
}
```

### Solving with extension point-specific code

Move shared code into the extension point directory and use relative imports freely:

```tsx theme={null}
// In: src/app/cards/Widget.tsx
import { formatData } from './utils/format'; // ✓ Stays within cards directory

function Widget() {
  const data = formatData(props.data);
  return <Text>{data}</Text>;
}
```

You can use relative imports anywhere within your extension point:

```tsx theme={null}
// In: src/app/cards/components/Widget.tsx
import { useCardData } from '../hooks/useCardData'; // ✓ Stays within cards directory
import { Button } from './Button'; // ✓ Stays within cards directory

function Widget() {
  const data = useCardData();
  return <Button onClick={() => {}}>{data.title}</Button>;
}
```

### Valid relative import patterns

The following patterns are all valid because they stay within the extension point:

```tsx theme={null}
// All in src/app/cards/ directory structure

// From: src/app/cards/components/Widget.tsx
import { util } from './Button';          // ✓ Same directory
import { util } from '../utils';          // ✓ Parent directory, still in cards
import { util } from '../../cards/hooks'; // ✓ Goes up but comes back to cards
```

## Common scenarios

### Sharing constants

Instead of importing constants from outside the extension point:

```tsx theme={null}
// Incorrect
// src/app/cards/Widget.tsx
import { API_URL } from '../config/constants'; // ❌ Escapes extension point
```

Define constants within the extension point:

```tsx theme={null}
// src/app/cards/constants.ts
export const API_URL = 'https://api.example.com';

// src/app/cards/Widget.tsx
import { API_URL } from './constants'; // ✓ Stays within cards
```

### Sharing utility functions

Instead of importing utilities from outside the extension point:

```tsx theme={null}
// Incorrect
// src/app/settings/Config.tsx
import { formatDate } from '../utils/date'; // ❌ Escapes extension point
```

Use npm workspaces to share utilities across extension points:

```tsx theme={null}
// packages/shared-utils/src/date.ts
export const formatDate = (date: Date) => { /* ... */ };

// src/app/settings/Config.tsx
import { formatDate } from '@my-app/shared-utils'; // ✓ Using workspace
```

### Sharing types/interfaces

Instead of importing types from outside the extension point:

```tsx theme={null}
// Incorrect
// src/app/cards/Widget.tsx
import type { UserData } from '../../types/user'; // ❌ Escapes extension point
```

Use npm workspaces to share types across extension points:

```tsx theme={null}
// packages/shared-types/src/user.ts
export interface UserData { /* ... */ }

// src/app/cards/Widget.tsx
import type { UserData } from '@my-app/shared-types'; // ✓ Using workspace
```

## Related resources

* [UI extensions SDK overview](/apps/developer-platform/add-features/ui-extensions/ui-extensions-sdk)
* [Extension point locations](/apps/developer-platform/add-features/ui-extensions/overview#supported-locations)
* [npm workspaces documentation](/apps/developer-platform/add-features/ui-extensions/tools/code-sharing-with-npm-workspaces)
