Pernoex
FeaturesPricingDocs
Sign InGet Started
FeaturesPricingDocs
Sign InGet Started

Getting Started

  • Floating Mode
  • Embedded Mode
  • Inline Explainer Mode

Advanced

  • Theme Customization
  • Common Use Cases
  • JavaScript API
  • Framework Examples

Resources

  • Security
  • Troubleshooting

Integration Guide

Everything you need to integrate the Pernoex cognition layer into your product

Pernoex offers three UI integration modes: Floating for a chat bubble experience,Embedded for custom layouts where you want the intelligence always visible, and Inline Explainer for contextual "Ask AI" functionality on text selection that opens an AI sidebar with full conversational support. (For IDE integration, see our MCP documentation).

Floating Mode

The default integration. A floating interface appears in the corner of your page that users can click to open and close.

Basic Setup

Add this before the closing </body> tag:

html
<script src="https://cdn.pernoex.com/widget.js"
data-api-key="YOUR_API_KEY"></script>

Custom API URL

For self-hosted instances:

html
<script src="https://cdn.pernoex.com/widget.js"
data-api-key="YOUR_API_KEY"
data-api-url="https://your-api.example.com/api/v1"></script>

Live Preview

Click the chat bubble to preview

Embedded Mode

Render the intelligence inside a specific container. Perfect for dedicated help pages, sidebars, or custom layouts.

Container Requirements: Your container needs a defined height (or flex/grid sizing). The widget will automatically set position: relative on it if needed. If the container has zero height, a console warning will help you diagnose the issue.

Setup

html
<div id="chat-container" style="height: 600px;"></div>
<script src="https://cdn.pernoex.com/widget.js"
data-manual-init="true"></script>
<script>
Pernoex.init({
apiKey: 'YOUR_API_KEY',
mode: 'embedded',
container: '#chat-container',
showHeader: true,
borderRadius: '12px'
});
</script>

Live Preview

AI Assistant

Hi! How can I help you today?

How do I get started?

Great question! You can start by creating a project in your dashboard...

Embedded mode - always visible

Configuration Options

OptionTypeDefaultDescription
apiKeystringrequiredYour project's public API key
mode'floating' | 'embedded' | 'inline''floating'Widget display mode
containerstring | HTMLElementnoneCSS selector or element (required for embedded)
apiUrlstringcdn defaultCustom API endpoint URL
showHeaderbooleantrueShow or hide header in embedded mode
showBrandingbooleanfrom configOverride branding visibility
borderRadiusstring'0'CSS border radius for container
showAvatarsbooleantrueShow or hide user/bot avatars next to messages
themeThemeOverridesnoneCustom color and style overrides (see Theme Customization)
zIndexnumber2147483000Base z-index for the widget layer stack. The widget uses 7 layers above this base value. Adjust if you need to control stacking with other overlays.

Inline Explainer Mode

Add contextual AI explanations to any text in your product. Users can highlight text and click "Ask AI" to get explanations grounded in your knowledge base in a sidebar that pushes page content, keeping the reading context visible.

Dashboard Controlled Enable or disable the inline explainer from your project's Settings page in the dashboard. When enabled, users can select text and get AI explanations powered by your indexed documentation. The sidebar also supports follow up conversations for deeper understanding.

Basic Setup

html
<!-- Inline explainer is controlled from your dashboard settings -->
<!-- Once enabled, it works automatically with text selection -->
<script src="https://cdn.pernoex.com/widget.js"
data-api-key="YOUR_API_KEY"></script>

How It Works

Our RAG pipeline ensures accurate responses grounded in your documentation.

Click "RAG pipeline" above to preview

Advanced Configuration

javascript
// For programmatic control, you can override dashboard settings
Pernoex.init({
apiKey: 'YOUR_API_KEY',
inline: {
enabled: true, // Override dashboard setting
triggerSelector: 'article, .docs-content', // Only in these areas
excludeSelector: 'nav, .code-block', // Not in these areas
position: 'auto', // 'auto' | 'above' | 'below'
showFollowUp: true, // Allow follow-up questions
theme: 'auto' // Match system theme
}
});

Configuration Options

OptionTypeDefaultDescription
enabledbooleanfalseEnable inline explainer (controlled from dashboard settings by default)
triggerSelectorstringnoneCSS selector to limit where text selection triggers the explainer
excludeSelectorstringnoneCSS selector for areas to exclude from text selection
position'auto' | 'above' | 'below''auto'Preferred tooltip position relative to selection
maxWidthnumber400Maximum width of the explainer sidebar in pixels
showFollowUpbooleanfalseShow input field for follow up questions
theme'light' | 'dark' | 'auto''auto'Color theme for the sidebar

Combined with Floating Integration

