Skip to main content
Crosslink ships the desktop pairing experience. You mount it; you do not build it.
That is a complete integration. The card renders the QR, the nine-digit code and the countdown, mints a fresh session when the current one is close to expiring, mints another when a device redeems one, exposes the connection-mode settings, lists paired devices and revokes them, and shows the Crosslink mark. It also takes your application’s name, icon and colours from the host: the application block you pass to createCrosslinkServer travels with each pairing session, so the desktop page states none of it a second time. With no source option, the card uses the Crosslink system endpoints your host already exposes (/__crosslink/*). You do not write those routes. The old source: true spelling remains a compatibility alias, but omission is the canonical path.
Migration for older controlled integrations: omission now means the canonical HTTP source. Add source: false before continuing to drive the card with update(). Existing source: true, custom base-path strings, and custom PairingSource objects keep their behavior.

Where the branding comes from

Configure it once, on the host:
The same block drives the pairing card, the installable manifest, the mobile onboarding, the offline screen and the revoked screen. Nothing is repeated in the page.

Overriding it in the page

Only when the pairing screen should differ from your host metadata. Options win over what the host reports, field by field — set the name and the colours still come from the host.
There is no option that replaces the card’s markup, swaps its renderer, or removes the Crosslink mark. That is deliberate: the value of a recognisable pairing screen is that it is the same screen in every Crosslink application. The card carries the wordmark and no attribution footer, divider, link or reserved footer space. The Crosslink attribution footer belongs to the authorized mobile app shell — see Mobile bootstrap.

While a setting is applied

Changing the connection mode is a round trip to the host: it re-derives which routes to advertise and may ask your router for a port mapping, which routinely takes seconds. The settings popover shows a spinner and refuses further changes until a session minted under the new mode is on screen, so a slow mode change never looks like a click that did nothing.

Framework bindings

The card is plain DOM, so it works anywhere. React gets a thin wrapper that mounts the same implementation:
Vue, Svelte and plain pages call createPairingCard directly. There is no framework-specific reimplementation to keep in step.

Reacting to pairing

The card drives itself, so callbacks are for your UI, not for its behaviour.
onError fires after the card has already rendered the failure and scheduled a retry. You do not need to build recovery on top of it.

When your host is not reachable over HTTP

An Electron renderer behind a preload bridge, or any page that cannot call the host directly, supplies its own source:
The source decides where a pairing session comes from. It never decides what the pairing screen looks like — both paths render the identical card.

Controlled mode (advanced)

Set source: false and the card renders only what you pass to update(). This explicit opt-out exists for hosts that already own a pairing loop; it is not the normal integration path, and choosing it means writing the loop the card would otherwise run for you.