Overview
The person.run embed widget lets you add a fully functional persona chat interface to any website. The widget handles the UI and session lifecycle — you just configure which persona to use and how it should look.
The widget is available as a vanilla JavaScript snippet (works anywhere) or as a React component for tighter integration.
Script tag (vanilla JS)
The fastest way to get started. Add this snippet before the closing </body> tag on any page:
<script
src="https://person.run/widget.js"
data-persona-id="your-persona-id"
data-tenant-id="your-tenant-id"
data-api-key="your-public-api-key"
data-title="Talk to Aria"
data-placeholder="Ask me anything..."
data-theme="dark"
data-position="bottom-right"
defer
></script>Prefer a guided flow? Use the snippet builder below and paste values from Keys and Personas.
Snippet builder
Fill in your values, then copy a ready-to-paste script tag for your site.
<script
src="https://person.run/widget.js"
data-persona-id="your-persona-id"
data-tenant-id="your-tenant-id"
data-api-key="your-public-api-key"
data-title="Talk to Aria"
data-placeholder="Ask me anything..."
data-theme="dark"
data-position="bottom-right"
defer
></script>personas.prompt) for client-side embeds. Never expose a full-access API key in frontend code.https://person.run/api/widget/prompt by default. Override with data-endpoint if you self-host.React component
For React apps, import the widget component directly for more control over rendering and lifecycle:
npm install @person/widgetimport { PersonaChat } from "@person/widget/react";
export default function App() {
return (
<div>
<h1>My App</h1>
<PersonaChat
personaId="your-persona-id"
tenantId="your-tenant-id"
apiKey="your-public-api-key"
theme="dark"
position="bottom-right"
title="Talk to Aria"
placeholder="Ask me anything..."
greeting="Hi! I'm Aria. Ask me anything about design."
accentColor="#6366f1"
endpoint="https://person.run/api/widget/prompt"
/>
</div>
);
}Configuration options
Both the script tag and React component accept these configuration options:
personaIdUUID of the persona to chat with.
tenantIdYour tenant ID.
apiKeyPublic-scoped API key for client-side use.
theme"dark" (default) or "light". Matches the host page.
position"bottom-right" (default), "bottom-left", or "inline".
titleHeader text shown at the top of the widget (default: Chat).
placeholderInput placeholder text (default: "Type your message...").
greetingInitial message shown when the chat opens.
accentColorHex color for the send button and active states.
endpointWidget proxy endpoint. Defaults to https://person.run/api/widget/prompt.
containerCSS selector used by inline mode to find the mount node.
maxInputLengthMaximum input length for each message (default: 2000).
requestTimeoutMsHTTP timeout for widget prompt requests in milliseconds (default: 15000).
maxHeightMaximum chat window height in pixels (default: 520).
zIndexCSS z-index for the widget container (default: 9999).
Keep it aligned with Playground
- Validate persona tone and behavior in Playground before embedding on your site.
- Use the same tenant ID, persona ID, and public API key between Playground experiments and widget rollout.
- Keep greeting/title/placeholder copy consistent so the embedded chat feels like your dashboard experience.
- Use API docs for endpoint-level request/response details and error handling.
Inline mode
Set position="inline" to render the chat directly inside a container element instead of as a floating bubble. This is useful for dedicated chat pages or embedded support panels.
<div id="persona-chat" style="width: 100%; height: 600px;"></div>
<script
src="https://person.run/widget.js"
data-persona-id="your-persona-id"
data-tenant-id="your-tenant-id"
data-api-key="your-public-api-key"
data-position="inline"
data-container="#persona-chat"
defer
></script>Customizing appearance
Beyond the configuration options, you can override widget styles with CSS custom properties on the host page:
.pr-widget-root {
--pr-bg: #101728;
--pr-text: #f8fafc;
--pr-border: rgba(148, 163, 184, 0.25);
--pr-accent: #6366f1;
}Troubleshooting
- If you see an in-page setup error, verify data-persona-id, data-tenant-id, and data-api-key are all present.
- A 403 Invalid or mismatched API key usually means the key does not belong to the same tenant ID in your snippet.
- If inline mode fails, confirm the data-container selector exists on the page before widget.js loads.
- For self-hosted routes, make sure your site origin is explicitly allowed by widget CORS settings.
WIDGET_ALLOWED_ORIGINS as a comma-separated allowlist (including protocol) for embed origins.WIDGET_ALLOWED_ORIGINS="https://www.yoursite.com,https://app.yoursite.com"Best practices
- Always use a public API key with prompt-only permissions — never embed a full-access key.
- Set a greeting message to guide users on what the persona can help with.
- Match the widget theme to your page for a seamless look.
- Use inline mode for dedicated chat pages; floating mode for auxiliary support.
- Test across screen sizes — the widget adapts to mobile viewports automatically.