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

# Choose an SDK

> Pick the Era SDKs that match where your application runs.

Most applications use two SDKs:

1. A client SDK creates a stable `visitorId`.
2. The Node SDK sends the conversation to Era and returns a context block.

## SDK comparison

| Your code runs in | Package                | Use it for                                    | Key type    |
| ----------------- | ---------------------- | --------------------------------------------- | ----------- |
| Browser           | `@seasonlabs/era-web`  | Create a visitor ID and verify email or phone | Publishable |
| Flutter app       | `era_flutter`          | Create a visitor ID and verify email or phone | Publishable |
| Trusted backend   | `@seasonlabs/era-node` | Get the context block for a conversation      | Secret      |

<Warning>
  Never put a Node SDK API key in browser or mobile code.
</Warning>

## Browser application

Use the Web SDK in the browser and the Node SDK on your backend.

```typescript Browser theme={null}
const visitorId = await eraWeb.init();

await fetch("/api/chat", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ messages, visitorId }),
});
```

```typescript Trusted backend theme={null}
const block = await era.turnContext(messages, {
  visitorId,
  sessionId,
});
```

## Flutter application

Use `era_flutter` in the app and the Node SDK on your backend.

```dart Flutter theme={null}
final visitorId = await era.init();
```

Send `visitorId` with the chat request. Your backend uses it in the same
`turnContext()` call shown above.

## Backend-only application

The Node SDK still needs a stable `visitorId`. Create and store one for each
user or visitor, then pass it on every turn.

## Signed-in users

When your backend knows the signed-in user, add your own stable user ID:

```typescript theme={null}
const block = await era.turnContext(messages, {
  visitorId,
  partnerEndUserId: authenticatedUser.id,
  sessionId,
});
```

`partnerEndUserId` adds trusted account identity, but it does not replace
`visitorId`. Only send email or phone assertions that your backend has already
verified.

<CardGroup cols={3}>
  <Card title="Node SDK quickstart" icon="server" href="/quickstart">
    Request your first context block.
  </Card>

  <Card title="Web SDK quickstart" icon="browser" href="/web-sdk/quickstart">
    Create a browser visitor.
  </Card>

  <Card title="Flutter SDK quickstart" icon="mobile" href="/flutter-sdk/quickstart">
    Create a mobile visitor.
  </Card>
</CardGroup>
