> ## 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.

# Sync Targets

> Frontend type/service synchronization settings

export const FileItem = ({name, description, children}) => {
  const isLeaf = !children;
  const ext = getFileExtension(name);
  const extStyle = ext ? getExtensionStyle(ext) : null;
  return <div style={{
    marginLeft: "30px"
  }}>
      <div style={{
    display: "flex",
    alignItems: "center",
    gap: "4px"
  }}>
        <span style={{
    position: "relative",
    display: "inline-block"
  }}>
          <span className="file-icon">{isLeaf && !name.endsWith("/") ? "📄" : "📁"}</span>
          {ext && <span style={{
    position: "absolute",
    bottom: "2px",
    right: "0px",
    fontSize: "5px",
    fontWeight: "bold",
    padding: "1px",
    borderRadius: "2px",
    lineHeight: "1",
    minWidth: "8px",
    textAlign: "center",
    ...extStyle
  }}>
              {ext}
            </span>}
        </span>
        <code>{name}</code>
        {description && <span className="description"> - {description}</span>}
      </div>
      {children}
    </div>;
};

export const FileTree = ({children}) => {
  return <div className="file-tree" style={{
    margin: "20px",
    marginLeft: "-30px"
  }}>
      {children}
    </div>;
};

Sonamu automatically generates type definitions and Service code when Entities and APIs change, synchronizing them to frontend projects. Use `sync.targets` to specify the frontends to sync to.

## Basic Structure

```typescript theme={null}
import { defineConfig } from "sonamu";

export default defineConfig({
  sync: {
    targets: ["web"], // Sync to web folder
  },
  // ...
});
```

## targets

Specifies the list of frontend projects to synchronize.

**Type**: `string[]` (required)

```typescript theme={null}
export default defineConfig({
  sync: {
    targets: ["web", "app"], // Sync to 2 projects
  },
});
```

### How It Works

When Entities or APIs change, Sonamu automatically generates and synchronizes the following files to each target directory:

1. **Type Definitions** (`{entity}.types.ts`)
   * TypeScript types generated from Entity fields
   * Zod validation schemas
   * Subset types

2. **Service Classes** (`{entity}.service.ts`)
   * Type-safe methods for API calls
   * TanStack Query integration ready

### Directory Structure

<Card>
  <FileTree>
    <FileItem name="project-root/">
      <FileItem name="api/" description="Backend">
        <FileItem name="src/">
          <FileItem name="application/">
            <FileItem name="user/">
              <FileItem name="user.entity.json" />

              <FileItem name="user.model.ts" />
            </FileItem>
          </FileItem>
        </FileItem>
      </FileItem>

      <FileItem name="web/" description="First target">
        <FileItem name="src/">
          <FileItem name="services/">
            <FileItem name="user.types.ts" description="Auto-generated" />

            <FileItem name="user.service.ts" description="Auto-generated" />
          </FileItem>
        </FileItem>
      </FileItem>

      <FileItem name="app/" description="Second target">
        <FileItem name="src/">
          <FileItem name="services/">
            <FileItem name="user.types.ts" description="Auto-generated" />

            <FileItem name="user.service.ts" description="Auto-generated" />
          </FileItem>
        </FileItem>
      </FileItem>
    </FileItem>
  </FileTree>
</Card>

## Single Frontend

The most common case, using only one web frontend.

