# Implementation

## Step 1 - Authorize your project

#### The Widget is a Browser-only SDK

#### For testing

Use a tool such as ngrok (<https://ngrok.com/docs/http/>) to get a unique URL for your web app running locally on your device and add it to your allowlist. \
\
See: [allowlisting via the admin dashboard](/developers/sdk/classes-and-functions/authentication/allow-listing-a-domain.md).

#### For production

Add your production domain by [allowlisting it via the admin dashboard](/developers/sdk/classes-and-functions/authentication/allow-listing-a-domain.md)

## Step 2 - Add the package

Install the package in your project

{% code overflow="wrap" %}

```bash
npm install @chainvine/widget
```

{% endcode %}

or

{% code overflow="wrap" %}

```bash
yarn add @chainvine/widget
```

{% endcode %}

## Step 3 - Add the Widget Component

Here is an example using a React component called "App".

### React

```typescript
import React from "react";
import "./App.css";
import { ChainvineWidget } from "@chainvine/widget";

const App = () => {
  const [isOpen, setIsOpen] = React.useState<boolean>(false);

  const openWidget = () => {
    setIsOpen(true);
  }
  const closeWidget = () => {
    setIsOpen(false);
  }

  return (
   <div>
     <button
        type={'submit'}
        onClick={() => {
          openWidget()
        }}>
        Open me
      </button>
      <ChainvineWidget
        isOpen={isOpen}
        userIdentifier={walletAddress}
        identifierType={'wallet'}
        campaignId={campaignId}
        onToggle={() => closeWidget()} 
      />
    </div>
  );
}
```

### NextJS/SSR

For server-side rendered projects, please ensure to wrap the widget component inside a client-side rendered component. For NextJS, a simple way to do this is by using the `'use-client'` tag at the top of your file:

```typescript
'use-client' //<--- IMPORTANT
import React from "react";
import "./App.css";
import { ChainvineWidget } from "@chainvine/widget";

export const MyClientSideWidgetComponent = () => {
  const [isOpen, setIsOpen] = React.useState<boolean>(false);

  const openWidget = () => {
    setIsOpen(true);
  }
  const closeWidget = () => {
    setIsOpen(false);
  }

  return (
    <div>
      <button
        type={'submit'}
        onClick={() => {
          openWidget()
        }}>
        Open me
      </button>
      <ChainvineWidget
        isOpen={isOpen}
        userIdentifier={walletAddress}
        identifierType={'wallet'}
        campaignId={campaignId}
        onToggle={() => closeWidget()} 
      />
    </div>
  );
}
```

Note: if your flow does not include a wallet connect step, we also support an identifier type of 'email' and 'externalId' where the externalId can be any unique user identifier within your system.

### Guidances

* When in desktop screen sizes: you must pass in the component around which the Widget will be positioned on the screen as a child component.&#x20;
  * In this example, we use a button, however, you can use any component that suits your needs, as long as it is able to update *isOpen* state hook in the example.
  * This example uses a useState hook, however you can very well use other state hooks such as Redux, or other  context providers.

## Step 4 - Testing&#x20;

### How to test

The ChainVine widget uses the ChainVine SDK under the hood. The *clientConfig* prop of the Widget is an extension of the ChainVine SDK's ***ClientConfig*** constructor options.

Refer to the [ChainVine SDK documentation](/developers/sdk/configuring-the-client.md) for how to setup testMode and ClientConfig options.&#x20;

## That's it!

If you have any questions, or run into any issues, please do not hesitate to reach out on [Telegram](https://t.me/chainvinehq)!

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.chainvine.xyz/developers/embedded-widget/implementation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
