@embedanyai/sdk
v1.7.1
Published
Embeddable SDK for app creation, preview, and AI chat functionality
Readme
EmbedAnyAI SDK
The EmbedAnyAI SDK allows you to embed powerful app creation, preview, and AI chat functionality into your own applications. Build complete app development workflows with just a few lines of code.
Features
- 🚀 App Creation: Embeddable app creation forms with framework selection
- 👁️ Live Preview: Real-time app preview with fullscreen support
- 🤖 AI Agent: Advanced AI assistant with real development capabilities
- 🔧 MCP Integration: Model Control Protocol for connecting to development tools
- 🏗️ Freestyle Development: Direct integration with Freestyle dev servers
- 💬 AI Chat: Interactive chat interface with file upload support
- 🛠️ Development Tools: File operations, terminal commands, and code generation
- 🎨 Customizable: Flexible theming and configuration options
- 📱 Responsive: Mobile-friendly components
- ⚡ React Hooks: Easy integration with React applications
- 🔧 TypeScript: Full TypeScript support with comprehensive types
Quick Start
Installation
npm install @embedanyai/sdk
# or
yarn add @embedanyai/sdkBasic Usage
import {
initialize,
AppCreator,
AppPreview,
AppChat,
AppBuilder
} from '@embedanyai/sdk';
// Initialize the SDK
initialize({
apiUrl: 'https://your-api-endpoint.com',
teamSlug: 'your-team',
authToken: 'your-auth-token', // optional
theme: {
primary: '#3b82f6',
background: '#ffffff',
text: '#1e293b',
},
});
// Use individual components
function MyApp() {
return (
<div>
{/* App creation form */}
<AppCreator
companyId="your-company-id"
onAppCreated={(app) => console.log('App created:', app)}
/>
{/* App preview */}
<AppPreview
appId="app-id-here"
config={{ allowFullscreen: true }}
/>
{/* AI chat interface */}
<AppChat
appId="app-id-here"
config={{ autoFocus: true }}
/>
{/* Complete app builder */}
<AppBuilder
companyId="your-company-id"
config={{ layout: 'split' }}
/>
</div>
);
}Components
AppCreator
Embeddable app creation form with framework selection and validation.
<AppCreator
companyId="your-company-id"
config={{
enabled: true,
showAdvancedOptions: false,
defaultFramework: 'nextjs',
allowFrameworkSelection: true,
}}
onAppCreated={(app) => {
console.log('New app created:', app);
}}
onError={(error) => {
console.error('Creation failed:', error);
}}
/>Props:
companyId(required): Company/team identifierconfig: Configuration object for the creatorclassName: Additional CSS classesonAppCreated: Callback when app is successfully createdonError: Callback for error handling
AppPreview
Live preview component with fullscreen support and auto-refresh.
<AppPreview
appId="your-app-id"
config={{
enabled: true,
autoRefresh: true,
refreshInterval: 5000,
allowFullscreen: true,
showCode: true,
}}
onPreviewLoad={(url) => {
console.log('Preview loaded:', url);
}}
style={{ height: '600px' }}
/>Props:
appId(required): App identifierconfig: Configuration object for the previewclassName: Additional CSS classesstyle: Inline stylesonPreviewLoad: Callback when preview loadsonError: Callback for error handling
AppChat
Interactive AI chat interface for app development assistance.
<AppChat
appId="your-app-id"
config={{
enabled: true,
autoFocus: true,
allowImageUpload: false,
maxMessages: 100,
placeholder: "Ask me anything about your app...",
}}
onMessageSent={(message) => {
console.log('Message sent:', message);
}}
onMessageReceived={(message) => {
console.log('AI response:', message);
}}
/>Props:
appId(required): App identifierconfig: Configuration object for the chatclassName: Additional CSS classesstyle: Inline stylesonMessageSent: Callback when user sends a messageonMessageReceived: Callback when AI respondsonError: Callback for error handling
AI Agent Capabilities
The AppChat component includes advanced AI agent functionality powered by Mastra and MCP integration:
Real Development Tools:
- File operations (create, read, edit, delete)
- Terminal command execution
- Project structure navigation
- Package installation and management
- Code generation and refactoring
Supported Commands:
// Users can ask the AI to perform real development tasks:
"Add a login form with validation"
"Create a responsive navigation menu"
"Install React Router and set up routing"
"Add dark mode toggle to the app"
"Fix the TypeScript errors in components/"
"Add unit tests for the LoginForm component"
"Optimize the image loading in Gallery"MCP Integration: The AI connects to development environments through the Model Control Protocol (MCP), enabling:
- Direct filesystem access
- Real-time code execution
- Live app modification
- Freestyle sandbox integration
AI Provider Configuration:
# Environment variables for AI configuration
ADORABLE_AI_PROVIDER=anthropic # or 'google', 'openai'
ANTHROPIC_API_KEY=your_anthropic_key
ANTHROPIC_MODEL=claude-3-5-sonnet-20241022
# Google configuration
GOOGLE_API_KEY=your_google_key
GOOGLE_MODEL=gemini-2.5-flashAppBuilder
Complete app development interface combining all components.
<AppBuilder
companyId="your-company-id"
appId="existing-app-id" // optional
config={{
layout: 'split', // 'split', 'tabbed', or 'stacked'
showHeader: true,
headerTitle: 'App Builder',
chatPosition: 'right',
previewPosition: 'left',
resizable: true,
}}
onAppCreated={(app) => {
console.log('App created:', app);
}}
onAppUpdated={(app) => {
console.log('App updated:', app);
}}
/>Props:
companyId(required): Company/team identifierappId: Existing app ID to load (optional)config: Configuration object for the builderclassName: Additional CSS classesstyle: Inline stylesonAppCreated: Callback when new app is createdonAppUpdated: Callback when app is updatedonError: Callback for error handling
React Hooks
useEmbedAnyAIApp
Hook for managing a single app's state and operations.
import { useEmbedAnyAIApp } from '@embedanyai/sdk';
function MyComponent({ appId }) {
const { app, loading, error, refresh, updateApp } = useEmbedAnyAIApp(appId);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h1>{app?.name}</h1>
<p>Status: {app?.status}</p>
<p>Framework: {app?.framework}</p>
<button onClick={refresh}>Refresh</button>
<button onClick={() => updateApp({ description: 'Updated!' })}>
Update
</button>
</div>
);
}useAppChat
Hook for managing chat functionality.
import { useAppChat } from '@embedanyai/sdk';
function ChatComponent({ appId }) {
const { messages, loading, error, sendMessage, clearMessages } = useAppChat(appId);
return (
<div>
{messages.map(msg => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
<button
onClick={() => sendMessage('Hello AI!')}
disabled={loading}
>
Send Message
</button>
<button onClick={clearMessages}>
Clear Chat
</button>
</div>
);
}useAppPreview
Hook for managing app preview functionality.
import { useAppPreview } from '@embedanyai/sdk';
function PreviewComponent({ appId }) {
const { previewUrl, loading, error, refresh } = useAppPreview(appId);
return (
<div>
{previewUrl ? (
<iframe src={previewUrl} width="100%" height="400" />
) : (
<div>No preview available</div>
)}
<button onClick={refresh} disabled={loading}>
{loading ? 'Refreshing...' : 'Refresh Preview'}
</button>
</div>
);
}useEmbedAnyAIApps
Hook for managing multiple apps with filtering, pagination, and external ID support.
import { useEmbedAnyAIApps } from '@embedanyai/sdk';
function AppListComponent() {
const { apps, loading, error, pagination, refresh, loadMore, setFilters } = useEmbedAnyAIApps({
limit: 10,
status: 'deployed'
});
// Filter by external customer ID
const handleFilterByCustomer = (customerId: string) => {
setFilters({
customerId: customerId,
limit: 10
});
};
// Filter by external organization ID
const handleFilterByOrg = (orgId: string) => {
setFilters({
orgId: orgId,
limit: 10
});
};
if (loading && apps.length === 0) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h1>Apps ({pagination?.totalCount})</h1>
<div>
<button onClick={() => handleFilterByCustomer('customer-123')}>
Filter by Customer 123
</button>
<button onClick={() => handleFilterByOrg('org-456')}>
Filter by Org 456
</button>
<button onClick={() => setFilters({})}>
Clear Filters
</button>
</div>
{apps.map(app => (
<div key={app.id}>
<h3>{app.name}</h3>
<p>Status: {app.status}</p>
<p>Framework: {app.framework}</p>
</div>
))}
{pagination?.hasNext && (
<button onClick={loadMore} disabled={loading}>
{loading ? 'Loading...' : 'Load More'}
</button>
)}
<button onClick={refresh}>Refresh All Apps</button>
</div>
);
}External ID Filtering
The SDK supports filtering apps by external IDs to help integrate with your existing systems:
// Using external customer ID
const { apps } = useEmbedAnyAIApps({
customerId: 'customer-123',
limit: 20
});
// Using external tenant/org ID (multiple naming options)
const { apps } = useEmbedAnyAIApps({
tenantId: 'tenant-456', // or orgId: 'org-456'
externalOrgId: 'org-789', // alternative naming
framework: 'nextjs' // combine with other filters
});
// Creating apps with external IDs
await createApp({
name: 'Customer App',
framework: 'nextjs',
companyId: 'your-company-id',
customerId: 'customer-123', // External customer ID
tenantId: 'tenant-456', // External tenant ID
externalOrgId: 'org-789' // Alternative external org ID
});Supported External ID Parameters:
customerId/externalCustomerId- Filter by external customer identifiertenantId/externalTenantId- Filter by external tenant identifierorgId/externalOrgId- Filter by external organization identifier
These parameters work in both app creation and filtering, allowing you to organize and retrieve apps based on your external system's identifiers.
Configuration
SDK Configuration
import { initialize } from '@embedanyai/sdk';
initialize({
// API endpoint (required)
apiUrl: 'https://your-api-endpoint.com',
// Team slug for API requests (required)
teamSlug: 'your-team',
// Optional authentication token
authToken: 'your-auth-token',
// Theme customization
theme: {
primary: '#3b82f6',
secondary: '#64748b',
background: '#ffffff',
text: '#1e293b',
border: '#e2e8f0',
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444',
},
// Global component configuration
components: {
appCreator: {
enabled: true,
showAdvancedOptions: false,
},
appPreview: {
enabled: true,
autoRefresh: true,
refreshInterval: 5000,
},
appChat: {
enabled: true,
allowImageUpload: true,
maxMessages: 100,
maxMessageLength: 4000,
ai: {
enabled: true,
streamingSupported: true,
toolsEnabled: true,
contextualAssistance: true,
agent: {
enabled: true,
provider: {
provider: 'anthropic',
model: 'claude-3-5-sonnet-20241022',
maxTokens: 4000,
temperature: 0.1,
},
mcpServers: [
{
id: 'freestyle-dev',
url: 'your-freestyle-mcp-url',
enabled: true,
tools: ['write_file', 'read_file', 'exec', 'list_directory'],
sessionCache: true,
},
],
maxSteps: 10,
maxRetries: 3,
contextAware: true,
},
},
},
},
// Enable debug mode
debug: true,
});Custom Styling
The SDK includes default CSS styles, but you can customize the appearance:
/* Override CSS variables */
:root {
--embed-primary: #your-color;
--embed-background: #your-bg;
--embed-border-radius: 12px;
}
/* Custom component styles */
.embed-app-creator {
border: 2px solid #custom-border;
}
.embed-button-primary {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
}Or disable default styles and provide your own:
// Don't import the default CSS
import {
AppCreator,
AppPreview,
AppChat
} from '@embedanyai/sdk/components';
// Provide your own CSS classes
<AppCreator
className="my-custom-creator"
companyId="company-id"
/>Examples
Basic Integration
import React from 'react';
import { initialize, AppBuilder } from '@embedanyai/sdk';
// Initialize once in your app
initialize({
apiUrl: process.env.REACT_APP_API_URL,
teamSlug: 'my-team',
theme: {
primary: '#6366f1',
background: '#f8fafc',
},
});
function App() {
return (
<div className="app">
<h1>My App Builder</h1>
<AppBuilder
companyId="my-company"
config={{
layout: 'split',
showHeader: true,
headerTitle: 'Build Your App',
}}
onAppCreated={(app) => {
console.log('New app:', app);
// Handle app creation (e.g., navigate to app page)
}}
style={{ height: '80vh' }}
/>
</div>
);
}
export default App;Custom Layout
import React, { useState } from 'react';
import { AppCreator, AppPreview, AppChat } from '@embedanyai/sdk';
function CustomBuilder() {
const [currentApp, setCurrentApp] = useState(null);
const [activeTab, setActiveTab] = useState('create');
return (
<div className="custom-builder">
<nav className="tabs">
<button
onClick={() => setActiveTab('create')}
className={activeTab === 'create' ? 'active' : ''}
>
Create
</button>
{currentApp && (
<>
<button
onClick={() => setActiveTab('preview')}
className={activeTab === 'preview' ? 'active' : ''}
>
Preview
</button>
<button
onClick={() => setActiveTab('chat')}
className={activeTab === 'chat' ? 'active' : ''}
>
Chat
</button>
</>
)}
</nav>
<div className="tab-content">
{activeTab === 'create' && (
<AppCreator
companyId="my-company"
onAppCreated={(app) => {
setCurrentApp(app);
setActiveTab('chat');
}}
/>
)}
{activeTab === 'preview' && currentApp && (
<AppPreview
appId={currentApp.id}
config={{ allowFullscreen: true }}
/>
)}
{activeTab === 'chat' && currentApp && (
<AppChat
appId={currentApp.id}
config={{ autoFocus: true }}
/>
)}
</div>
</div>
);
}With Error Handling
import React, { useState } from 'react';
import { AppBuilder } from '@embedanyai/sdk';
function BuilderWithErrorHandling() {
const [error, setError] = useState(null);
const handleError = (err) => {
console.error('SDK Error:', err);
setError(err.message);
};
const clearError = () => setError(null);
return (
<div>
{error && (
<div className="error-banner">
<span>Error: {error}</span>
<button onClick={clearError}>×</button>
</div>
)}
<AppBuilder
companyId="my-company"
config={{
layout: 'tabbed',
showHeader: true,
}}
onError={handleError}
onAppCreated={(app) => {
console.log('App created successfully:', app);
clearError();
}}
/>
</div>
);
}Multi-Tenant App Management
import React, { useState } from 'react';
import { useEmbedAnyAIApps, AppCreator, AppBuilder } from '@embedanyai/sdk';
function CustomerAppsManager({ customerId, tenantId }) {
const [selectedApp, setSelectedApp] = useState(null);
const [showCreateForm, setShowCreateForm] = useState(false);
// Get apps filtered by customer and tenant
const { apps, loading, error, refresh, setFilters } = useEmbedAnyAIApps({
customerId,
tenantId,
limit: 10,
status: 'deployed'
});
const handleCreateApp = (app) => {
console.log('New customer app created:', app);
setShowCreateForm(false);
refresh(); // Refresh the list
};
const handleFilterChange = (filters) => {
setFilters({
customerId,
tenantId,
...filters
});
};
return (
<div className="customer-apps-manager">
<div className="header">
<h1>Apps for Customer {customerId}</h1>
<button onClick={() => setShowCreateForm(true)}>
Create New App
</button>
</div>
<div className="filters">
<select onChange={(e) => handleFilterChange({ framework: e.target.value })}>
<option value="">All Frameworks</option>
<option value="nextjs">Next.js</option>
<option value="react">React</option>
<option value="vue">Vue.js</option>
</select>
<select onChange={(e) => handleFilterChange({ status: e.target.value })}>
<option value="">All Status</option>
<option value="deployed">Deployed</option>
<option value="building">Building</option>
<option value="draft">Draft</option>
</select>
</div>
{showCreateForm && (
<div className="modal">
<AppCreator
companyId="my-company"
defaultValues={{
customerId,
tenantId,
}}
onAppCreated={handleCreateApp}
onCancel={() => setShowCreateForm(false)}
/>
</div>
)}
{loading ? (
<div>Loading apps...</div>
) : error ? (
<div className="error">Error: {error}</div>
) : (
<div className="apps-grid">
{apps.map(app => (
<div key={app.id} className="app-card">
<h3>{app.name}</h3>
<p>{app.description}</p>
<p>Status: {app.status}</p>
<p>Framework: {app.framework}</p>
<button onClick={() => setSelectedApp(app)}>
Open Builder
</button>
</div>
))}
</div>
)}
{selectedApp && (
<div className="app-builder-modal">
<AppBuilder
appId={selectedApp.id}
companyId="my-company"
config={{ layout: 'split' }}
onClose={() => setSelectedApp(null)}
/>
</div>
)}
</div>
);
}API Reference
Types
interface EmbedAnyAIApp {
id: string;
name: string;
description?: string;
framework: string;
status: 'draft' | 'building' | 'deployed' | 'error';
previewUrl?: string;
deployUrl?: string;
sourceCode?: string;
companyId: string;
metadata?: {
mcpEphemeralUrl?: string;
aiProvider?: string;
aiModel?: string;
developmentMode?: boolean;
[key: string]: any;
};
createdAt: string;
updatedAt: string;
}
interface CreateAppRequest {
name: string;
description?: string;
framework: string;
companyId: string;
templateId?: string;
prompt?: string;
tags?: string[];
customerId?: string;
tenantId?: string;
orgId?: string;
externalCustomerId?: string;
externalTenantId?: string;
externalOrgId?: string;
}
interface GetAppsFilters {
page?: number;
limit?: number;
status?: string;
framework?: string;
customerId?: string;
tenantId?: string;
orgId?: string;
externalCustomerId?: string;
externalTenantId?: string;
externalOrgId?: string;
}
interface ChatMessage {
id: string;
role: 'user' | 'assistant' | 'system';
content: string;
images?: any[];
createdAt: string;
}
interface SDKConfig {
apiUrl: string;
authToken?: string;
teamSlug?: string;
theme: SDKTheme;
components: ComponentConfigs;
debug?: boolean;
}
// AI Configuration Types
interface AIProviderConfig {
provider: 'anthropic' | 'google' | 'openai';
model?: string;
apiKey?: string;
maxTokens?: number;
temperature?: number;
}
interface MCPServerConfig {
id: string;
url: string;
enabled?: boolean;
tools?: string[];
sessionCache?: boolean;
}
interface AIAgentConfig {
enabled: boolean;
provider: AIProviderConfig;
mcpServers?: MCPServerConfig[];
systemPrompt?: string;
maxSteps?: number;
maxRetries?: number;
contextAware?: boolean;
}
interface AIConfig {
enabled: boolean;
agent?: AIAgentConfig;
streamingSupported?: boolean;
toolsEnabled?: boolean;
contextualAssistance?: boolean;
onAgentStart?: () => void;
onAgentComplete?: (result: any) => void;
onToolExecution?: (toolName: string, args: any) => void;
}
interface AppChatConfig {
enabled: boolean;
allowImageUpload?: boolean;
maxMessages?: number;
maxMessageLength?: number;
placeholder?: string;
autoFocus?: boolean;
ai?: AIConfig;
onMessageSent?: (message: ChatMessage) => void;
onMessageReceived?: (message: ChatMessage) => void;
onError?: (error: Error) => void;
}Utility Functions
import { createApp, getApp, getApps, sendChatMessage } from '@embedanyai/sdk';
// Create a new app
const response = await createApp({
name: 'My App',
description: 'A great app',
framework: 'nextjs',
companyId: 'my-company',
});
// Create app with external IDs for multi-tenant scenarios
const customerApp = await createApp({
name: 'Customer Portal',
description: 'Customer-specific portal app',
framework: 'nextjs',
companyId: 'my-company',
customerId: 'customer-123',
tenantId: 'tenant-abc',
externalOrgId: 'org-456',
});
// Get app details
const app = await getApp('app-id');
// Get apps with filtering by external IDs
const customerApps = await getApps({
customerId: 'customer-123',
limit: 20,
});
const orgApps = await getApps({
orgId: 'org-456',
status: 'deployed',
framework: 'nextjs',
});
// Get all apps for a specific tenant with pagination
const tenantApps = await getApps({
tenantId: 'tenant-abc',
page: 1,
limit: 10,
});
// Send chat message
const chatResponse = await sendChatMessage('app-id', 'Hello AI!');Requirements
- React 16.8+
- TypeScript 4.0+ (optional but recommended)
- Modern browser with ES6+ support
Support
License
MIT License - see LICENSE file for details.
