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

# Mount API

> Complete reference for mountFlowDropApp(), mountWorkflowEditor(), and mountPlayground() — all options, return values, and lifecycle.

The mount API lets you embed FlowDrop into any HTML container, regardless of framework.

## `mountFlowDropApp()`

Mounts the full FlowDrop application (sidebar, editor, config panel) into a container.

```typescript theme={null}
import { mountFlowDropApp } from '@flowdrop/flowdrop/editor';

const app = await mountFlowDropApp(container: HTMLElement, options: FlowDropMountOptions);
```

### Options

```typescript theme={null}
interface FlowDropMountOptions {
  // Data
  /** Initial workflow to load */
  workflow?: Workflow;
  /** Available node types (overrides API fetch) */
  nodes?: NodeMetadata[];

  // API
  /** REST API endpoint configuration */
  endpointConfig?: EndpointConfig;
  /** Port data type configuration (overrides API fetch) */
  portConfig?: PortConfig;
  /** Category definitions (overrides API fetch) */
  categories?: CategoryDefinition[];
  /** Authentication provider for API requests */
  authProvider?: AuthProvider;

  // Event handlers — the grouped lifecycle events bag
  eventHandlers?: FlowDropEventHandlers;

  // Features
  features?: FlowDropFeatures;

  // UI options
  /** Show the top navbar @default true */
  showNavbar?: boolean;
  /** Disable the node sidebar */
  disableSidebar?: boolean;
  /** Editor interaction mode. @default 'edit' */
  mode?: 'edit' | 'readonly' | 'locked';
  /** Editor height (CSS value or number) */
  height?: string | number;
  /** Editor width (CSS value or number) */
  width?: string | number;

  // Navbar customization
  /** Custom navbar title */
  navbarTitle?: string;
  /** Custom navbar action buttons */
  navbarActions?: NavbarAction[];
  /** Show settings gear icon in navbar */
  showSettings?: boolean;
  /** Show the "Connected" status indicator in the navbar @default true */
  showStatus?: boolean;

  // Pipeline mode
  /** Pipeline ID for execution status display */
  pipelineId?: string;

  // Theme
  /** Visual theme — named built-in ('default' | 'minimal') or a custom theme object */
  theme?: FlowDropTheme | FlowDropThemeName;

  // Instance
  /** Identifier for this instance. @default 'default' (auto-generated for extra mounts) */
  instanceId?: string;

  // Settings
  /** Initial settings overrides (theme, behavior, editor, ui, api) */
  settings?: PartialSettings;
  /** Custom localStorage key for draft auto-save */
  draftStorageKey?: string;
  /** Where workflow drafts are persisted: 'local' (default), 'session', or a custom adapter */
  draftStorage?: DraftStorageOption;
  /** Which settings tabs to show in the modal (defaults to all) */
  settingsCategories?: SettingsCategory[];
  /** Show the "Sync to Cloud" button in the settings modal */
  showSettingsSyncButton?: boolean;
  /** Show the reset buttons in the settings modal */
  showSettingsResetButton?: boolean;

  // Format adapters
  /** Custom workflow format adapters */
  formatAdapters?: WorkflowFormatAdapter[];
}
```

The `mode` option controls canvas interaction: `'edit'` (the default) allows editing; `'readonly'` and `'locked'` disable all canvas interaction.

<Accordion title="How instance ids and draft keys work">
  When you omit `instanceId`, the first mount on the page becomes the default
  instance (id `default`); additional mounts get auto-generated ids (`fd-1`,
  `fd-2`, …). Every instance scopes its draft and panel storage keys by id
  (`flowdrop:draft:<id>:…`).

  Pass an explicit `instanceId` whenever you mount more than one editor with
  drafts enabled, so the keys stay stable across page loads.
</Accordion>

### Feature flags (`FlowDropFeatures`)

```typescript theme={null}
interface FlowDropFeatures {
  /** Auto-save the current workflow to localStorage as a draft. @default true */
  autoSaveDraft?: boolean;

  /** How often to auto-save the draft, in milliseconds. @default 30000 */
  autoSaveDraftInterval?: number;

  /** Show toast notifications for save success, failure, and API errors.
   * Disable if you want to handle notifications yourself via event handlers. @default true */
  showToasts?: boolean;
}
```

See [Auto-Save & Drafts](/recipes/auto-save-and-drafts) for practical examples.

See [Core Types](/reference/types) for `FlowDropEventHandlers` and `FlowDropFeatures`.

### Return value