```typescript theme={null}
export default defineConfig({
  sync: {
    targets: ["web"],
  },
  // ...
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="my-project/">
      <FileItem name="api/" description="Sonamu backend" />

      <FileItem name="web/" description="React/Vue frontend" />
    </FileItem>
  </FileTree>
</Card>

**Sync location**: `web/src/services/`

## Multiple Frontends

When developing web and app (React Native, Flutter, etc.) simultaneously:

```typescript theme={null}
export default defineConfig({
  sync: {
    targets: ["web", "app"],
  },
  // ...
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="my-project/">
      <FileItem name="api/" description="Sonamu backend" />

      <FileItem name="web/" description="Web frontend" />

      <FileItem name="app/" description="Mobile app" />
    </FileItem>
  </FileTree>
</Card>

**Sync locations**:

* `web/src/services/`
* `app/src/services/`

<Tip>
  Each frontend shares the same types and Services, so all clients are automatically updated when
  APIs change.
</Tip>

## target Directory Location

By default, Sonamu looks for directories with the same name as the target in the project root.

<Card>
  <FileTree>
    <FileItem name="project-root/">
      <FileItem name="api/" description="Where Sonamu runs" />

      <FileItem name="web/" description="targets: [&#x22;web&#x22;]" />

      <FileItem name="mobile-app/" description="targets: [&#x22;mobile-app&#x22;]" />
    </FileItem>
  </FileTree>
</Card>

### Custom Paths

If target directories are in different locations, you can use relative paths:

```typescript theme={null}
export default defineConfig({
  sync: {
    targets: ["../frontend/web", "../mobile/app"],
  },
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="workspace/">
      <FileItem name="backend/">
        <FileItem name="api/" description="Sonamu run location" />
      </FileItem>

      <FileItem name="frontend/">
        <FileItem name="web/" description="../frontend/web" />
      </FileItem>

      <FileItem name="mobile/">
        <FileItem name="app/" description="../mobile/app" />
      </FileItem>
    </FileItem>
  </FileTree>
</Card>

## Verifying Sync

When you modify and save an Entity, sync messages appear in the console:

```bash theme={null}
✨ Syncing to targets...
   → web/src/services/user.types.ts
   → web/src/services/user.service.ts
   → app/src/services/user.types.ts
   → app/src/services/user.service.ts

✅ All files are synced!
```

### Generated Files

Two files are generated for each Entity:

**user.types.ts**:

```typescript theme={null}
// Auto-generated types
export type UserSaved = {
  id: number;
  email: string;
  name: string;
  createdAt: Date;
};

export type UserForm = {
  email: string;
  name: string;
};

// Zod schema
export const UserFormSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1),
});
```

**user.service.ts**:

```typescript theme={null}
// Auto-generated Service
export class UserService {
  static async list(params: UserListParams): Promise<UserSaved[]> {
    return apiClient.get("/api/user/list", { params });
  }

  static async detail(id: number): Promise<UserSaved> {
    return apiClient.get(`/api/user/${id}/detail`);
  }

  static async save(form: UserForm): Promise<UserSaved> {
    return apiClient.post("/api/user/save", form);
  }
}
```

## Disabling Sync

If there's no frontend or sync is not needed, specify an empty array:

```typescript theme={null}
export default defineConfig({
  sync: {
    targets: [], // No sync
  },
  // ...
});
```

<Note>Sync can be disabled for API-only projects (e.g., microservices).</Note>

## Practical Examples

### Basic Web Project

```typescript theme={null}
import { defineConfig } from "sonamu";

