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

# Creating Your First Entity

> Create your first entity with Sonamu UI and build an API

In this guide, you'll learn how to create a `Post` entity using Sonamu UI, create a database table, and auto-generate Model files through scaffolding.

## Prerequisites

* You must have completed the [Quick Start](/en/getting-started/quick-start) guide and have the development server running.
* The API server must be running at [http://localhost:34900](http://localhost:34900).

<Tip>
  When the API server (`pnpm dev`) is running, Sonamu UI is automatically served
  at [http://localhost:34900/sonamu-ui](http://localhost:34900/sonamu-ui).
</Tip>

## Step 1: Access Sonamu UI

Open [http://localhost:34900/sonamu-ui](http://localhost:34900/sonamu-ui) in your browser.

<Frame caption="Sonamu UI main screen (Entity, Migration, Scaffolding tabs)">
  <img src="https://mintcdn.com/cartanova-7788888c/wk-O_9zBoKGthXNV/images/sonamuUI1.png?fit=max&auto=format&n=wk-O_9zBoKGthXNV&q=85&s=637d6e1a97b920da63a7409013c92159" alt="Sonamu UI main screen" style={{ width: "100%", borderRadius: "0.75rem" }} width="3456" height="1916" data-path="images/sonamuUI1.png" />
</Frame>

Sonamu UI is a web interface for visually managing entities. Here you can:

* Create and edit entities
* Add/modify/delete props
* Define relations
* Manage Enum types
* Define Subsets
* Create and run migrations
* Scaffolding (auto-generate Model files)

## Step 2: Create a New Entity

<Steps>
  <Step title="Click Entity Tab">
    Click the **Entity** tab in the Sonamu UI top menu to see existing entities.

    <Frame caption="Entity tab screen">
      <img src="https://mintcdn.com/cartanova-7788888c/wk-O_9zBoKGthXNV/images/sonamuUI1.png?fit=max&auto=format&n=wk-O_9zBoKGthXNV&q=85&s=637d6e1a97b920da63a7409013c92159" alt="Entity tab" style={{width: '100%', borderRadius: '0.75rem'}} width="3456" height="1916" data-path="images/sonamuUI1.png" />
    </Frame>
  </Step>

  <Step title="Click New Entity Button">
    Click the **New Entity** button at the bottom of the left sidebar.

    <Frame caption="Entity creation modal">
      <img src="https://mintcdn.com/cartanova-7788888c/wk-O_9zBoKGthXNV/images/sonamuUI-create-entity.png?fit=max&auto=format&n=wk-O_9zBoKGthXNV&q=85&s=5c462c85be483a7b9126a9f1e20c1045" alt="Entity creation modal" style={{width: '100%', borderRadius: '0.75rem'}} width="1844" height="750" data-path="images/sonamuUI-create-entity.png" />
    </Frame>
  </Step>

  <Step title="Enter Basic Information and Create">
    Enter the basic information for the new entity and click the **Create** button:

    * **Entity ID**: `Post` (starts with uppercase, singular)
    * **Table Name**: `posts` (lowercase, plural)
    * **Title**: `Post`

    <Frame caption="Post entity screen after clicking Create button">
      <img src="https://mintcdn.com/cartanova-7788888c/wk-O_9zBoKGthXNV/images/sonamuUI-created-entity.png?fit=max&auto=format&n=wk-O_9zBoKGthXNV&q=85&s=8a0bfe09c51843f4ca9fad863996edc5" alt="Created Post entity" style={{ width: "100%", borderRadius: "0.75rem" }} width="2872" height="1916" data-path="images/sonamuUI-created-entity.png" />
    </Frame>

    <Note>
      **Entity ID** is used as the TypeScript class name, and **Table Name** is the actual database table name.
    </Note>
  </Step>
</Steps>

## Step 3: Define Props

Now add props to the `Post` entity:

<Steps>
  <Step title="Add Basic Props">
    Click the **Add a prop** button to add the following props:

    | Prop Name    | Type    | Description | Options                         |
    | ------------ | ------- | ----------- | ------------------------------- |
    | `id`         | integer | ID          | Primary Key                     |
    | `created_at` | date    | Created At  | DB Default: `CURRENT_TIMESTAMP` |
    | `title`      | string  | Title       | Length: 255                     |
    | `content`    | string  | Content     | -                               |
    | `author`     | string  | Author      | Length: 100                     |
    | `view_count` | integer | View Count  | DB Default: `0`                 |

    <Accordion title="How to Configure Each Prop">
      **id prop**

      * Name: `id`
      * Type: `integer`
      * Description: `ID`

      **created\_at prop**

      * Name: `created_at`
      * Type: `date`
      * Description: `Created At`
      * DB Default: `CURRENT_TIMESTAMP`

      **title prop**

      * Name: `title`
      * Type: `string`
      * Description: `Title`
      * Length: `255`

      **content prop**

      * Name: `content`
      * Type: `string`
      * Description: `Content`
      * Length: empty (creates TEXT type)

      **author prop**

      * Name: `author`
      * Type: `string`
      * Description: `Author`
      * Length: `100`

      **view\_count prop**

      * Name: `view_count`
      * Type: `integer`
      * Description: `View Count`
      * DB Default: `0`
    </Accordion>

    <Frame caption="Prop addition UI (Add a prop button and prop list with all props added)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-add-a-prop.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=22a619080a692b5f5461793f1b8a30eb" alt="Prop addition UI" style={{ width: "100%", borderRadius: "0.75rem" }} width="1698" height="728" data-path="images/sonamuUI-add-a-prop.png" />
    </Frame>
  </Step>

  <Step title="Define Subsets">
    In the **Subsets** section, define data query forms:

    * **Subset A** (Admin): `id`, `created_at`, `title`, `content`, `author`, `view_count` - Full information
    * **Subset P** (Public): `id`, `title`, `author`, `created_at` - Public information
    * **Subset SS** (Secure Short): `id`, `title`, `author` - Summary information

    <Frame caption="Subset editing screen (with Subset A, P, SS defined)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-subsets.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=453587fdd56979c99fe0badfd1a398fe" alt="Subset editing screen" style={{ width: "400px", borderRadius: "0.75rem" }} width="858" height="686" data-path="images/sonamuUI-subsets.png" />
    </Frame>

    <Note>
      Subsets pre-define which props to include when querying data through APIs.
      For details, see the [Subset Guide](/en/database/subsets/what-are-subsets).
    </Note>
  </Step>

  <Step title="Define Enums">
    In the **Enums** section, define sorting and search options:

    **PostOrderBy**

    * `id-desc`: ID newest first
    * `created_at-desc`: Created at newest first
    * `view_count-desc`: Highest view count first

    **PostSearchField**

    * `id`: ID
    * `title`: Title
    * `author`: Author

    <Frame caption="Enum editing screen (with PostOrderBy, PostSearchField defined)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-enums.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=2f16991b67226b45b80480c74d0e7802" alt="Enum editing screen" style={{ width: "800px", borderRadius: "0.75rem" }} width="1440" height="542" data-path="images/sonamuUI-enums.png" />
    </Frame>
  </Step>
</Steps>

## Step 4: Database Migration

Now you need to apply the entity definition to the database.

<Steps>
  <Step title="Go to Migration Tab">
    Click the **Migration** tab in Sonamu UI.

    <Frame caption="Migration tab screen (migration list or Generate Migration button)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-db-migration2.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=a5b7a223a30d2d8a42da6a3a397cdd2f" alt="Migration tab screen" style={{width: '100%', borderRadius: '0.75rem'}} width="2594" height="1352" data-path="images/sonamuUI-db-migration2.png" />
    </Frame>
  </Step>

  <Step title="Generate Migration">
    Click the **Generate** button to auto-generate a new migration Code File.

    Click the `<>` button in the generated file list to open the migration file page in Cursor. The file content looks like this:

    <Frame caption="Migration file opened in Cursor">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-db-migration3.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=0429a7004207d33e86a1f5927f48a097" alt="Migration file opened in Cursor" style={{width: '100%', borderRadius: '0.75rem'}} width="1478" height="1052" data-path="images/sonamuUI-db-migration3.png" />
    </Frame>
  </Step>

  <Step title="Run Migration">
    You can see pending migrations in the Migration tab.

    Click the **all** button, then click **Apply to Latest** to see migration targets in the modal.

    Select **Shadow DB Testing** and click the **commit** button to create the database table.

    <Frame caption="Migration execution complete">
      <video autoPlay muted loop playsInline controls className="w-full rounded-xl" src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUi-db-migration2-generate.mp4?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=e9aacfcd59bd521d77707c78d3e0b623" data-path="images/sonamuUi-db-migration2-generate.mp4" />
    </Frame>
  </Step>

  <Step title="Verify">
    Connect to the database using a PostgreSQL client or pgAdmin to verify the `posts` table was created.
  </Step>
</Steps>

## Step 5: Scaffolding (Auto-Generate Model Files)

After migration is complete, you can auto-generate Model files using Sonamu's scaffolding feature.

<Steps>
  <Step title="Go to Scaffolding Tab">
    Click the **Scaffolding** tab in Sonamu UI.

    <Frame caption="Scaffolding tab screen (entity list and template selection UI)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-scaffolding1.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=4276df31716045addf9af3786af7ee8d" alt="Scaffolding tab screen" style={{width: '100%', borderRadius: '0.75rem'}} width="2610" height="1058" data-path="images/sonamuUI-scaffolding1.png" />
    </Frame>
  </Step>

  <Step title="Select Post Entity">Select **Post** as the entity to scaffold.</Step>

  <Step title="Select Templates">
    Select templates to generate:

    * ✅ **Model** - `post.model.ts` (business logic and API endpoints)
    * ✅ **Model Test** - `post.model.test.ts` (test file)

    <Frame caption="Template selection UI (with Model, Model Test checkboxes selected)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-scaffolding2.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=fcf2ec2f655b636459f01bc91bb4ce9e" alt="Template selection UI" style={{ width: "100%", borderRadius: "0.75rem" }} width="2608" height="1148" data-path="images/sonamuUI-scaffolding2.png" />
    </Frame>

    <Note>
      Scaffolding auto-generates template files, so you don't need to write code from scratch. Generated files can be modified to fit your project.
    </Note>
  </Step>

  <Step title="Preview (Optional)">
    Click the **Preview** button to preview the code that will be generated.

    <Frame caption="Code preview modal (model.ts code to be generated)">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-scaffolding3.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=d0770e413ffbf7b700345f85ae1b8376" alt="Code preview modal" style={{width: '100%', borderRadius: '0.75rem'}} width="2618" height="2034" data-path="images/sonamuUI-scaffolding3.png" />
    </Frame>
  </Step>

  <Step title="Generate">
    Click the **Generate** button to create the files.

    <Frame caption="Generated file list">
      <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-scaffolding5.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=5d9a87c29279f7eeb911d7bc7e4eb77c" alt="Generated file list" style={{ width: "100%", borderRadius: "0.75rem" }} width="1548" height="442" data-path="images/sonamuUI-scaffolding5.png" />
    </Frame>

    The following files are generated:

    * `api/src/application/post/post.model.ts`
    * `api/src/application/post/post.model.test.ts`

    You can also run this from the terminal:

    ```bash theme={null}
    cd api
    pnpm sonamu scaffold model Post
    pnpm sonamu scaffold model_test Post
    ```
  </Step>
</Steps>

## Step 6: Review Generated Model File

Let's check the `post.model.ts` file generated by scaffolding:

<Frame caption="post.model.ts file opened in VS Code">
  <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/afterScaffolding-model.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=e5f22f8d0aa05689cedd3463744c7261" alt="post.model.ts file opened in VS Code" style={{ width: "100%", borderRadius: "0.75rem" }} width="2184" height="2458" data-path="images/afterScaffolding-model.png" />
</Frame>

<Info>
  The generated Model file includes basic CRUD APIs. You can add or modify
  business logic as needed.
</Info>

The API server automatically restarts via HMR (Hot Module Replacement):

<Frame caption="HMR restart logs in terminal">
  <img src="https://mintcdn.com/cartanova-7788888c/QSwN67OqJqlfz1mQ/images/sonamuUI-scaffolding4.png?fit=max&auto=format&n=QSwN67OqJqlfz1mQ&q=85&s=ee64d4198e8e5c1bca78a117d2f6bda9" alt="HMR restart logs in terminal" style={{ width: "100%", borderRadius: "0.75rem" }} width="1906" height="1102" data-path="images/sonamuUI-scaffolding4.png" />
</Frame>

## Step 7: Auto-Generate Frontend Service

When you write APIs, frontend Service files are automatically generated.

<Frame caption="📸 Needed: VS Code screen showing web/src/services/PostService.ts file created" />

```typescript title="web/src/services/PostService.ts (auto-generated)" theme={null}
export class PostService {
  static async findById(subset: PostSubsetKey, id: number) {
    const res = await axios.get(`/api/posts/${id}`, {
      params: { subset },
    });
    return res.data;
  }

  static async findMany(subset: PostSubsetKey, params?: PostListParams) {
    const res = await axios.get("/api/posts", {
      params: { subset, ...params },
    });
    return res.data;
  }

  static async save(params: PostSaveParams) {
    const res = await axios.post("/api/posts", params);
    return res.data;
  }

  static async del(id: number) {
    await axios.delete(`/api/posts/${id}`);
  }
}
```

## Step 8: Test the API

Now let's test if the API is working correctly.

### Test with REST Client

<CodeGroup>
  ```bash title="Create Post (POST)" theme={null}
  curl -X POST http://localhost:34900/api/posts \
    -H "Content-Type: application/json" \
    -d '{
      "title": "First Post",
      "content": "This is my first post created with Sonamu.",
      "author": "John Doe"
    }'
  ```

  ```bash title="List Posts (GET)" theme={null}
  curl http://localhost:34900/api/posts?subset=C
  ```

  ```bash title="Get Post Detail (GET)" theme={null}
  curl http://localhost:34900/api/posts/1?subset=A
  ```

  ```bash title="Delete Post (DELETE)" theme={null}
  curl -X DELETE http://localhost:34900/api/posts/1
  ```
</CodeGroup>

### Test in Browser

Navigate to [http://localhost:34900/api/posts?subset=C](http://localhost:34900/api/posts?subset=C) to view the JSON response.

<Frame caption="📸 Needed: Browser screen showing API response JSON (post list data)" />

## Complete! 🎉

Congratulations! You've successfully created your first entity.

You've completed the following:

* ✅ Defined entity with Sonamu UI
* ✅ Created database table
* ✅ Auto-generated types and schemas
* ✅ Auto-generated Model and Test files with scaffolding
* ✅ Auto-generated REST API
* ✅ Auto-generated frontend Service
* ✅ Tested the API

<Warning>
  **Benefits of Scaffolding**

  Using scaffolding:

  * Basic CRUD APIs are auto-generated without writing Model files from scratch
  * Test file templates are generated together, making test writing easier
  * Maintains consistent code style across the project
  * Generated code can be modified anytime to add business logic
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Development Workflow" icon="diagram-project" href="/en/getting-started/development-workflow">
    Understand Sonamu's complete development workflow and learn how to work
    efficiently.
  </Card>

  <Card title="Defining Relations" icon="link" href="/en/core-concepts/entity/relations">
    Learn how to define relationships between entities and write JOIN queries.
  </Card>

  <Card title="Puri Query Builder" icon="database" href="/en/database/puri/basic-queries">
    Learn how to write complex database queries with the type-safe query builder.
  </Card>

  <Card title="Writing Tests" icon="flask" href="/en/testing/writing-tests/test-structure">
    Learn how to test Model business logic based on the auto-generated test
    templates.
  </Card>
</CardGroup>
