@brandssl/connect
v1.0.0
Published
Let your customers connect their own domain. Loader and React bindings for the BrandSSL Connect SDK.
Maintainers
Readme
@brandssl/connect
Let your customers connect their own domain. This package loads the BrandSSL Connect SDK and gives you typed bindings, including a React hook that manages the flow state for you.
npm install @brandssl/connectReact
import { useConnect } from "@brandssl/connect/react";
const records = [
{ type: "CNAME", host: "www", value: "cname.yourservice.com" },
];
export function DomainSetup({ domain }) {
const { ready, isOpen, result, error, open } = useConnect();
const handleConnect = async () => {
const res = await fetch("/connect-session", { method: "POST" });
const { token } = await res.json();
open({ token, domain, records });
};
if (result) {
return <p className="success">{result.domain} is {result.status}.</p>;
}
return (
<div>
<button onClick={handleConnect} disabled={!ready || isOpen}>
{isOpen ? "Connecting..." : "Connect your domain"}
</button>
{error && <p role="alert">{error.error}</p>}
</div>
);
}The hook handles what you would otherwise wire by hand:
ready- true once the SDK script has loaded; gate your button on it.isOpen- true while the Connect window is up.result/error- the latest outcome, reset on eachopen().open(options)- your ownonSuccess/onError/onClosecallbacks still fire if you pass them; state updates happen either way.check(options)- preflight a domain before opening anything.close()- close the window programmatically.
Check the domain before opening
const { check, open } = useConnect();
const result = await check({ token, domain, records });
if (result.setup === "automatic") {
open({ token, domain, records });
} else {
// render your own DNS guide, or open() anyway for guided manual steps
}Plain JavaScript
import { open, check, close } from "@brandssl/connect";
await open({ token, domain, records, onSuccess: console.log });open/check load the SDK on first use. To control loading yourself, use
loadConnect().
TypeScript
Every option and result is typed:
import {
open,
check,
type OpenOptions,
type CheckResult,
type ConnectSuccess,
} from "@brandssl/connect";Window events
The SDK mirrors its callbacks as window events, useful for analytics or for
listeners that don't have the open() call:
| Event | detail |
|---|---|
| brandssl-connect:success | { domain, status } where status is connected or manual |
| brandssl-connect:failed | { domain, status: "failed", error } |
| brandssl-connect:close | { completed } |
useEffect(() => {
const onSuccess = (e) => analytics.track("domain_connected", e.detail);
window.addEventListener("brandssl-connect:success", onSuccess);
return () => window.removeEventListener("brandssl-connect:success", onSuccess);
}, []);WindowEventMap entries are included, so the listeners are fully typed in
TypeScript. Callbacks remain the primary interface; events are a mirror, not a
replacement.
Focus locks (Radix, Reach UI, react-focus-lock)
The Connect window is a full viewport iframe. If you open it from inside a dialog that enforces a focus trap, disable the trap while Connect is open:
const { isOpen, open } = useConnect();
<FocusLock disabled={isOpen}>
<button onClick={() => open({ token, domain, records })}>Setup domain</button>
</FocusLock>Notes
- The session
tokencomes from your server:POST /connect/v1/sessionswith your secret key. Fetch the token inside the click handler, not at mount; tokens last 60 minutes. - Calling
open()while a flow is already open closes the first flow; there is only ever one Connect window. - Server side rendering is safe:
loadConnect()resolvesnullon the server and the hook'sreadystaysfalseuntil the browser loads the SDK.
