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

# Deploying Flows custom apps

> Deploy your Flows custom app to Cognite Data Fusion (CDF) with interactive or automated deployment and App Hosting lifecycle commands.

You can deploy your Flows custom app to CDF **interactively** from your machine (browser sign-in, no OAuth secrets in the terminal) or **automate** deployment in CI/CD with client credentials.

## Interactive deployment

The simplest path uses your browser for sign-in—no OAuth configuration in the terminal:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npx @cognite/cli@latest apps deploy --interactive
```

This will:

1. Build your app.
2. Open a browser window for you to sign in to CDF.
3. Prompt you to select a deployment target from `app.json`.
4. Package and deploy to your configured project.
5. Show a link to your deployed app.

### Options

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
# Use the first deployment target (skip selection prompt)
npx @cognite/cli@latest apps deploy --interactive -d 0

# Use a specific project by name
npx @cognite/cli@latest apps deploy --interactive -d your-project-name

# Skip the build step (if already built)
npx @cognite/cli@latest apps deploy --interactive --skip-build
```

### Draft and published versions

`apps deploy` uploads your app as a **Draft** version. To publish and activate it, see [App lifecycle](/cdf/flows/concepts/app-lifecycle).

<Info>
  `--published` flag is used for legacy apps:

  | Scenario                            | Behavior                                                                                                  |
  | ----------------------------------- | --------------------------------------------------------------------------------------------------------- |
  | Legacy app, `--published` flag      | Honored — deploys as published                                                                            |
  | App Hosting app, `--published` flag | Warning printed, flag ignored — always deploys as DRAFT. Use `apps publish .` / `apps activate .` instead |

  For App Hosting apps, use `npx @cognite/cli@latest apps publish .` and `npx @cognite/cli@latest apps activate .` to control visibility.
</Info>

## App Hosting lifecycle commands

For apps using App Hosting infrastructure (`"infra": "appsApi"` in `app.json`), use the following commands to manage the version lifecycle after deployment. Each version progresses through the states: **DRAFT → PUBLISHED → ACTIVE**.

### Check status

Print the current deployment status of your app version:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npx @cognite/cli@latest apps status .
```

### Publish a version

Transition the current version from DRAFT to PUBLISHED (visible but not yet the active version):

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npx @cognite/cli@latest apps publish .
```

This command is idempotent — re-running on an already PUBLISHED or ACTIVE version is a no-op.

### Activate a version

Set the current version as ACTIVE (the version users see). Publish the version if it's still DRAFT:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npx @cognite/cli@latest apps activate .
```

If a previous version was active, the output reports which version it replaced.

<Tip>
  Use `--interactive` to authenticate via browser sign-in when running these commands from your machine:

  ```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
  npx @cognite/cli@latest apps status . --interactive
  npx @cognite/cli@latest apps publish . --interactive
  npx @cognite/cli@latest apps activate . --interactive
  ```
</Tip>

## Automated deployment (CI/CD)

For CI/CD pipelines, configure client credentials.

### Prerequisites

1. **OAuth client** — A client ID registered in your CDF project.
2. **Client secret** — The secret for that client.
3. **Capabilities** — The `apphosting:read` and `apphosting:write` capabilities granted to the client via a group. These capabilities can be scoped to the app's `externalId` from `app.json`. Add `apphosting:run` if the same client also needs to run the app. See [Assign capabilities](/cdf/access/guides/capabilities#flows-custom-apps).

Ask your Cognite administrator to register an OAuth client with the required permissions.

### Step 1: Configure app.json

Add `deployClientId` and `deploySecretName` to your deployment configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "name": "My App",
  "description": "My awesome Flows app",
  "externalId": "my-app",
  "versionTag": "1.0.0",
  "deployments": [
    {
      "org": "my-org",
      "project": "my-project",
      "baseUrl": "https://api.cognitedata.com",
      "deployClientId": "your-client-id",
      "deploySecretName": "MY_APP_SECRET"
    }
  ]
}
```

