Skip to main content
Use the <stackone-hub> custom element from @stackone/hub directly in JSX. This is the right choice if you can’t add another copy of React to your bundle, or if you want the same code path as your non-React surfaces.
If you’re starting fresh in React, the <StackOneHub> component is usually a better fit — it integrates with your React tree and lets you pass callbacks as props. Reach for the web component when you need the framework-agnostic build.
1

Install the package

npm install @stackone/hub
2

Register the element at app entry

The import is side-effecting — it registers <stackone-hub> on customElements.
// src/main.tsx
import '@stackone/hub/webcomponent';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const root = document.getElementById('root');
if (!root) {
  throw new Error('#root element not found');
}
createRoot(root).render(
  <StrictMode>
    <App />
  </StrictMode>,
);
3

Type the element for JSX

Tell TypeScript that <stackone-hub> is a valid JSX tag:
declare global {
  // biome-ignore lint/style/noNamespace: JSX intrinsic-element augmentation requires namespace syntax.
  namespace JSX {
    interface IntrinsicElements {
      'stackone-hub': React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          token?: string;
          mode?: string;
          'base-url'?: string;
          'app-url'?: string;
          'account-id'?: string;
          height?: string;
          theme?: string;
          'show-footer-links'?: boolean | string;
          'on-close-label'?: string;
        },
        HTMLElement
      >;
    }
  }
}
4

Get a session token from your backend

5

Add the element and listen for events

React 19 passes unknown props through as attributes, but events still need to be wired with addEventListener via a ref — React doesn’t synthesize custom DOM events.
import { useEffect, useRef, useState } from 'react';

export default function App() {
  const [token, setToken] = useState('');
  const hubRef = useRef<HTMLElement>(null);

  useEffect(() => {
    retrieveConnectSessionToken().then(setToken);
  }, []);

  useEffect(() => {
    const el = hubRef.current;
    if (!el) return;
    const onSuccess = (event: Event) => {
      const detail = (event as CustomEvent).detail;
      console.log('Connected:', detail.id, detail.provider);
    };
    const onClose = () => console.log('Closed');
    el.addEventListener('success', onSuccess);
    el.addEventListener('close', onClose);
    return () => {
      el.removeEventListener('success', onSuccess);
      el.removeEventListener('close', onClose);
    };
  }, []);

  return (
    <stackone-hub
      ref={hubRef}
      token={token || undefined}
      mode="integration-picker"
      height="600px"
    />
  );
}

Attribute reference

All scalar StackOneHub props map to kebab-case HTML attributes — see the vanilla guide for the full table.

Events

Native DOM CustomEvents on the element:
Eventevent.detail
success{ id: string; provider: string }
closeundefined
React’s onSuccess={...} JSX shorthand does not fire on native DOM CustomEvents — React doesn’t synthesize custom DOM events. Subscribe with addEventListener via a ref instead.

Next steps

Backend setup

Generate session tokens from your backend.

React component path

Use <StackOneHub> instead, with native React props.