The inline explainer works alongside your main floating integration automatically. When enabled from the dashboard, both the floating interface and text selection explainer are available to your users:

javascript
// Inline explainer works alongside the floating widget automatically
// Just enable it in your dashboard settings, or override via init:
Pernoex.init({
apiKey: 'YOUR_API_KEY',
inline: {
enabled: true // Works alongside the floating chat widget
}
});

Theme Customization

Fully customize the widget's visual appearance to match your brand. Pass a theme object with any combination of color overrides. All properties are optional — only specify what you want to change.

Example: Transparent Background (No Avatars)

javascript
Pernoex.init({
apiKey: 'YOUR_API_KEY',
showAvatars: false,
theme: {
background: 'transparent',
assistantBubbleBg: '#f0f1f3',
assistantTextColor: '#1a1d23',
userBubbleBg: '#0f172a',
userTextColor: '#ffffff',
linkColor: '#0f172a',
inputBg: '#ffffff',
inputBorderColor: '#e5e7eb',
inputTextColor: '#1a1d23',
inputPlaceholderColor: '#9ca3af',
sendButtonBg: '#0f172a',
sendButtonColor: '#ffffff',
fontFamily: '"Inter", sans-serif'
}
});

Example: Dark Theme

javascript
Pernoex.init({
apiKey: 'YOUR_API_KEY',
theme: {
background: '#1a1a2e',
assistantBubbleBg: '#16213e',
assistantTextColor: '#e2e8f0',
userBubbleBg: '#0f172a',
userTextColor: '#ffffff',
linkColor: '#818cf8',
inputBg: '#16213e',
inputBorderColor: '#2a2a4a',
inputTextColor: '#e2e8f0',
inputPlaceholderColor: '#64748b',
sendButtonBg: '#0f172a',
sendButtonColor: '#ffffff'
}
});

Theme Properties

PropertyTypeDefaultDescription
backgroundstring#f7f8faMessages area & window background. Use 'transparent' for seamless embedding.
assistantBubbleBgstring#ffffffAssistant message bubble background
assistantTextColorstring#1a1d23Assistant message text color
userBubbleBgstringprimary colorUser message bubble background
userTextColorstring#ffffffUser message text color
linkColorstringprimary colorLink color inside messages
inputBgstring#f7f8faInput textarea background
inputBorderColorstring#e5e7ebInput border color
inputTextColorstring#1a1d23Input text color
inputPlaceholderColorstring#b0b8c1Input placeholder text color
sendButtonBgstringprimary colorSend button background
sendButtonColorstring#ffffffSend button icon color
fontFamilystringsystem defaultGlobal font family override

Common Use Cases

Full-Page Intelligence

Create a dedicated support or chat page:

html
<!DOCTYPE html>
<html>
<head>
<style>
body, html { margin: 0; height: 100%; }
#chat-container { height: 100vh; width: 100%; }
</style>
</head>
<body>
<div id="chat-container"></div>
<script src="https://cdn.pernoex.com/widget.js"
data-manual-init="true"></script>
<script>
Pernoex.init({
apiKey: 'YOUR_API_KEY',
mode: 'embedded',
container: '#chat-container'
});
</script>
</body>
</html>
AI Assistant

Hi! How can I help you today?

How do I get started?

Great question! You can start by creating a project in your dashboard...

Embedded mode - always visible

Sidebar Integration

Add a persistent intelligence sidebar to your application:

html
<div style="display: flex; height: 100vh;">
<main style="flex: 1;">
<!-- Your main content -->
</main>
<aside id="chat-sidebar"
style="width: 400px; border-left: 1px solid #e5e7eb;">
</aside>
</div>
<script src="https://cdn.pernoex.com/widget.js"
data-manual-init="true"></script>
<script>
Pernoex.init({
apiKey: 'YOUR_API_KEY',
mode: 'embedded',
container: '#chat-sidebar',
showHeader: true
});
</script>
Help

Need help with anything?

Sidebar integration layout

JavaScript API Reference

Control Methods

Available for floating mode:

javascript
// Open the chat window
Pernoex.open()
// Close the chat window
Pernoex.close()
// Toggle open/closed state
Pernoex.toggle()
// Check if widget is currently open
const isOpen = Pernoex.isOpen()
// Clear all messages and start a new conversation
Pernoex.clearMessages()
// Get explanation for text programmatically
const explanation = await Pernoex.explain("text to explain")
// Destroy the widget and clean up
Pernoex.destroy()

Event Callbacks

Listen to integration lifecycle events:

