# Applications and Ports

> Cordium documentation. Canonical page: <https://octelium.com/docs/cordium/latest/workspaces/applications>.

Applications are named TCP ports inside a *Workspace* that are served over HTTPS by the Cordium portal's reverse proxy. They make development servers, notebooks, dashboards and APIs running inside your *Workspaces* reachable from your browser, authenticated by your Octelium identity, without any port forwarding or public exposure.

## Defining Applications

Applications are defined in the `spec.applications` field of a *Workspace*:

```yaml
spec:
  applications:
    - name: web
      displayName: Storefront
      port: 5173
      isDefault: true
    - name: api
      port: 8080
    - name: storybook
      port: 6006
```

| Field         | Description                                                                                                |
| ------------- | ---------------------------------------------------------------------------------------------------------- |
| `name`        | A unique name that is used as a subdomain prefix of the *Workspace*'s hostname.                            |
| `displayName` | An optional human-friendly name shown in the portal.                                                       |
| `port`        | The TCP port that the application listens on inside the *Workspace*.                                       |
| `isDefault`   | Serves the application at the *Workspace*'s root hostname. At most one application can be the default one. |

You can also define them via the `--port` flag of `cordium run` and `cordium create workspace` in the `PORT`, `NAME:PORT` or `NAME:PORT:default` format:

```bash
cordium run --image node:24-bookworm \
  --repository https://github.com/acme-corp/storefront \
  --port web:5173:default \
  --port api:8080
```

> **Note:**
>
> Applications must listen on all interfaces (i.e. `0.0.0.0`) inside the *Workspace*, not only on `localhost`, since the portal reaches them through the *Workspace*'s internal tunnel interface. For example, use `vite --host 0.0.0.0`, `jupyter lab --ip=0.0.0.0` or `next dev -H 0.0.0.0`.

## Accessing Applications

Once the *Workspace* is `PREPARING` or `RUNNING`, its applications are reachable at the following URLs:

| URL                                                  | What it serves                                                                                              |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `https://<WORKSPACE>.cordium.<DOMAIN>`               | The default application, or the port `8080` if no application is the default one.                           |
| `https://<APPLICATION>_<WORKSPACE>.cordium.<DOMAIN>` | A named application (e.g. `https://api_x7k2.cordium.example.com`).                                          |
| `https://port_<PORT>_<WORKSPACE>.cordium.<DOMAIN>`   | Any port, even if it is not declared as an application (e.g. `https://port_9229_x7k2.cordium.example.com`). |

*Workspaces* running in a *Region* other than `default` use `<WORKSPACE>.<REGION>.cordium.<DOMAIN>` instead. You can find a running *Workspace*'s hostname in its `status.hostname` field, in the portal, and in the `CORDIUM_HOSTNAME` environment variable inside it.

Applications are authenticated by your Octelium *Session*: in a browser, you simply log in once via the *Cluster*'s identity providers. Programs and AI agents can access them with an Octelium access token, for example via the Go SDK's authorized HTTP client (read more [here](https://octelium.com/docs/cordium/latest/use/api.md)). Every request to an application counts as activity for the *Workspace*'s inactivity timeout.

## Sharing Applications

By default, only the *Workspace*'s owner can access its applications. You can share a named application from the portal or via the `ShareWorkspacePort` API, either with the members of the *Workspace*'s *Space* (`MEMBERS`) or with all the *Users* of the *Cluster* (`ALL`). Shared applications are only accessible via their named URL (i.e. `https://<APPLICATION>_<WORKSPACE>.cordium.<DOMAIN>`), which is perfect for sharing a preview of a branch with your teammates or for a quick design review. Here is an example via the Go SDK:

```go
if err := ws.SharePort(ctx, "web", cordium.ShareWithMembers); err != nil {
	return err
}
fmt.Println("Share this URL with your teammates:", ws.AppURL("web"))
```

You can stop sharing an application at any time from the portal or via the `UnshareWorkspacePort` API. The sharing state is part of the *Workspace*'s status (i.e. `status.sharedPorts`).

> **Note:**
>
> To expose a *Workspace*'s application beyond Cordium (e.g. to anonymous visitors, to external webhooks, or as a full-fledged Octelium *Service* with its own *Policies* and visibility), serve it as an Octelium *Service* from the *Workspace* instead (read more [here](https://octelium.com/docs/cordium/latest/workspaces/secretless.md#serving-services)).
