Provides the Vite-powered React 19 single-page application for deco Studio.
| Attribute | Value |
|---|---|
| Workspace | @decocms/studio-web (apps/web) |
| Kind | React single-page application |
| Runtime | Browser; Vite runs on Node.js |
| Distribution | Private static bundle; GHCR studio-nginx image |
Studio Web is the browser interface for the Studio control plane. It renders organization-scoped chats, agents, connections, files, reports, monitoring, settings, and deployment administration while consuming the API over same-origin HTTP, MCP, and streaming routes.
The workspace builds independently to apps/web/dist. The combined Studio build
copies that directory into apps/api/dist/client; the release pipeline also
packages the same assets in the studio-nginx image.
- Define public, authenticated, organization-scoped, and instance-admin routes.
- Render the Studio shell, chats, projects, agents, connections, tools, monitoring, files, reports, onboarding, and settings.
- Manage browser authentication, organization selection, query state, and streaming interactions.
- Provide the app-local browser SDK under
src/sdk. - Render MCP app resources and embedded application views.
- Own web localization, preferences, themes, design-system composition, and static assets.
- Proxy development traffic to the API without changing production request paths.
- Produce the static production bundle consumed by the combined distribution and nginx image.
Install dependencies and start the complete Studio development environment from the repository root:
bun install
bun run devTo run only Vite, start the API separately and then run:
bun run --cwd=apps/web devVite listens on http://localhost:4000 and proxies server routes to
http://localhost:3000 by default.
Build only the static client with:
bun run --cwd=apps/web buildBuild the released API and web artifact together with:
bun run build:studiosrc/router.tsx creates the TanStack Router tree and mounts the top-level
providers; src/index.web.tsx is the browser entry that renders it (the Tauri
desktop build has its own entry, src/index.native.tsx). Route components load
lazily, TanStack Query manages remote state, and shared UI primitives come from
@decocms/ui.
TanStack Router
|
v
providers and layouts
|
+----> views and feature components
|
+----> browser SDK and API clients
|
v
Vite same-origin proxy
|
v
Studio API
Key paths:
| Path | Purpose |
|---|---|
src/index.web.tsx |
Web application entry point |
src/index.native.tsx |
Tauri desktop application entry point |
src/router.tsx |
TanStack Router route tree |
src/routes/ |
Route components and route-specific logic |
src/layouts/ |
Authenticated shell and shared page layouts |
src/views/ |
Domain-oriented application views |
src/components/ |
Reusable Studio components |
src/providers/ |
Authentication, theme, analytics, and root providers |
src/hooks/ and src/lib/ |
Browser hooks, API clients, and utilities |
src/sdk/ |
App-local browser-facing Studio client APIs |
src/i18n/ |
English and Brazilian Portuguese dictionaries and useT() |
public/ |
Static assets copied unchanged to the build |
test/ and playwright-ct.config.ts |
Test setup and component-test configuration |
vite.config.ts |
Build, React Compiler, Tailwind, aliases, and development proxy |
The build injects the version from apps/api/package.json as
__STUDIO_VERSION__, keeping API and web release metadata aligned.
Run focused checks from the repository root:
bun run --cwd=apps/web check
bun run --cwd=apps/web test
bun run --cwd=apps/web test:ct
bun run --cwd=apps/web buildUse test:ct:ui for Playwright's interactive component-test runner:
bun run --cwd=apps/web test:ct:uiUnit tests cover pure browser logic. Component tests run through Playwright.
Cross-process user flows belong in packages/e2e. Run bun run fmt from the
repository root after code changes.
Vite development must run on Node.js through the manifest's vite dev command.
Do not change it to bun --bun vite dev: the proxy depends on Node's
ServerResponse close event to cancel aborted streaming and long-poll requests.
apps/webowns browser behavior and user-facing copy. It does not own Hono routes, database access, migrations, secrets, or server infrastructure.- Never import from
apps/api/src. Communicate through HTTP/MCP routes and put isomorphic contracts in explicit@decocms/shared/*exports. - Keep React hooks, contexts, and other browser runtime code in
apps/web, includingsrc/sdk; do not move them into the shared package. - Consume design-system primitives from
@decocms/uiand use design tokens rather than raw palette values. - Route every user-facing string through
useT(). Add matching English and Brazilian Portuguese dictionary entries. - Keep backend identifiers and wire contracts named
thread; render the concept as a chat in user-facing copy. - React Compiler handles memoization. Do not add
useMemo,useCallback, ormemo, and use the repository-approved alternatives touseEffect.
vite.config.ts proxies /api, /mcp, /oauth-proxy, /.well-known, /org,
/health, and /metrics to the API.
| Setting | Purpose | Default |
|---|---|---|
VITE_PORT |
Vite listener and HMR client port | 4000 |
PORT |
API port used to construct the proxy target | 3000 |
HOST=0.0.0.0 |
Bind Vite on all interfaces for sandbox previews | Disabled |
The client deliberately uses relative server URLs. Do not add a separate browser API origin when the same-origin proxy or production front door can route the request.