Developer quickstart

Add a MeshLite avatar to your site

The avatar runs in an iframe served by MeshLite and is rendered in your visitor’s browser. Your page loads one script, your server issues short-lived session tokens, and voice and AI come from your own provider account.

Using an AI coding agent?

Paste this prompt into Claude Code, Codex, Cursor or another coding agent. It follows our integration guide for agents, writes the server route and the page code, and tells you what to set up in the Console. Your secret key stays out of the chat: you add it to your .env file yourself.

Add a MeshLite talking avatar to this website. Follow the guide at https://meshlite.io/llms.txt (if you can't open it, ask me to paste it). Ask me for my MeshLite publishable key and, optionally, an avatar ID. Never ask me to paste my secret key: put a placeholder in .env and I'll add it myself. If I don't have a MeshLite account, send me to https://console.meshlite.io/console?plan=free#signup first.
Get API key

Agent without web access? Copy the full guide and paste it into the conversation.

Create your workspace

Sign up in the Console: free, no card, activated from the email we send. The Free plan is for building and testing: localhost and staging domains, the default avatars, a MeshLite badge on the avatar, up to 3 simultaneous conversations and a one-time voice trial. Going live on your production domain needs a paid plan.

Set up the Console

Then add them to your server’s environment. The secret key never goes in browser code or Git.

MESHLITE_SECRET_KEY=ml_sk_test_...
MESHLITE_PUBLISHABLE_KEY=ml_pk_test_...
MESHLITE_ORIGIN=http://localhost:3000
MESHLITE_AVATAR=

Issue session tokens from your server

Your server keeps the secret key and asks MeshLite for a session token. Call this from a POST /api/meshlite-session route and return { sessionToken }. Tokens last 2 minutes; the SDK asks for a new one when it needs it. Node.js 18+, no dependency:

export async function createMeshLiteSession() {
  const response = await fetch("https://console.meshlite.io/api/v1/client-sessions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MESHLITE_SECRET_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      publishableKey: process.env.MESHLITE_PUBLISHABLE_KEY,
      origin: process.env.MESHLITE_ORIGIN, // from your config, never from the request
      avatar: process.env.MESHLITE_AVATAR || undefined,
      conversation: { language: "en", responseStyle: "concise", idleTimeout: 30 },
    }),
  });
  const body = await response.json();
  if (!response.ok) throw new Error(`MeshLite ${body.error?.code}: ${body.error?.message}`);
  return body.sessionToken;
}

The route is public: rate-limit it, or put it behind your own sign-in if only signed-in users should talk to the avatar.

Mount the avatar in your page

The iframe takes the size of its container. Browsers only open the microphone after a click, so start the conversation from one.

<div id="avatar" style="width:340px;height:510px"></div>
<button id="talk">Talk to the avatar</button>
<script src="https://console.meshlite.io/sdk/1.11.39/meshlite.js" crossorigin="anonymous"></script>
<script>
  const avatar = MeshLite.mount({
    container: "#avatar",
    avatar: "YOUR_AVATAR_ID",          // same as MESHLITE_AVATAR; remove for the default avatar
    locale: "en",
    publishableKey: "ml_pk_test_...",  // safe to expose
    sessionToken: async () => {
      const response = await fetch("/api/meshlite-session", { method: "POST" });
      if (!response.ok) throw new Error("Could not start the avatar session");
      return (await response.json()).sessionToken;
    },
    conversation: { language: "en", responseStyle: "concise", idleTimeout: 30 },
    captions: "overlay",
  });
  avatar.on("error", (message, detail) => console.error("MeshLite", detail.code, message));
  document.getElementById("talk").addEventListener("click", () => avatar.startConversation());
</script>

React, Next.js, Vue: load the script once, mount in a client-side effect (useEffect, onMounted) and call avatar.unmount() in its cleanup. There is no npm package: load the SDK from console.meshlite.io only.

Going live

Move to a paid plan, add your production domain as a live domain (HTTPS), create live keys and replace the test values in your environment. No code change is needed.

Reference

Questions about your integration? Write to hello@meshlite.io.