> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Path Mapping

> Setting up module path aliases

Path Mapping allows you to import modules using absolute paths instead of relative paths. This improves code readability and eliminates the need to update import paths when files are moved.

## Path Mapping in Web (React)

Sonamu Web projects provide `@/*` path mapping by default.

### tsconfig.json Configuration

```json title="web/tsconfig.json" theme={null}
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
```

### Vite Configuration

TypeScript configuration alone is not enough; you also need to set up the same alias in Vite.

```typescript title="web/vite.config.ts" theme={null}
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
});
```

<Warning>
  You must configure both TypeScript and Vite. If only one is configured, type checking or builds will fail.
</Warning>

### Usage Examples

<Tabs>
  <Tab title="Before (Relative Paths)" icon="ban">
    <FileTree>
      * src/
        * pages/
          * users/
            * UserList.tsx
            * UserDetail.tsx
        * components/
          * Button.tsx
          * Input.tsx
        * utils/
          * format.ts
        * hooks/
          * useAuth.ts
    </FileTree>

    ```typescript title="src/pages/users/UserDetail.tsx" theme={null}
    // ❌ Complex and hard to maintain
    import { Button } from "../../components/Button";
    import { Input } from "../../components/Input";
    import { formatDate } from "../../utils/format";
    import { useAuth } from "../../hooks/useAuth";
    ```

    **Problems:**

    * Need to update all imports when file location changes
    * Complex paths like `../../../`
    * Poor readability
  </Tab>

  <Tab title="After (Absolute Paths)" icon="check">
    ```typescript title="src/pages/users/UserDetail.tsx" theme={null}
    // ✅ Clean and clear
    import { Button } from "@/components/Button";
    import { Input } from "@/components/Input";
    import { formatDate } from "@/utils/format";
    import { useAuth } from "@/hooks/useAuth";
    ```

    **Benefits:**

    * Import paths remain the same when file location changes
    * Same import method from anywhere
    * Improved readability
  </Tab>
</Tabs>

### Directory-specific Mapping

You can map more paths.

```json title="web/tsconfig.json" theme={null}
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@pages/*": ["./src/pages/*"],
      "@utils/*": ["./src/utils/*"],
      "@hooks/*": ["./src/hooks/*"],
      "@types/*": ["./src/types/*"]
    }
  }
}
```

```typescript title="web/vite.config.ts" theme={null}
export default defineConfig({
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
      "@components": path.resolve(__dirname, "./src/components"),
      "@pages": path.resolve(__dirname, "./src/pages"),
      "@utils": path.resolve(__dirname, "./src/utils"),
      "@hooks": path.resolve(__dirname, "./src/hooks"),
      "@types": path.resolve(__dirname, "./src/types"),
    },
  },
});
```

**Usage examples:**

```typescript theme={null}
// Default method
import { Button } from "@/components/Button";

// Specific mappings
import { Button } from "@components/Button";
import { UserPage } from "@pages/UserPage";
import { formatDate } from "@utils/format";
import { useAuth } from "@hooks/useAuth";
import type { User } from "@types/user";
```

<Tip>
  We recommend using only `@/*`. Too many mappings can cause confusion.
</Tip>

## Module Resolution in API Server

The API server typically does not use path mapping.

### Reason

```json title="api/tsconfig.json" theme={null}
{
  "compilerOptions": {
    "moduleResolution": "bundler",  // Vite resolves modules
    "target": "esnext",
    "module": "esnext"
  }
}
```

**Vite resolves all modules**

* API is built with Vite, so separate path mapping is unnecessary
* Packages like `sonamu` are automatically resolved by Vite
* Relative paths are clearer and simpler

### API Structure

API has a relatively simple structure.

<FileTree>
  * api/
    * src/
      * application/
        * controllers/
        * services/
      * domain/
        * entities/
        * models/
      * sonamu.config.ts
</FileTree>

```typescript title="api/src/application/controllers/UserController.ts" theme={null}
// Relative paths are sufficiently clear
import { UserService } from "../services/UserService";
import { User } from "../../domain/entities/User";
```

<Info>
  You can add path mapping to API if needed, but it's generally unnecessary.
</Info>

## Importing Sonamu Packages

Sonamu itself can be imported without path mapping.

```typescript theme={null}
// ✅ Direct import
import { BaseModelClass, api, transactional } from "sonamu";
import { DB } from "sonamu";
import { drivers } from "sonamu/storage";
import { store } from "sonamu/cache";

// ✅ Type import
import type { Context, SonamuConfig } from "sonamu";
```

**Sonamu package structure:**

* `sonamu` - Main package
* `sonamu/storage` - Storage drivers
* `sonamu/cache` - Cache drivers

<Info>
  Sonamu provides subpackages through the `exports` field in `package.json`.
</Info>

## Type Imports

Use the `type` keyword when importing only types.

```typescript theme={null}
// ✅ Import types only
import type { User } from "@/types/user";
import type { Context } from "sonamu";

// ✅ Mixed values and types
import { DB, type Context } from "sonamu";

// ❌ Unnecessary import at runtime
import { User } from "@/types/user";
```

<Tip>
  `type` imports are removed after compilation, reducing bundle size.
</Tip>

## IDE Auto-completion

When path mapping is configured, IDEs automatically recognize it.

### VS Code

```json title=".vscode/settings.json" theme={null}
{
  "typescript.preferences.importModuleSpecifier": "non-relative"
}
```

This setting uses absolute paths for auto imports.

