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

# Deploying the Studio

> Serve the built Studio app from the skeleton, with the import map and OAuth-bridge notes.

The Studio ships as a static single-page app that the skeleton serves. There is
no separate Studio server to run: you point the skeleton at the built app, and
it hosts the UI on the same origin as the `/api/*` surface the UI drives.

## Serve the built app

Build the Studio to a `dist` directory, then set the skeleton's
`STUDIO_DIST_PATH` (the `studio_dist_path` setting) to that path and start the
server. The skeleton serves the app — `index.html`, the hashed asset bundles,
and the stable `vendor/` modules — under its own origin, with the `/api/*`
routes taking precedence and every other path falling back to the app shell.

```bash theme={null}
export STUDIO_DIST_PATH=/path/to/studio/dist
tai serve --manifest-path manifest.yml
```

<Frame caption="The Studio, served by the skeleton on the same origin as its API.">
  <img className="block dark:hidden" src="https://mintcdn.com/tai42/xZQ4KkTcYRU0f7y9/images/studio/tools-light.png?fit=max&auto=format&n=xZQ4KkTcYRU0f7y9&q=85&s=44784161ed838c2583a34a8245bdd0b0" alt="The Studio served by a skeleton." width="1440" height="900" data-path="images/studio/tools-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/tai42/xZQ4KkTcYRU0f7y9/images/studio/tools-dark.png?fit=max&auto=format&n=xZQ4KkTcYRU0f7y9&q=85&s=82132675dd7b6deca0b2623aff528ef0" alt="The Studio served by a skeleton." width="1440" height="900" data-path="images/studio/tools-dark.png" />
</Frame>

<Note>
  `studio_dist_path` is a per-deployment setting, not [manifest](/concepts/manifest)
  content. Leave it unset on a server that does not host the UI — the app route
  answers `404` while the path is unset.
</Note>

## Why the app must be built and served

The skeleton injects an import map into `index.html` at serve time — the map
that resolves the app's shared modules (`react`, `@tai42/studio-sdk`, and the
rest) and, for a [Studio plugin](/reference/studio-sdk/index), the plugin's
bundle. A statically previewed `index.html` carries the un-replaced import-map
anchor and dies on the first bare import, so a Studio plugin loads only against
a built app the skeleton serves — never under a plain dev server.

## The OAuth-bridge allowlist

[Connectors](/concepts/connectors) that use OAuth redirect through the skeleton,
or through its configured OAuth bridge. When `CONNECTORS_OAUTH_BRIDGE_URL` is set
on the skeleton, the bridge origin **must** also appear in the skeleton's
`CONNECTORS_REDIRECT_URI_ALLOWLIST`.

<Warning>
  If the bridge origin is missing from `CONNECTORS_REDIRECT_URI_ALLOWLIST`, every
  Connect flow fails closed — the skeleton rejects the redirect and no connector
  can be authorized.
</Warning>

See the [deploy guide](/guides/deploy) for running a server for real, the
[serve command](/reference/cli/serve) for the launch flags, and the
[Studio SDK reference](/reference/studio-sdk/index) for building a Studio plugin.
