Skip to content

Components ​

The Quickstart uses the simplest entry point: your own chip, linked to a route on your server that sends the user to Configure's page. Use the components below when you want Configure's page inside yours instead. Configure serves them all, and all of them run in production. Two scripts carry them: https://configure.dev/js/configure.js gives you the Configure.* functions, and https://configure.dev/components/configure-components.global.js defines the raw elements. Include each once per page.

publishableKey is your pk_ key, safe in the browser, and agent is your agent handle. Both come from npx configure setup --users. displayName is what the user reads; agent is the identity every approval and token is bound to.

Composer button ​

The entry point for a chat. It sits next to the image and file attachments as a + menu, with a Personalization row that opens Configure's hosted flow inline. Pass linkEl so the flow mounts in a dismissible panel across the assistant lane instead of inside the composer row.

html
<script src="https://configure.dev/js/configure.js"></script>

<div id="configure-entry"></div>
<div id="configure-link-host"></div>

<script>
  Configure.personalizationButton({
    el: "#configure-entry",
    linkEl: "#configure-link-host",
    publishableKey: "pk_...",
    agent: "your-agent",
    displayName: "Your App",
    theme: "light",                 // or "dark"; omit it and the script warns and follows the system
    onImage: () => openImagePicker(),
    onFile: () => openFilePicker(),
  });
</script>

Let the link host span the assistant message lane. Do not cap it at 420px; the flow needs the width.

Your own button ​

Most products already have a button style, so the entry point is your own control. It links to the route that sends the user to Configure's page, and Configure brings them back to your return route. This is the Quickstart pattern, steps 2 through 5.

Smry's home page with the chip circled in red: it reads Connect, followed by the Claude, ChatGPT, Gemini, and Grok marks

A chip under the composer on Smry's home page.
html
<a class="chip" href="/configure/start">Connect</a>

The route mints the link with a returnUrl and redirects. profileFor is the handle from the Quickstart, and RETURN_URL is your return route's https address, a constant:

ts
const RETURN_URL = "https://yourapp.com/configure/return";

app.get("/configure/start", async (req, res) => {
  const connect = await profileFor(req.user.id).connect({ returnUrl: RETURN_URL });
  res.redirect(connect.connect_url);   // Configure's page, then back to RETURN_URL
});

Configure brings the user back to your return route: Quickstart, step 5.

Integration button ​

For a settings or integrations surface, the raw element renders a connect or manage control that opens Configure's hosted flow itself.

html
<script src="https://configure.dev/js/configure.js"></script>
<script src="https://configure.dev/components/configure-components.global.js"></script>

<configure-personalization-button
  variant="integration"
  external-id="user_123"
></configure-personalization-button>

variant is menu, the composer button above as a raw element, or integration. With manual the element announces its events and never opens the flow, which is how the demos on this page run.

When you want the flow on its own, mount it and take the token from the event. This is the same grant the composer button and the integration button run; here your page owns where it renders.

html
<script src="https://configure.dev/js/configure.js"></script>
<div id="configure-link"></div>

<script>
  Configure.link({
    el: "#configure-link",
    publishableKey: "pk_...",
    agent: "your-agent",
    displayName: "Your App",
    theme: "light",
    onEvent: (event) => {
      if (event.type === "configure:linked") {
        // event.payload = { token, userId, tokenUse }
        sendTokenToYourBackend(event.payload.token);
      }
    },
  });
</script>

Configure.link() returns a frame handle, not the token. The token arrives in configure:linked, through onEvent or as a DOM CustomEvent on the mount element. Send it to your server and use it there with configure.profile({ token }).

Connected ​

The composer button flips its own state when it sees the link complete on the page. Across reloads, and for your own button, render the connected state from what your server already knows: the context your daily refresh stored.

ts
// The refresh in Quickstart step 6 stores { text, refreshedAt }. text is null until the user connects.
const stored = await store.get(user.id);
const label = stored?.text ? "Connected" : "Connect";

Render from what Configure told you, stored and refreshed on the daily read. That keeps page loads off the network. Never set a "connected" flag from your own events.

Approval card ​

For the two tools that change the outside world, sending an email and creating an event, the bundle ships a card that asks the user first. It shows the tool and its parameters, times out to Deny, and answers with one event.

html
<configure-tool-approval
  action-id="call_123"
  tool="configure_email_send"
  timeout-seconds="60"
></configure-tool-approval>
<script>
  const card = document.querySelector("configure-tool-approval");
  card.params = { to: "sam@example.com", subject: "Intro" };        // a property, not an attribute
  card.addEventListener("configure:tool-approve", (e) => runTool(e.detail.actionId));
  card.addEventListener("configure:tool-deny", (e) => skipTool(e.detail.actionId));
</script>

configure:tool-always-allow fires when the user chooses to stop being asked for that tool; remembering that choice is yours.

Attributes ​

On the raw <configure-personalization-button>:

AttributeDefaultWhat it does
variantmenumenu or integration
external-idYour user id, so the connection lands on the profile your server reads
connectorsWhich apps the flow offers, comma separated
personalization-labelThe text of the Personalization row
placeholderPlaceholder text in the composer slot
manualfalseAnnounce events only; never open the flow
hide-images, hide-filesfalseRemove the image or file rows from the + menu
image-label, file-labelText of the image and file rows
max-visibleHow many recent items the menu lists
show-actions, show-settingsShow the actions row and the settings row

Events the element announces: configure:personalization-open and configure:personalization-toggle as the flow opens and closes, configure:personalization-menu-toggle for the + menu, configure:linked when the link completes, configure:image-select and configure:file-select for the attachment rows, and configure:settings-press.

The buttons are real buttons: keyboard reachable, with a visible focus ring, and still on the page at 375px wide.

Personalization infrastructure for agents