javascript
Pernoex.init({
apiKey: 'YOUR_API_KEY',
onReady: () => {
console.log('Widget is ready');
},
onOpen: () => {
console.log('Widget opened');
},
onClose: () => {
console.log('Widget closed');
},
onMessage: (message) => {
console.log('New message:', message);
},
onError: (error) => {
console.error('Widget error:', error);
},
onExplain: (text, explanation) => {
console.log('Explained:', text, explanation);
},
onExplainError: (error) => {
console.error('Explain error:', error);
}
});

Framework Examples

jsx
import { useEffect, useRef } from 'react';
function ChatWidget() {
const containerRef = useRef(null);
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://cdn.pernoex.com/widget.js';
script.setAttribute('data-manual-init', 'true');
document.body.appendChild(script);
script.onload = () => {
window.Pernoex.init({
apiKey: 'YOUR_API_KEY',
mode: 'embedded',
container: containerRef.current,
showHeader: true
});
};
return () => {
window.Pernoex?.destroy();
document.body.removeChild(script);
};
}, []);
return <div ref={containerRef} style={{ height: '600px' }} />;
}

Security & Best Practices

Shadow DOM Isolation: The widget renders inside a Shadow DOM boundary, providing full CSS and DOM encapsulation:
  • Your page's CSS cannot affect the widget, and widget styles cannot leak into your page
  • Host-page scripts cannot access widget DOM internals (e.g. conversation messages)
  • Styles are injected via adoptedStyleSheets — no style-src 'unsafe-inline' CSP directive needed
  • Fonts are loaded via @font-face inside the shadow root — no <link> tags are injected into your <head>
Important: Only use your public API key in client-side code. Never expose private/secret keys in HTML or JavaScript.

Domain Restrictions

Domain restrictions control which sites are allowed to load your widget. The behavior depends on whether you have configured any allowed domains yet:

  • No domains configured (default): The API key is open — any origin is accepted, including localhost. This lets you develop and test locally without any extra setup, and allows third-party integrators to get started immediately.
  • At least one domain configured: Enforcement becomes strict. Only the exact domains you have listed are accepted. localhost is not automatically allowed once you lock down your project.
Testing locally after locking down? Add localhost or your specific local port (e.g. localhost:3000) to your project's allowed domains list. Remove it before going to production.

Content Security Policy

If you use CSP headers, allow the following. Note that style-src 'unsafe-inline' is not required — the widget uses Shadow DOM with adoptedStyleSheets for CSP-compliant style injection.

text
script-src 'self' https://cdn.pernoex.com;
connect-src 'self' https://api.pernoex.com;
style-src 'self';
img-src 'self' https:;
font-src 'self' data: https://fonts.gstatic.com;
frame-src 'none';
object-src 'none';
base-uri 'self';

Troubleshooting

Widget Blocked After Adding Domain Restrictions

  • Once you add at least one allowed domain, localhost is no longer automatically permitted
  • Add localhost or localhost:PORT (e.g.localhost:3000) to your allowed domains list for local development
  • Remove localhost from your allowed domains before deploying to production if you want to restrict access to your live domains only
  • The browser console error will show origin_not_allowed when this occurs

Integration Not Appearing

  • Verify your API key is correct
  • If you have configured allowed domains, check that the current domain is in the list
  • If no domains are configured yet, the widget accepts all origins automatically
  • Open browser console for errors
  • Ensure the script tag is loaded (check the Network tab)

Embedded Mode Container Empty

  • Confirm container element exists before calling Pernoex.init()
  • Set an explicit height on the container element
  • Check console for initialization errors
  • Verify data-manual-init="true" is set on the script tag

Styling Issues

  • The widget renders inside a Shadow DOM boundary, so host page styles cannot affect it and widget styles cannot leak into your page
  • Ensure the container has defined dimensions for embedded mode
  • If the widget appears behind other elements, use the zIndex option in Pernoex.init() to adjust the stacking order

Inline Explainer Not Appearing

  • Verify inline explainer is enabled in your project's Settings page on the dashboard
  • Check triggerSelector matches elements on your page
  • Ensure selection is at least 3 characters
  • Check console for JavaScript errors
  • Verify the selected area is not excluded by excludeSelector

Explanations Are Generic

  • Ensure your knowledge base is indexed (check Crawl status in dashboard)
  • The selected text should relate to content in your indexed pages
  • Try selecting more specific terms from your documentation
  • Check that your project has sufficient credit balance

Sidebar Not Pushing Content

  • The sidebar pushes page content to the left when it opens
  • Ensure your page layout can accommodate the sidebar width
  • Check for fixed positioning elements that may not respond to the push

Need Help?

Have questions about integration? Reach out to our support team at [email protected] or explore more examples in your dashboard.

Pernoex

Give your product a mind.

Product

  • Features
  • Pricing
  • Compare Plans
  • Changelog
  • Security

Resources

  • Documentation
  • API Reference

Company

  • About
  • Contact

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
© 2026 Pernoex. All rights reserved.