### IntelliJ / WebStorm

Automatically reads `tsconfig.json` and recognizes path mapping.

<Accordion title="When auto-completion doesn't work" icon="question-circle">
  **Symptoms:**

  * `@/...` paths show red underline
  * Auto-completion doesn't work

  **Solutions:**

  1. **Restart TypeScript server**
     ```
     VS Code: Cmd/Ctrl + Shift + P → "TypeScript: Restart TS Server"
     ```

  2. **Check tsconfig.json**
     ```json theme={null}
     {
       "compilerOptions": {
         "baseUrl": ".",  // Required!
         "paths": {
           "@/*": ["./src/*"]
         }
       }
     }
     ```

  3. **Restart Vite dev server**
     ```bash theme={null}
     # Restart Vite
     pnpm dev
     ```

  4. **Reinstall node\_modules**
     ```bash theme={null}
     rm -rf node_modules
     pnpm install
     ```
</Accordion>

## Jest Test Configuration

Jest configuration is needed to use path mapping in tests.

```typescript title="web/jest.config.ts" theme={null}
export default {
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
    "^@components/(.*)$": "<rootDir>/src/components/$1",
  },
};
```

**Usage in test files:**

```typescript title="src/components/Button.test.tsx" theme={null}
import { render } from "@testing-library/react";
import { Button } from "@/components/Button";
import { formatDate } from "@/utils/format";

describe("Button", () => {
  it("renders correctly", () => {
    const { getByText } = render(<Button>Click me</Button>);
    expect(getByText("Click me")).toBeInTheDocument();
  });
});
```

## Common Troubleshooting

<Accordion title="Cannot find module '@/...' error" icon="exclamation-triangle">
  **Symptom:**

  ```
  Cannot find module '@/components/Button' or its corresponding type declarations.
  ```

  **Causes:**

  1. `baseUrl` is not set
  2. Vite alias is not configured
  3. Path typo

  **Solutions:**

  **1. Check tsconfig.json**

  ```json theme={null}
  {
    "compilerOptions": {
      "baseUrl": ".",  // Required!
      "paths": {
        "@/*": ["./src/*"]
      }
    }
  }
  ```

  **2. Check vite.config.ts**

  ```typescript theme={null}
  import path from "path";

  export default defineConfig({
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "./src"),
      },
    },
  });
  ```

  **3. Verify file exists**

  ```bash theme={null}
  ls -la src/components/Button.tsx
  ```
</Accordion>

<Accordion title="Build succeeds but type check fails" icon="code">
  **Symptom:**

  ```bash theme={null}
  pnpm build  # ✅ Success
  pnpm tsc    # ❌ Type error
  ```

  **Cause:**

  * Vite recognizes the alias but TypeScript doesn't

  **Solution:**

  Add `baseUrl` and `paths` to `tsconfig.json`:

  ```json theme={null}
  {
    "compilerOptions": {
      "baseUrl": ".",
      "paths": {
        "@/*": ["./src/*"]
      }
    }
  }
  ```
</Accordion>

<Accordion title="Type check succeeds but build fails" icon="hammer">
  **Symptom:**

  ```bash theme={null}
  pnpm tsc    # ✅ Success
  pnpm build  # ❌ Build error
  ```

  **Cause:**

  * TypeScript recognizes the alias but Vite doesn't

  **Solution:**

  Add alias to `vite.config.ts`:

  ```typescript theme={null}
  import path from "path";

  export default defineConfig({
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "./src"),
      },
    },
  });
  ```
</Accordion>

## Recommendations

<Tabs>
  <Tab title="Web" icon="browser">
    **Recommended settings:**

    ```json theme={null}
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["./src/*"]
        }
      }
    }
    ```

    **Usage:**

    * `@/components/*` - Components
    * `@/pages/*` - Pages
    * `@/utils/*` - Utilities
    * `@/hooks/*` - Custom hooks
    * `@/types/*` - Type definitions

    **Avoid:**

    * Too many aliases (adds confusion)
    * Alias for every subdirectory (unnecessary)
  </Tab>

  <Tab title="API" icon="server">
    **Recommended:**

    * Don't use path mapping
    * Relative paths are sufficiently clear

    **If needed:**

    ```json theme={null}
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["./src/*"]
        }
      }
    }
    ```

    However, Vite config is not needed (moduleResolution: bundler)
  </Tab>

  <Tab title="Consistency" icon="check">
    **Maintain team-wide consistency:**

    ```json theme={null}
    // ✅ Same across all projects
    {
      "paths": {
        "@/*": ["./src/*"]
      }
    }
    ```

    ```typescript theme={null}
    // ✅ All team members use the same method
    import { Button } from "@/components/Button";
    ```

    **Avoid:**

    ```typescript theme={null}
    // ❌ Different prefix per project
    import { Button } from "~/components/Button";  // Project A
    import { Button } from "@/components/Button";  // Project B
    import { Button } from "#/components/Button";  // Project C
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="tsconfig.json" icon="file-code" href="/en/configuration/typescript/tsconfig">
    Check the complete TypeScript configuration
  </Card>

  <Card title="Type Checking" icon="shield-check" href="/en/configuration/typescript/type-checking">
    Learn about type check options
  </Card>

  <Card title="Writing Components" icon="cube" href="/en/frontend-integration/react-components/generated-components">
    Write React components
  </Card>

  <Card title="Project Structure" icon="folder-tree" href="/en/getting-started/project-structure">
    Check the overall project structure
  </Card>
</CardGroup>
