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

> ## Agent Instructions
> Choose User guide for browser tasks, Developers for CLI, SDK and external agents, and Administration for organization management.
> Confirm identity and organization/project context before operations. Documentation access does not grant ThinkPlatform permissions.
> Review side effects, verify changes with a read, and do not blindly retry an operation with an uncertain outcome.
> Use documented UI steps for the web app and documented public CLI or SDK interfaces for automation. Follow each page’s prerequisites and authentication requirements.

# Publish a web app

> Build a container app from source, publish it behind ThinkPlatform authentication, and open it from Canvas.

Use **ThinkPlatform-client 0.6.134** with an authenticated saved profile for the intended organization and project. Hosted Apps and source builds must be enabled and configured by your deployment administrator. You need permission to publish to the project and use its Registry and build infrastructure. This guide publishes a small new app; do not reuse an existing app ID without reviewing its current release.

## Prepare a small application

Create an `app-example` directory containing these two files. This example serves a static page and requests no Table or Lakehouse access.

```html index.html theme={"system"}
<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <title>Inspection app</title>
  <h1>Inspection app</h1>
  <p>Published with ThinkPlatform.</p>
</html>
```

```dockerfile Dockerfile theme={"system"}
FROM python:3.12-slim
WORKDIR /app
COPY index.html .
CMD ["python", "-m", "http.server", "8080", "--bind", "127.0.0.1"]
```

The app listens on loopback port `8080` inside its container; the ThinkPlatform authentication sidecar provides browser access. Source publication builds a Linux amd64 image remotely, so an Agent Workspace does not need a local Docker daemon. Test the page locally before uploading your source.

## Create the companion Dynamic UI

The publication API requires a companion HTML Dynamic UI in the same project. Save this as `companion-ui.json`:

```json theme={"system"}
{
  "renderer": "html",
  "title": "Inspection app",
  "owner": {"scope": "project"},
  "html": "<!doctype html><title>Inspection app</title>"
}
```

```bash theme={"system"}
tp dynamic-ui create --body @companion-ui.json
```

Record the returned `uiId` as `UI_ID`. The companion identifies the app's project resource; the container serves the actual UI.

## Publish and inspect

Generate one request UUID and save it with your publication inputs. In Bash:

```bash theme={"system"}
REQUEST_UUID=$(python -c 'import uuid; print(uuid.uuid4())')
tp apps publish inspection-app --name "Inspection app" --source ./app-example --ui-id "$UI_ID" --request-id "$REQUEST_UUID"
tp apps show inspection-app
```

On PowerShell, assign the UUID with `$REQUEST_UUID = [guid]::NewGuid().ToString()` and pass `$UI_ID` and `$REQUEST_UUID` in the same command. Set `UI_ID` to your actual returned value first.

Inspect readiness, release and URL. The default wait is 300 seconds; a timeout does not prove that publication failed. Retain the request UUID, source and options, inspect the recorded state, and resume the same operation when appropriate. Do not repeatedly submit new request IDs while an earlier result is uncertain.

> [accordion] Use an image, grant data access, or control waiting
>
> Use `--image` instead of `--source` for an authorized Registry image with an immutable `@sha256:` digest. Source upload is limited to 50 MiB compressed. The CLI does not interpret `.dockerignore`: within Git it uses tracked and nonignored untracked files, plus built-in exclusions. Review tracked inputs and use `.gitignore` for local-only files. Outside Git, prepare a dedicated source directory. Exclude credentials, profiles and unrelated data yourself.
>
> Use repeated `--table-read` or `--table-write` options for exact Table IDs, `--lakehouse-read` for delegated Lakehouse reads, and `--project-permission` only for an accepted read permission shown in help. Publication permissions, the current user's permissions and resource scope all apply. The app must use the [request-bound SDK](https://docs.thinkplatform.ai/python-sdk/hosted-apps.md); do not put a personal token in the image. Keep `--legacy-table` only for existing apps that require that separate bridge.
>
> `--wait 0` submits one step without polling. Other values range from 0 to 1800 seconds. Keep the same request ID and inputs when resuming; an explicitly terminal failure requires diagnosis rather than an automatic resubmission loop.

## Open it from Canvas

Save `app-page.json` with the stable app ID:

```json theme={"system"}
{
  "title": "Inspection app",
  "layout": {"surface": "application", "contentWidth": "full"},
  "application": {"source": {"kind": "hosted-app", "appId": "inspection-app"}},
  "blocks": []
}
```

```bash theme={"system"}
tp canvas pages create --body @app-page.json
```

Open `/canvas/PAGE_ID` on your ThinkPlatform host, replacing `PAGE_ID` with the returned page ID. Check that **Inspection app** appears. If permissions were requested, review the consent before continuing. A successful CLI publication alone does not verify another person's access or an app's data writes; test the intended action and read its stored result back.

## Update or stop an app

Read the current release first:

```bash theme={"system"}
tp apps show inspection-app
```

For an update, generate a new request UUID and publish with `--replaces` set to the exact previous release. Retain that release and the new UUID on retries. Use `--replaces-stopped` only if that exact previous release is stopped. Inspect `tp apps publish --help` for `--replace-current` and the full update options.

To stop a release you own and intend to retire:

```bash theme={"system"}
tp apps stop inspection-app --release "$RELEASE"
tp apps show inspection-app
```

Set `RELEASE` to the inspected release ID. Stopping unpublishes the release and stops its runtime; preserve shared Tables, files and Canvas pages unless you intend to remove those separately.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.