```typescript theme={null}
interface MountedFlowDropApp {
  /** This mount's state container — drive the editor programmatically. */
  instance: FlowDropInstance;

  /** Destroy the editor and clean up resources */
  destroy(): void;

  /** Check if there are unsaved changes */
  isDirty(): boolean;

  /** Mark the workflow as saved (clears dirty state) */
  markAsSaved(): void;

  /** Get the current workflow data */
  getWorkflow(): Workflow | null;

  /** Trigger save operation */
  save(): Promise<void>;

  /** Trigger export (downloads JSON file) */
  export(): void;

  /** Clear all workflow drafts from draft storage. Returns the number of entries removed. */
  clearAllDrafts(): number;
}
```

`instance` is the state container — workflow, history, playground, interrupts,
categories, and the rest. Call into it to drive the editor programmatically,
e.g. `app.instance.workflow.addNode(...)` or `app.instance.history.undo()`.

<Note>
  **Call `clearAllDrafts()` on logout.**

  Otherwise drafts persist across user sessions on shared devices. It clears the
  configured draft storage (`localStorage` unless changed via the `draftStorage`
  option).
</Note>

## `mountWorkflowEditor()`

Mounts just the editor canvas — no navbar, no sidebar. Useful for embedding a minimal editor.

```typescript theme={null}
import { mountWorkflowEditor } from '@flowdrop/flowdrop/editor';

const editor = await mountWorkflowEditor(container, {
  workflow: myWorkflow,
  endpointConfig: createEndpointConfig('/api/flowdrop'),
  portConfig: myPortConfig, // optional, overrides API
  categories: myCategories, // optional, overrides API
  instanceId: 'editor-b' // optional — scope to a named instance for multi-editor pages
});
```

Returns the same `MountedFlowDropApp` interface as `mountFlowDropApp()`. `instanceId` follows the same default-instance semantics as `mountFlowDropApp()` above.

## `mountPlayground()`

Mounts the interactive playground for workflow testing.

```typescript theme={null}
import { mountPlayground } from '@flowdrop/flowdrop/playground';

const playground = await mountPlayground(container, {
  workflowId: 'my-workflow-id',
  endpointConfig: createEndpointConfig('/api/flowdrop'),
  mode: 'standalone', // 'standalone' | 'embedded' | 'modal'
  config: {
    pollingInterval: 1500,
    shouldStopPolling: (status) => ['completed', 'failed'].includes(status),
    isTerminalStatus: (status) => ['completed', 'failed'].includes(status)
  },
  onSessionStatusChange: (newStatus, previousStatus) => {
    console.log(`${previousStatus} -> ${newStatus}`);
  },
  onClose: () => console.log('Playground closed'), // required for embedded/modal
  height: '600px',
  width: '100%',
  initialSessionId: 'resume-session-id', // optional
  instanceId: 'playground-b' // optional — scope to a named instance
});
```

`instanceId` follows the same default-instance semantics as `mountFlowDropApp()`.

<Note>
  **Live polling is page-global.**

  Playground state (sessions, messages, interrupts) is isolated per instance, but
  only one playground can actively poll at a time. Drive a non-polling playground
  via `pushMessages()` instead.
</Note>

### Playground return value

```typescript theme={null}
interface MountedPlayground {
  /** Destroy and clean up */
  destroy(): void;
  /** Get the current session */
  getCurrentSession(): PlaygroundSession | null;
  /** Get all sessions */
  getSessions(): PlaygroundSession[];
  /** Get message count in current session */
  getMessageCount(): number;
  /** Check if currently executing */
  isExecuting(): boolean;
  /** Stop polling for messages */
  stopPolling(): void;
  /** Restart polling */
  startPolling(): void;
  /** Push poll response data */
  pushMessages(response: PlaygroundMessagesApiResponse): void;
  /** Reset playground state */
  reset(): void;
}
```

## `unmountFlowDropApp()` / `unmountPlayground()`

Clean up a mounted instance. Equivalent to calling `.destroy()` on the returned object.

```typescript theme={null}
import { unmountFlowDropApp } from '@flowdrop/flowdrop/editor';

unmountFlowDropApp(container);
```

## Lifecycle

1. **Mount** — Call `mountFlowDropApp()` with a container element
2. **Interact** — Use the returned API to control the editor programmatically
3. **Destroy** — Call `.destroy()` or the unmount function to clean up

Registration of custom nodes and fields can happen **before or after** mounting. The node and field registries are instance-scoped — resolve them via `getInstance()` inside the component tree, or the mount handle's `.instance` outside it.

<Accordion title="Why registration works after mount">
  Each registry tracks a version counter that invalidates dependent reactive
  reads. When you register a node or field after mount, that counter bumps and
  the editor re-resolves, so late registrations take effect.
</Accordion>