| Field              | Description                                                                                                          |
| ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `name`             | Display name in CDF                                                                                                  |
| `externalId`       | Unique identifier (kebab-case)                                                                                       |
| `versionTag`       | Semantic version                                                                                                     |
| `deployClientId`   | OAuth client ID                                                                                                      |
| `deploySecretName` | Environment variable name for the secret                                                                             |
| `idpType`          | Identity provider (`cdf` or `entra_id`). Defaults to `cdf`                                                           |
| `tenantId`         | Microsoft Entra tenant ID (required when `idpType` is `entra_id`)                                                    |
| `published`        | Legacy field: whether the app is visible to end users. Prefer `apps publish` / `apps activate` for App Hosting apps. |

#### Microsoft Entra ID deployment

Set `idpType` to `entra_id` and provide `tenantId`:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "deployments": [
    {
      "org": "my-org",
      "project": "my-project",
      "baseUrl": "https://api.cognitedata.com",
      "deployClientId": "your-entra-client-id",
      "deploySecretName": "MY_APP_SECRET",
      "idpType": "entra_id",
      "tenantId": "00000000-0000-0000-0000-000000000000"
    }
  ]
}
```

When `idpType` is `entra_id`, Flows requests a token from Microsoft Entra ID and derives the CDF scope from `baseUrl` (for example, `https://greenfield.cognitedata.com/.default`).

### Step 2: Set the secret

Export the client secret:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
export MY_APP_SECRET="your-client-secret"
```

<Tip>
  In CI/CD, store secrets in your platform’s secret manager (for example, GitHub Actions repository secrets, Azure DevOps variable groups, or GitLab CI variables).
</Tip>

### Step 3: Deploy

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npm run deploy
```

This will:

1. Build your app (`tsc && vite build`).
2. Package `dist/` into a zip.
3. Authenticate with client credentials.
4. Upload through the CDF Files API.
5. Make the app available in CDF.

### Preview deployments

For pull request previews:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npm run deploy-preview
```

### Multiple environments

Add multiple entries to `deployments`:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "deployments": [
    {
      "org": "your-org",
      "project": "dev-project",
      "baseUrl": "https://api.cognitedata.com",
      "deployClientId": "dev-client-id",
      "deploySecretName": "DEV_SECRET"
    },
    {
      "org": "your-org",
      "project": "prod-project",
      "baseUrl": "https://api.cognitedata.com",
      "deployClientId": "prod-client-id",
      "deploySecretName": "PROD_SECRET"
    }
  ]
}
```

## Versioning

Update `versionTag` in `app.json` for each release:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "versionTag": "1.2.0"
}
```

Each version is stored in CDF so you can roll back if needed.

## Troubleshooting

### What permissions do I need to deploy?

Your OAuth client (for CI/CD) or user account (for interactive deployment) needs `apphosting:read` and `apphosting:write`. You can scope these capabilities to the app's `externalId` from `app.json`. Add `apphosting:run` if the same principal also needs to run the app. See [Assign capabilities](/cdf/access/guides/capabilities#flows-custom-apps).

### "Deployment secret not found"

Ensure the environment variable name matches `deploySecretName`:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
export MY_APP_SECRET="your-secret"
```

### "Failed to authenticate"

Check that:

* The client ID is correct.
* The client secret is valid and not expired.
* The client has the required CDF permissions (including Files API write access).

### Build fails

Run the build locally:

```bash theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
npm run build
```

### Interactive sign-in issues

1. Confirm you have access to the CDF project.
2. Ensure pop-ups are not blocked.
3. Try `npx @cognite/cli@latest apps deploy --interactive --org your-org` as a hint.

## Further reading

* [Get started with Flows](/cdf/flows/guides/getting-started) — Create an app and first deploy.
* [Run your app locally](/cdf/flows/guides/running-locally) — Dev server, HTTPS, and troubleshooting.
* [App lifecycle](/cdf/flows/concepts/app-lifecycle) — Draft, published, and active versions.
* [Auth API](/cdf/flows/reference/api/auth) — Tokens and SDK usage related to deployment identities.
