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

# Create your app

> Go from zero to a running Ooneex application — install the CLI, scaffold the project, and build your first resource with the CLI or an AI prompt.

This guide takes you from an empty machine to a working Ooneex application with its first domain. You install the CLI, scaffold the project, then build a `Movie` resource — a module, an entity, a repository, and a controller.

You can build that resource in two ways: by running the CLI commands yourself, or by handing a single detailed prompt to your AI agent. Both produce the same result.

## Prerequisites

The CLI runs on [Bun](https://bun.sh). Install it first:

```bash theme={null}
curl -fsSL https://bun.sh/install | bash
```

Verify the installation:

```bash theme={null}
bun --version
```

## Step 1: Install the CLI

<Steps>
  <Step title="Install globally">
    Install `@ooneex/cli` globally with Bun. It exposes two interchangeable binaries, `ooneex` and its short alias `oo`.

    ```bash theme={null}
    bun add -g @ooneex/cli
    ```
  </Step>

  <Step title="Verify">
    Confirm the CLI is available:

    ```bash theme={null}
    ooneex help
    ```
  </Step>
</Steps>

<Tip>
  Prefer not to install globally? Run any command through `bunx` instead, for
  example `bunx @ooneex/cli@latest app:create`. See
  [Installation](/cli/installation) for Zsh completions and more.
</Tip>

## Step 2: Create the application

Scaffold a complete application with `app:create`. Run it with no flags to be prompted for the name and destination:

```bash theme={null}
ooneex app:create
```

Or pass them directly:

```bash theme={null}
ooneex app:create --name=MovieApp --destination=movie-app
```

This creates the `app` and `shared` modules, the entrypoint, the shared database, roles, Docker files, and config, then installs all dependencies. You are also offered optional CI/CD files for GitHub, GitLab, or Bitbucket.

Move into the project and start it:

```bash theme={null}
cd movie-app
ooneex app:start
```

`app:start` brings up the Docker services defined by the `app` module, then runs every `api`, `microservice`, and `spa` module concurrently — `api` and `microservice` modules serve their entrypoint with hot reload, while `spa` modules run their dev server.

<Note>
  The environment file is generated at `modules/shared/.env.yml`. Edit it to
  point at your database, Redis, and other services before starting.
</Note>

### Start only part of the app

Pass a type flag to narrow what runs. A bare flag keeps every module of that type; `--<type>=a,b` keeps only the named ones. Flags combine, so you can start several types at once.

```bash theme={null}
ooneex app:start --api                            # only the api modules
ooneex app:start --microservice                   # only the microservice modules
ooneex app:start --spa                            # only the spa modules
ooneex app:start --microservice=billing,payments  # only the named microservices
ooneex app:start --api --spa                       # the api and spa modules together
```

The shared Docker stack still comes up first regardless of the flags — they only narrow which modules are run.

When you're done, stop the app:

```bash theme={null}
ooneex app:stop
```

`app:stop` brings down the `app` module's shared Docker stack with `docker compose down`. The running module processes — spa dev servers and hot-reloaded entrypoints — stop when you interrupt the `app:start` process with <kbd>Ctrl</kbd>+<kbd>C</kbd>. A type flag narrows the stop to the named modules that ship their own `docker-compose.yml`:

```bash theme={null}
ooneex app:stop --microservice=billing   # bring down a microservice's own Docker stack
```

Build the app for production:

```bash theme={null}
ooneex app:build
```

## Project structure

`app:create` generates a Bun workspace organized around **modules**. Every module under `modules/<name>/` owns its own controllers, services, repositories, entities, and config — a self-contained vertical slice of your domain.

```
movie-app/
├── modules/
│   ├── app/                    # API module — the application entrypoint
│   │   ├── src/
│   │   │   ├── AppModule.ts     # Registers controllers, middlewares, cron jobs, events
│   │   │   ├── index.ts         # Boots the App (routing, cache, rate limit, loggers)
│   │   │   └── OnAppStart.ts    # Startup hook
│   │   ├── tests/
│   │   ├── var/
│   │   ├── app.yml              # Module config (type: api)
│   │   ├── docker-compose.yml
│   │   ├── Dockerfile
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── shared/                  # Shared module — cross-cutting code
│       ├── src/
│       │   ├── databases/
│       │   │   └── SharedDatabase.ts
│       │   ├── SharedModule.ts  # Aggregates entities from every module
│       │   └── roles.yml        # Role definitions
│       ├── tests/
│       ├── .env.yml             # Environment configuration
│       ├── package.json
│       └── tsconfig.json
├── .commitlintrc.ts            # Conventional commit rules
├── .dockerignore
├── .gitignore
├── biome.jsonc                 # Formatter and linter config
├── bunfig.toml
├── nx.json
├── package.json                # Workspace root (scripts, workspaces, lint-staged)
├── README.md
└── tsconfig.json               # Root config with module path aliases
```

Each business domain you add — like `Movie` — becomes its own module alongside `app` and `shared`, registered automatically into `AppModule`.

## Step 3: Build your first resource

With the app scaffolded, build the `Movie` domain. Choose the path that fits how you work — the CLI walks you through each artifact, while the AI prompt produces the whole slice in one pass.

<Tabs>
  <Tab title="AI prompt">
    Your project ships AI skills for every create command. Initialize them once, then give your agent a single prompt and it drives the `module:create`, `entity:create`, `repository:create`, and `controller:create` skills for you.

    Initialize the skills for your agent:

    <Tabs>
      <Tab title="Claude">
        ```bash theme={null}
        ooneex claude:init
        ```
      </Tab>

      <Tab title="Codex">
        ```bash theme={null}
        ooneex codex:init
        ```
      </Tab>
    </Tabs>

    Then copy this prompt into your agent:

    ```md theme={null}
    Build a complete `Movie` domain in my Ooneex application using the
    Ooneex CLI create skills. Follow the project's module conventions and
    generate the matching tests for every artifact.

    1. Module
       - Create a `movie` module and register it into the `app` destination.

    2. Entity — `Movie`, mapped to the `movies` table, with these columns:
       - `title`        varchar(255), required, indexed
       - `slug`         varchar(255), required, unique
       - `description`  text, nullable
       - `releaseYear`  int, required
       - `durationMin`  int, nullable          (runtime in minutes)
       - `rating`       numeric(3,1), nullable (0.0–10.0)
       - `genre`        varchar(50), nullable
       - `isPublished`  boolean, default false
       Keep the generated audit columns (id, timestamps, soft delete).

    3. Repository — `Movie`
       - Keep the generated CRUD methods.
       - Enable the `q` text search in `find` to match on `title`.
       - Add `findBySlug(slug: string)` returning a single movie or null.

    4. Controllers under `/movies`, each thin, validated, and restricted to
       `ROLE_USER`:
       - `MovieList`    GET    /movies        list with pagination + `q` search
       - `MovieRead`    GET    /movies/:id    fetch one by id
       - `MovieCreate`  POST   /movies        validate the payload, persist
       - `MovieUpdate`  PUT    /movies/:id    partial update
       - `MovieDelete`  DELETE /movies/:id    soft delete

    Wire payload, params, query, and response validation on each route, keep
    the controllers delegating to the repository, and run the formatter,
    linter, and tests when done.
    ```

    The agent scaffolds each artifact with the CLI, fills in the columns, methods, routes, and validation, and writes the tests — producing the same module structure shown in the CLI tab.
  </Tab>

  <Tab title="CLI commands">
    Run the create commands in order. Each one scaffolds the class plus a mirrored test file and registers it into the module.

    <Steps>
      <Step title="Create the module">
        Generates `modules/movie/` and registers it into `AppModule` (and its entities into `SharedModule`).

        ```bash theme={null}
        ooneex module:create --name=movie --destination=app
        ```

        See [module:create](/cli/commands/module-create).
      </Step>

      <Step title="Create the entity">
        Scaffolds a TypeORM entity. The `Entity` suffix is appended automatically, so `--name=Movie` produces `MovieEntity`, mapped to the `movies` table.

        ```bash theme={null}
        ooneex entity:create --name=Movie --module=movie --table-name=movies
        ```

        Open `modules/movie/src/entities/MovieEntity.ts` and add your columns. See [entity:create](/cli/commands/entity-create).
      </Step>

      <Step title="Create the repository">
        Scaffolds a repository with full CRUD over the entity.

        ```bash theme={null}
        ooneex repository:create --name=Movie --module=movie
        ```

        See [repository:create](/cli/commands/repository-create).
      </Step>

      <Step title="Create the controller">
        Generates an HTTP controller, registers it in the module's `controllers` array, and configures the route. Repeat with different names, paths, and methods for each endpoint.

        ```bash theme={null}
        ooneex controller:create \
          --name=MovieList \
          --module=movie \
          --is-socket=false \
          --route-name=movie.list \
          --route-path=/movies \
          --route-method=get
        ```

        See [controller:create](/cli/commands/controller-create).
      </Step>
    </Steps>
  </Tab>
</Tabs>

### Resulting module structure

Either path produces the same module — a complete vertical slice for the `Movie` domain:

```
modules/movie/
├── src/
│   ├── controllers/
│   │   └── MovieListController.ts   # Route config + handler
│   ├── entities/
│   │   └── MovieEntity.ts           # TypeORM entity → movies table
│   ├── repositories/
│   │   └── MovieRepository.ts       # CRUD over MovieEntity
│   └── MovieModule.ts               # Registers controllers, entities, …
├── tests/
│   ├── controllers/
│   ├── entities/
│   ├── repositories/
│   └── MovieModule.spec.ts
├── movie.yml                        # Module config
├── package.json
└── tsconfig.json
```

## Next steps

<CardGroup cols={2}>
  <Card title="CLI commands" icon={<Icon icon="terminal" size={16} />} href="/cli/commands/app-create">
    Explore every generator — services, events, migrations, seeds, and more.
  </Card>

  <Card title="Controllers" icon={<Icon icon="route" size={16} />} href="/components/controller">
    Learn routing, validation, and role-based access in depth.
  </Card>

  <Card title="Entities" icon={<Icon icon="database" size={16} />} href="/components/entity">
    Model your data with TypeORM entities and the shared database.
  </Card>

  <Card title="Repositories" icon={<Icon icon="layer-group" size={16} />} href="/components/repository">
    Query and persist data with the repository pattern.
  </Card>
</CardGroup>
