> For the complete documentation index, see [llms.txt](https://docs.bitte.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitte.ai/agents/widget-component.md).

# Widget Component

#### Introduction <a href="#introduction" id="introduction"></a>

The **BitteWidgetChat** component is a React component that enables AI-powered chat interactions in your application. It supports both **NEAR Protocol** and **EVM blockchain** interactions through wallet integrations, allowing users to interact with smart contracts and perform transactions directly through the chat interface.

> 🔑 Before you begin, make sure you have:
>
> * A **Bitte API Key** - Get your beta `BITTE_API_KEY` [here ](https://key.bitte.ai)

### Quick Start (<10min)

1. Install package
2. Add the Chat Component
3. Setup API Route
4. Wallet Connection\ <br>

   <figure><img src="https://74933262-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FB52AZELB8jl58pzYsH6O%2Fuploads%2FJMzqSJVW2cPH070LLWbT%2FScreenshot%202025-05-15%20at%2016.49.18.png?alt=media&amp;token=a7413258-75f6-4d74-9a24-3319e57f77ec" alt=""><figcaption></figcaption></figure>

### 2. Install Package

```
pnpm install @bitte-ai/chat
```

###

### 2. Add the Widget Component

Import and use WidgetChat in your react app and select the agent that you would like to use, browse the available agents and their respective ids on the [registry](https://www.bitte.ai/registry)\
The `apiUrl` corresponds to a proxy to not expose your api key on the client.\
The `historyApiUrl` is needed to keep context and state of the chat.\
\
from `@bitte-ai/chat@0.19.0` onwards we have now markdown rendering, you can keep rendering plaintext, or if you wanna markdown support just add `format="markdown"` to BitteWidgetChat Component

```jsx

import { BitteWidgetChat } from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';

<BitteWidgetChat  
  agentId="your-agent-id"
  apiUrl="/api/chat"
  historyApiUrl="/api/history"
  format="markdown"
  widget={{
    widgetWelcomePrompts: {
      questions: [
        'What is the price of the NFT?',
        'Latest activity of a specific wallet',
        'Which tokens are trending?'
      ],
      actions: ['Buy NFT', 'Sell NFT', 'Swap NFT'],
    },
  }}
/>
```

### 3. Setup API Route

Create an API route in your Next.js application to proxy requests to the Bitte API to not expose your key

```typescript
import type { NextRequest } from 'next/server';

const {
  BITTE_API_KEY,
  BITTE_API_URL = 'https://ai-runtime-446257178793.europe-west1.run.app/chat',
} = process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const POST = async (req: NextRequest): Promise<Response> => {
  try {
    const data = await req.json();

    const requestInit: RequestInit & { duplex: 'half' } = {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${BITTE_API_KEY}`,
      },
      duplex: 'half',
    };

    const upstreamResponse = await fetch(`${BITTE_API_URL}`, requestInit);

    const headers = new Headers(upstreamResponse.headers);
    headers.delete('Content-Encoding');

    return new Response(upstreamResponse.body, {
      status: upstreamResponse.status,
      headers,
    });
  } catch (error) {
    console.error('Error in chat API route:', error);
    return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
      status: 500,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  }
};


```

Create an history api route to keep the context of the widget chat.<br>

```typescript
import { type NextRequest, NextResponse } from 'next/server';

const { BITTE_API_KEY, BITTE_API_URL = "https://ai-runtime-446257178793.europe-west1.run.app" } =
  process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const GET = async (req: NextRequest): Promise<NextResponse> => {
  const { searchParams } = new URL(req.url);
  const id = searchParams.get('id');
  const url = `${BITTE_API_URL}/history?id=${id}`;

  const response = await fetch(url, {
    headers: {
      Authorization: `Bearer ${BITTE_API_KEY}`,
    },
  });

  const result = await response.json();

  return NextResponse.json(result);
};

```

At this point the chat should already work but to be able to send transactions you will need to add a wallet connection

### 4. Add wallet connection

#### NEAR Integration

You can integrate with NEAR using either the NEAR Wallet Selector or a direct account connection. If you want to be able to send near transacitons through the chat you will need to define at least one of these

**Using Wallet Selector**

```typescript
import { useBitteWallet, Wallet } from "@bitte-ai/react";
import { BitteWidgetChat } from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';


export default function Chat() {
  const { selector } = useBitteWallet();
  const [wallet, setWallet] = useState<Wallet>();

  useEffect(() => {
    const fetchWallet = async () => {
      const walletInstance = await selector.wallet();
      setWallet(walletInstance);
    };
    if (selector) fetchWallet();
  }, [selector]);

  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{ near: { wallet } }}
    />
  );
}
```

**Using Direct Account**

```typescript
import { Account } from "near-api-js";
// get near account instance from near-api-js by instantiating a keypair
<BitteWidgetChat
  agentId="your-agent-id"
  apiUrl="/api/chat"
  wallet={{ near: { account: nearAccount } }}
/>
```

#### EVM Integration

EVM integration uses WalletConnect with wagmi hooks:

```typescript

import { useAppKitAccount } from '@reown/appkit/react';
import { useSendTransaction, useSwitchChain } from 'wagmi';

export default function Chat() {

  const { address } = useAppKitAccount();
  const { data: hash, sendTransaction } = useSendTransaction();
  const { switchChain } = useSwitchChain();
  
  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{
        evm: { address, hash, sendTransaction, switchChain },
      }}
    />
  );
}
```

#### SUI Integration

SUI integration uses WalletConnect with wagmi hooks:

```typescript
import { useWallet as useSuiWallet } from '@suiet/wallet-kit';

export default function Chat() {

  const suiWallet = useSuiWallet();

  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={ sui: { wallet: suiWallet },}
    />
  );
}
```

### Example Usage

Here's how you might configure the `BitteWidgetChat` component, including some optional props and custom components:

```tsx
          <BitteWidgetChat
            options={{
              agentImage: bitteAgent?.image,
              agentName: bitteAgent?.name,
              colors: chatColors,
            }}
            wallet={{
              near: {
                wallet: wallet,
              },
              evm: evmAdapter,
            }}
            agentId={searchParams.get('agentId') || bitteAgent?.id || 'bitte-assistant'}
            apiUrl="/api/chat"
            historyApiUrl="api/history"
            widget={{
              widgetWelcomePrompts: {
                questions: [
                  'What is the price of the NFT?',
                  'Latest activity of a specific wallet',
                  'Which tokens are trending?',
                ],
                actions: ['Buy NFT', 'Sell NFT', 'Swap NFT'],
              },
            }}
        />
```

###

###
