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

# Basic application

> Build a complete web application with an Anam persona

This guide creates a minimal but complete web application with an interactive AI persona. You will build a Node.js server that handles authentication and a client that streams the persona to a video element.

<Info>
  Looking for a faster start? The [Quickstart](/javascript-sdk/quickstart) guide gets you running in a single HTML file without a server.
</Info>

## Prerequisites

* **Node.js** (version 16 or higher) and **npm** installed on your system
* Basic knowledge of JavaScript
* An Anam API key ([get one here](/api-key))
* A microphone and speakers for voice interaction

## Project Setup

This example creates a web application with three main files:

```
my-anam-app/
├── server.js          # Express server for secure API key handling
├── package.json       # Node.js dependencies
├── public/            # Static files served to the browser
│   ├── index.html     # Main HTML page with video element
│   └── script.js      # Client-side JavaScript for persona control
└── .env               # Environment variables (optional)
```

<Steps>
  <Step title="Create project directory">
    ```bash theme={"system"}
    mkdir my-anam-app
    cd my-anam-app
    ```
  </Step>

  <Step title="Initialize Node.js project">
    ```bash theme={"system"}
    npm init -y
    ```
  </Step>

  <Step title="Create public directory">
    ```bash theme={"system"}
    mkdir public
    ```
  </Step>

  <Step title="Install dependencies">
    ```bash theme={"system"}
    npm install express dotenv
    ```
  </Step>

  <Step title="Create environment file">
    Create a `.env` file in your project root to store your API key securely:

    ```bash .env theme={"system"}
    ANAM_API_KEY=your-api-key-here
    ```

    <Warning>
      Replace `your-api-key-here` with your actual Anam API key. Never commit this file to version control.
    </Warning>
  </Step>
</Steps>

## Step 1: Set up your server

Create a basic Express server to handle session token generation. In a production application, integrate this into your existing backend service.

```javascript server.js theme={"system"}
require("dotenv").config();
const express = require("express");
const app = express();

app.use(express.json());
app.use(express.static("public"));

app.post("/api/session-token", async (req, res) => {
  try {
    const response = await fetch("https://api.anam.ai/v1/auth/session-token", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.ANAM_API_KEY}`,
      },
      body: JSON.stringify({
        personaConfig: {
          name: "Cara",
          avatarId: "30fa96d0-26c4-4e55-94a0-517025942e18",
          voiceId: "6bfbe25a-979d-40f3-a92b-5394170af54b",
          llmId: "a7cf662c-2ace-4de1-a21e-ef0fbf144bb7",
          systemPrompt:
            "You are Cara, a helpful customer service representative. Be friendly and concise in your responses.",
        },
      }),
    });

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({}));
      console.error("Anam API error:", response.status, errorData);
      return res.status(response.status).json({
        error: errorData.message || "Failed to create session token",
      });
    }

    const data = await response.json();
    res.json({ sessionToken: data.sessionToken });
  } catch (error) {
    console.error("Server error:", error);
    res.status(500).json({ error: "Internal server error" });
  }
});

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});
```

The server exchanges your API key for a temporary session token. This token has limited scope and expires, so your API key stays secure on the server.

## Step 2: Set up your HTML

Create an HTML page with a video element for the persona and controls to start/stop the chat:

```html public/index.html theme={"system"}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My First Anam Persona</title>
  </head>
  <body>
    <div style="text-align: center; padding: 20px;">
      <h1>Chat with Cara</h1>
      <video
        id="persona-video"
        autoplay
        playsinline
        style="max-width: 100%; border-radius: 8px;"
      ></video>
      <div style="margin-top: 20px;">
        <button id="start-button">Start Chat</button>
        <button id="stop-button" disabled>Stop Chat</button>
      </div>
      <div id="status" style="margin-top: 10px; color: #666;"></div>
    </div>
    <script type="module" src="script.js"></script>
  </body>
</html>
```

## Step 3: Initialize the Anam client

Create the client-side JavaScript to control your persona connection:

```javascript public/script.js theme={"system"}
import { createClient } from "https://esm.sh/@anam-ai/js-sdk@latest";

let anamClient = null;

const startButton = document.getElementById("start-button");
const stopButton = document.getElementById("stop-button");
const videoElement = document.getElementById("persona-video");
const statusElement = document.getElementById("status");

function setStatus(message) {
  statusElement.textContent = message;
}

async function startChat() {
  try {
    startButton.disabled = true;
    setStatus("Creating session...");

    // Get session token from your server
    const response = await fetch("/api/session-token", {
      method: "POST",
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error || "Failed to get session token");
    }

    const { sessionToken } = await response.json();
    setStatus("Connecting...");

    // Create the Anam client
    anamClient = createClient(sessionToken);

    // Start streaming to the video element
    await anamClient.streamToVideoElement("persona-video");

    startButton.disabled = true;
    stopButton.disabled = false;
    setStatus("Connected - start speaking!");
  } catch (error) {
    console.error("Failed to start chat:", error);
    setStatus(`Error: ${error.message}`);
    startButton.disabled = false;
  }
}

function stopChat() {
  if (anamClient) {
    anamClient.stopStreaming();
    anamClient = null;

    videoElement.srcObject = null;

    startButton.disabled = false;
    stopButton.disabled = true;
    setStatus("Chat ended");
  }
}

startButton.addEventListener("click", startChat);
stopButton.addEventListener("click", stopChat);
```

For details on `createClient`, `streamToVideoElement`, and `stopStreaming`, see the [SDK Reference](/javascript-sdk/reference/basic-usage).

## Step 4: Run your application

1. Start your server:

```bash theme={"system"}
node server.js
```

2. Open [http://localhost:3000](http://localhost:3000) in your browser
3. Click "Start Chat" to begin your conversation with Cara

<Check>
  You should see Cara appear in the video element, ready to chat through voice interaction.
</Check>

## How it works

1. **Server-side authentication**: Your server exchanges the API key for a session token, keeping credentials secure
2. **Client connection**: The SDK creates a WebRTC connection for real-time video streaming
3. **Voice interaction**: Cara listens for your voice input and responds with synchronized audio and video
4. **Connection control**: Start and stop buttons control when the persona is active

## Next steps

<CardGroup cols={2}>
  <Card title="Cookbook: Basic Next.js App" icon="book-open" href="https://anam.ai/cookbook/basic-nextjs-app">
    Full tutorial for building a Next.js app with the Anam SDK
  </Card>

  <Card title="Core Concepts" icon="lightbulb" href="/personas/overview">
    Learn how personas, tokens, and streaming work
  </Card>

  <Card title="Handle Events" icon="bolt" href="/javascript-sdk/reference/event-types">
    React to conversation events and user interactions
  </Card>

  <Card title="Production Setup" icon="shield" href="/javascript-sdk/production">
    Deploy your persona securely at scale
  </Card>
</CardGroup>

## Common issues

**Persona not appearing?**

* Check that your API key is set correctly in `.env`
* Ensure the video element has `autoplay` and `playsinline` attributes
* Check the browser console for errors

**No audio?**

* Make sure your browser allows autoplay with sound
* The user must interact with the page first (clicking "Start Chat" satisfies this)

**Connection issues?**

* Verify your server can reach api.anam.ai
* Check network connectivity and firewall settings
