npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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/sdk

Basic 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 identifier
  • config: Configuration object for the creator
  • className: Additional CSS classes
  • onAppCreated: Callback when app is successfully created
  • onError: 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 identifier
  • config: Configuration object for the preview
  • className: Additional CSS classes
  • style: Inline styles
  • onPreviewLoad: Callback when preview loads
  • onError: 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 identifier
  • config: Configuration object for the chat
  • className: Additional CSS classes
  • style: Inline styles
  • onMessageSent: Callback when user sends a message
  • onMessageReceived: Callback when AI responds
  • onError: 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-flash

AppBuilder

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 identifier
  • appId: Existing app ID to load (optional)
  • config: Configuration object for the builder
  • className: Additional CSS classes
  • style: Inline styles
  • onAppCreated: Callback when new app is created
  • onAppUpdated: Callback when app is updated
  • onError: 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 identifier
  • tenantId / externalTenantId - Filter by external tenant identifier
  • orgId / 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.