> ## Documentation Index
> Fetch the complete documentation index at: https://docs.henrylabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Install the Henry JS SDK, embed a checkout widget, and handle events in under five minutes.

<Tip>
  This guide walks through the most common setup: embedding the Checkout Widget on a product page. If you're collecting card details for a custom payment flow, jump to the [Card Element
  guide](/v1/sdk/client/elements/card-element) instead.
</Tip>

## Prerequisites

* A Widget ID from the [Henry Dashboard](https://app.henrylabs.ai/dashboard/settings/app/developer)
* A product URL (any publicly accessible product page)

***

## Setup

<Steps>
  <Step title="Install the SDK">
    <CodeGroup>
      ```bash npm theme={null}
      npm install @henrylabs/js
      ```

      ```bash bun theme={null}
      bun add @henrylabs/js
      ```

      ```bash pnpm theme={null}
      pnpm add @henrylabs/js
      ```

      ```bash yarn theme={null}
      yarn add @henrylabs/js
      ```
    </CodeGroup>

    Or load via CDN - no build step required:

    ```html theme={null}
    <script src="https://cdn.jsdelivr.net/npm/@henrylabs/js"></script>
    ```

    <Info>When loaded via CDN, use `window.Henry` instead of the ES module import.</Info>
  </Step>

  <Step title="Add a container element">
    ```html theme={null}
    <div id='checkout-container'></div>
    ```
  </Step>

  <Step title="Mount the Checkout Widget">
    ```js theme={null}
    import Henry from "@henrylabs/js";

    const el = Henry.createCheckoutElement("#checkout-container", {
      widgetId: "widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
      items: [
        {
          link: "https://www.nike.com/t/some-product/ABC-123",
          quantity: 1,
          variant: { size: "10", color: "White" },
        },
      ],
    });
    ```
  </Step>
</Steps>

***

## End-to-end walkthrough

### Step 1 - Mount the widget

`createCheckoutElement` takes a CSS selector (or DOM element) and an options object. Henry renders the widget inside your container immediately.

```js theme={null}
import Henry from '@henrylabs/js';

const el = Henry.createCheckoutElement('#checkout-container', {
	widgetId: 'widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
	items: [
		{
			link: 'https://www.nike.com/t/air-max-270/AH8050-002',
			quantity: 1,
			variant: { size: '10', color: 'Black' },
		},
	],
	display: {
		size: 'compact', // "full" | "comfortable" | "compact" | "bubble" | "direct"
		theme: 'system', // "light" | "dark" | "system"
	},
});
```

<Tip>See [Checkout Widget](/v1/sdk/client/widgets/checkout) for the full list of display sizes and what each looks like.</Tip>

***

### Step 2 - Listen for checkout events

Use `.on()` to respond when the buyer completes or closes checkout:

```js theme={null}
el.on('checkout-complete', ({ status, order }) => {
	console.log('Checkout finished:', status);
	// show a confirmation UI, redirect, etc.
});

el.on('checkout-closed', ({ source }) => {
	// source is "user" (buyer closed) or "system" (programmatic close)
	console.log('Checkout closed by:', source);
});
```

***

### Step 3 - Clean up

Call `.destroy()` when the widget is no longer needed to unmount it and remove all listeners:

```js theme={null}
el.destroy();
```

***

### React

Use a `ref` guard to prevent double-mounting in React Strict Mode:

```tsx theme={null}
import { useEffect, useRef } from 'react';
import Henry from '@henrylabs/js';

function ProductPage() {
	const initialized = useRef(false);

	useEffect(() => {
		if (initialized.current) return;
		initialized.current = true;

		const el = Henry.createCheckoutElement('#checkout-container', {
			widgetId: 'widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
			items: [{ link: 'https://www.nike.com/t/air-max-270/AH8050-002', quantity: 1 }],
			display: { size: 'compact', theme: 'dark' },
		});

		el.on('checkout-complete', ({ status, order }) => {
			console.log('Done:', status, order);
		});

		return () => el.destroy();
	}, []);

	return <div id='checkout-container' />;
}
```

***

## Next steps

<CardGroup cols={2}>
  <Card title="Checkout Widget" icon="cart-shopping" href="/v1/sdk/client/widgets/checkout">
    All display modes, settings, and events for the checkout widget
  </Card>

  <Card title="Card Element" icon="credit-card" href="/v1/sdk/client/elements/card-element">
    Embed a secure card input for custom payment flows
  </Card>
</CardGroup>
