---
title: Configuration
description:
  Every Feeblo.init option, the three widget modes, launcher placement, and how each
  prop behaves in React.
---

`Feeblo.init` takes an organization ID plus options. Options decide what the widget
shows, where it sits, and how loud it is about its own internals. Pass them positionally
or as one config object:

```ts
// Positional form
const widget = Feeblo.init("org_123", { mode: "hub", debug: true });

// Config-object form. Same result, easier to read when many options are set.
const widget = Feeblo.init({
  organizationId: "org_123",
  mode: "hub",
  modules: ["feedback", "updates"],
});
```

The org ID comes from **Settings → Widget → Installation**. Init throws an
`EmbedError` with code `INVALID_ORG` when it is missing or empty.

## Options reference

| Option            | Type                                | Default                  | What it does                                                        |
| ----------------- | ----------------------------------- | ------------------------ | ------------------------------------------------------------------- |
| `organizationId`  | `string`                            | required                 | Your Feeblo organization                                            |
| `mode`            | `"feedback" \| "updates" \| "hub"`  | `"feedback"`             | Which widget loads. See [Modes](#modes)                             |
| `modules`         | `("feedback" \| "updates")[]`       | `["feedback", "updates"]`| Hub only. Order decides which module shows first                    |
| `placement`       | `"bottom-left" \| "bottom-right"`   | none                     | Adds the built-in launcher. Omit it to control opening yourself     |
| `theme`           | `string`                            | none                     | Forwarded to the widget iframe                                      |
| `locale`          | `string`                            | `"en"`                   | BCP 47 tag; the widget uses the language subtag                     |
| `defaultBoard`    | `string`                            | none                     | Board the feedback module opens on                                  |
| `debug`           | `boolean`                           | `false`                  | Logs the init banner, trigger bindings, and events to the console   |
| `baseUrl`         | `string`                            | auto                     | Widget host override for self-hosting                               |
| `root`            | `HTMLElement`                       | `document.body`          | Container the iframe and launcher mount into                        |
| `containerStyles` | `Partial<CSSStyleDeclaration>`      | none                     | Merged into the container element's style                           |
| `user`            | `UserIdentity`                      | none                     | Identify a user at init. See [Identifying users](/developers/identity) |
| `onClose`         | `() => void`                        | none                     | Runs when the widget closes                                         |
| `onError`         | `(error: EmbedError) => void`       | none                     | Runs on embed errors                                                |
| `onHeightChange`  | `(height: number) => void`          | none                     | Runs whenever the iframe reports a new height                       |

Invalid combinations throw an `EmbedError` with code `INVALID_CONFIG`: an unknown mode,
an unknown placement, `modules` outside hub mode, an empty module list, duplicate
modules, or a module other than `feedback`/`updates`.

## Modes

Three modes exist. Each one is a different entry page into your feedback:

**feedback**

The submit-a-post form. This is the default, so `Feeblo.init("org_123")` gives you the
feedback widget with nothing else configured.

**updates**

A card-based product updates panel:

```ts
const widget = Feeblo.init("org_123", { mode: "updates" });
```

**hub**

Several modules behind one launcher. The array order decides which module opens first:

```ts
const widget = Feeblo.init("org_123", {
  mode: "hub",
  modules: ["feedback", "updates"],
});

widget.openModule("updates"); // switch without closing
```

Hub defaults to `["feedback", "updates"]` when you omit `modules`. Board selection only
applies while the feedback module is the active one.

## Placement

Set `placement` and the SDK renders a launcher button pinned 20px from the corner you
chose:

```ts
const widget = Feeblo.init("org_123", { placement: "bottom-right" });
```

Omit `placement` and no launcher mounts. Open the widget yourself through trigger
attributes or `widget.open()` instead. See
[Triggers and events](/developers/triggers-and-events).

## Debug logging

```ts
const widget = Feeblo.init("org_123", { debug: true });
```

With `debug: true` the SDK prints a version banner with your org ID and base URL, plus
trigger bindings and event traffic as they happen. Turn it off before shipping;
the flag exists for setup problems.

## React

`FeebloProvider` accepts every option above as a prop, plus `children`:

```tsx
import { FeebloProvider } from "@feeblo/sdk-react";

<FeebloProvider organizationId="org_123" mode="hub" debug>
  <App />
</FeebloProvider>
```

Prop change behavior differs by kind:

- **Config props** (`organizationId`, `mode`, `modules`, `placement`, `theme`,
  `defaultBoard`, `locale`, `baseUrl`, `containerStyles`, `debug`) tear down and remount
  the widget when they change. Treat them as configuration, not state.
- **`user`** never remounts anything. Changes call `identify` on the live widget, and the
  last identity replays automatically if a config change recreates the widget.
  Setting `user` back to `undefined` does not sign anyone out.
- **Callbacks** (`onClose`, `onError`, `onHeightChange`) are read through refs. Inline
  closures are safe: they never trigger a re-init, and the widget always invokes the
  newest one you passed.

Only unmounting `<FeebloProvider>` discards the remembered identity.

## Next steps

<CardGroup cols={2}>
  <Card title="Triggers and events" href="/developers/triggers-and-events">
    Open the widget from your own buttons and listen to what happens inside it.
  </Card>
  <Card title="Identifying users" href="/developers/identity">
    Attach a verified user to every submission.
  </Card>
</CardGroup>
