---
title: 'Studio extensions'
description: 'Install bundled apps and extend the Studio interface.'
---

# Studio extensions

Studio extensions contribute apps, fields, previews, and supported navigation components to a configured Studio project. They are client UI extensions; server-side business logic belongs in [custom tools](/docs/automations/custom-tools).

A package is the npm distribution unit: for example, `@flexkit/desk` is an official Flexkit Studio extension. An integration connects to an external product or service. An **Agent Plugin** is a portable package conforming to the [Agent Plugins standard](https://agent-plugins.org/); Agent Plugin loading and marketplace support are future features, separate from Studio composition.

## Bundled extensions

| Package                  | Factory          | Purpose                                         |
| ------------------------ | ---------------- | ----------------------------------------------- |
| `@flexkit/desk`          | `Desk()`         | Schema-driven record lists and forms.           |
| `@flexkit/asset-manager` | `AssetManager()` | File library and organization.                  |
| `@flexkit/explorer`      | `Explorer()`     | GraphQL workspace.                              |
| `@flexkit/ai`            | `AI()`           | Chat, automations, skills, approvals, and runs. |

Install the packages, import their factories, register them in the project's `extensions` array, and include their published `styles.css` files alongside Studio's styles. Keep dependencies and configuration aligned; installing a package alone does not activate it.

## Extension guides

Build a [custom app](/docs/extensions/create-an-extension), replace a [form field](/docs/extensions/custom-fields), customize a [preview](/docs/extensions/custom-previews), or adjust [navigation and theming](/docs/extensions/navigation-and-theming).

Contributions are resolved in the selected project's extension configuration, including nested extensions. Give each Studio extension a distinct machine-readable `id`; its optional `name` is a human-readable label. Apps retain their routing `name` and display `title`. Test contribution order when overriding the same component. UI visibility is not a substitute for server authorization.

The public `StudioExtension` contract requires `id` and `contributes`, and optionally accepts `name` and nested `extensions`. `StudioContributions` describes the contribution points. Composition-only extensions use `contributes: {}`. `defineExtension` preserves the specific types of a custom extension:

```tsx
import { defineConfig, defineExtension } from '@flexkit/studio';
import { Desk } from '@flexkit/desk';
import { AssetManager } from '@flexkit/asset-manager';
import { Explorer } from '@flexkit/explorer';
import { AI } from '@flexkit/ai';

export default defineConfig([
  {
    projectId: 'YOUR_PROJECT_ID',
    basePath: '/studio',
    schema: [],
    extensions: [
      Desk(),
      AssetManager(),
      Explorer(),
      AI(),
      defineExtension({
        id: 'acme.order-management',
        name: 'Order Management',
        contributes: {
          apps: [{ name: 'orders', title: 'Orders', component: <p>Review orders and track fulfillment.</p> }],
        },
      }),
    ],
  },
]);
```


---

[View full sitemap](/docs/sitemap.md)