export default defineConfig({
  projectName: "MyApp",

  sync: {
    targets: ["web"],
  },

  // ...
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="my-app/">
      <FileItem name="api/">
        <FileItem name="src/">
          <FileItem name="application/">
            <FileItem name="user/" />

            <FileItem name="post/" />

            <FileItem name="comment/" />
          </FileItem>
        </FileItem>
      </FileItem>

      <FileItem name="web/">
        <FileItem name="src/">
          <FileItem name="services/" description="Sync location">
            <FileItem name="user.types.ts" />

            <FileItem name="user.service.ts" />

            <FileItem name="post.types.ts" />

            <FileItem name="post.service.ts" />

            <FileItem name="comment.types.ts" />

            <FileItem name="comment.service.ts" />
          </FileItem>
        </FileItem>
      </FileItem>
    </FileItem>
  </FileTree>
</Card>

### Web + Mobile App

```typescript theme={null}
import { defineConfig } from "sonamu";

export default defineConfig({
  projectName: "EcommerceApp",

  sync: {
    targets: ["web", "mobile"],
  },

  // ...
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="ecommerce/">
      <FileItem name="api/" description="Sonamu backend">
        <FileItem name="src/application/">
          <FileItem name="product/" />

          <FileItem name="order/" />

          <FileItem name="user/" />
        </FileItem>
      </FileItem>

      <FileItem name="web/" description="React web app">
        <FileItem name="src/services/">
          <FileItem name="product.types.ts" />

          <FileItem name="product.service.ts" />

          <FileItem name="..." />
        </FileItem>
      </FileItem>

      <FileItem name="mobile/" description="React Native app">
        <FileItem name="src/services/">
          <FileItem name="product.types.ts" />

          <FileItem name="product.service.ts" />

          <FileItem name="..." />
        </FileItem>
      </FileItem>
    </FileItem>
  </FileTree>
</Card>

### Monorepo Structure

```typescript theme={null}
import { defineConfig } from "sonamu";

export default defineConfig({
  projectName: "MonorepoApp",

  sync: {
    targets: ["../packages/web-client", "../packages/admin-panel", "../packages/mobile-app"],
  },

  // ...
});
```

**Project structure**:

<Card>
  <FileTree>
    <FileItem name="monorepo/">
      <FileItem name="apps/">
        <FileItem name="api/" description="Sonamu run location">
          <FileItem name="sonamu.config.ts" />
        </FileItem>
      </FileItem>

      <FileItem name="packages/">
        <FileItem name="web-client/" description="Customer web">
          <FileItem name="src/services/" />
        </FileItem>

        <FileItem name="admin-panel/" description="Admin panel">
          <FileItem name="src/services/" />
        </FileItem>

        <FileItem name="mobile-app/" description="Mobile app">
          <FileItem name="src/services/" />
        </FileItem>
      </FileItem>
    </FileItem>
  </FileTree>
</Card>

## Sync Cautions

### 1. Don't Modify Auto-generated Files

Synced files are auto-generated, so don't modify them directly.

```typescript theme={null}
// ❌ Don't modify!
// web/src/services/user.service.ts

export class UserService {
  static async list() {
    // Code added here will be lost on next sync!
  }
}
```

**Use a wrapper class instead**:

```typescript theme={null}
// ✅ Manage in separate file
// web/src/services/user-wrapper.ts

import { UserService } from "./user.service";

export class UserServiceWrapper {
  static async listActiveUsers() {
    const users = await UserService.list();
    return users.filter((u) => u.status === "active");
  }
}
```

### 2. Git Management

Commit synced files to Git.

```gitignore theme={null}
# ❌ Don't add to .gitignore
# web/src/services/

# ✅ Should be included in Git
```

**Reasons**:

* Team members can develop frontend without running backend
* CI/CD can build frontend without Sonamu

### 3. Verify target Directory Exists

The directory specified as target must exist.

```bash theme={null}
# Error if directory doesn't exist
❌ Error: Sync target 'web' not found at ../web
```

**Solution**:

```bash theme={null}
# Create target directories
mkdir web
mkdir app
```

## Frontend Setup

Some configuration is needed in the frontend to use synced Services.

### 1. API Client Setup

**web/src/lib/api-client.ts**:

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

export const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_URL ?? "http://localhost:34900",
  withCredentials: true,
});
```

### 2. Using Services

```typescript theme={null}
import { UserService } from "@/services/user.service";

// API calls
const users = await UserService.list();
const user = await UserService.detail(1);
```

→ [Frontend Integration Guide](/en/frontend-integration/generated-services/using-services)

## Next Steps

After completing sync target configuration:

* [frontend-integration](/en/frontend-integration/generated-services/how-services-work) - How to use Services
* [storage](/en/configuration/sonamu-config/storage) - File storage settings
* [cache](/en/configuration/sonamu-config/cache) - Cache settings
