Skip to main content

Frontend Components

Artos provides a single, embeddable Artos component that can be integrated into any React application. This component gives you complete access to the Artos platform while maintaining full control over authentication, styling, and user experience.

Overview

The Artos frontend integration consists of one comprehensive component that provides access to the entire Artos platform - from workflow creation and execution to debugging and analytics. This component can be embedded in any React application with your own authentication layer and custom styling.

What is the Artos Component?

The Artos component is a complete, embeddable interface to the Artos platform. It’s not just a set of individual components for specific backend operations - it’s a full-featured application that you can embed directly into your existing applications.

Key Benefits

  • Complete Platform Access: Full access to all Artos capabilities in one component
  • Custom Authentication: Wrap with your own authentication and authorization layer
  • Complete Styling Control: Full customization of appearance and branding
  • Seamless Integration: Embeds naturally into existing React applications
  • Responsive Design: Works on desktop, tablet, and mobile devices
  • TypeScript Support: Full type safety and IntelliSense support

Installation and Setup

Package Installation

Install the Artos React component package:
npm install @artos/react-component
# or
yarn add @artos/react-component

Basic Integration

The simplest way to integrate Artos into your application:
import React from 'react';
import { ArtosApp } from '@artos/react-component';

function MyApplication() {
  return (
    <div className="my-app">
      <header>
        <h1>My Company Dashboard</h1>
        <nav>{/* Your navigation */}</nav>
      </header>
      
      <main>
        <ArtosApp 
          apiKey="your_api_key"
          theme="light"
        />
      </main>
    </div>
  );
}

export default MyApplication;

With Authentication Wrapper

Integrate with your existing authentication system:
import React from 'react';
import { ArtosApp } from '@artos/react-component';
import { useAuth } from './auth/useAuth';
import { LoadingSpinner } from './components/LoadingSpinner';
import { LoginForm } from './components/LoginForm';

function AuthenticatedArtosApp() {
  const { user, isAuthenticated, isLoading, logout } = useAuth();

  if (isLoading) {
    return <LoadingSpinner />;
  }

  if (!isAuthenticated) {
    return <LoginForm />;
  }

  return (
    <div className="dashboard">
      <header className="dashboard-header">
        <h1>AI Workflow Platform</h1>
        <div className="user-menu">
          <span>Welcome, {user.name}</span>
          <button onClick={logout}>Logout</button>
        </div>
      </header>
      
      <ArtosApp
        apiKey="your_api_key"
        userId={user.id}
        userEmail={user.email}
        userRole={user.role}
        theme="light"
        onError={(error) => console.error('Artos error:', error)}
        onSuccess={(message) => console.log('Artos success:', message)}
      />
    </div>
  );
}

export default AuthenticatedArtosApp;

Component Configuration

Props

The ArtosApp component accepts the following props:
PropTypeDefaultDescription
apiKeystringRequiredYour Artos API key
theme'light' | 'dark' | 'auto''light'Component theme
userIdstringOptionalCurrent user ID for analytics
userEmailstringOptionalCurrent user email
userRolestringOptionalCurrent user role for permissions
localestring'en'Language locale
classNamestringOptionalCustom CSS class name
styleobjectOptionalInline styles
onError(error: Error) => voidOptionalError handler
onSuccess(message: string) => voidOptionalSuccess handler
onWorkflowCreate(workflow: Workflow) => voidOptionalWorkflow creation callback
onWorkflowExecute(execution: Execution) => voidOptionalWorkflow execution callback
customConfigobjectOptionalAdvanced configuration options

TypeScript Integration

import React from 'react';
import { ArtosApp, ArtosAppProps, Workflow, Execution } from '@artos/react-component';

interface DashboardProps {
  user: {
    id: string;
    name: string;
    email: string;
    role: 'admin' | 'user' | 'viewer';
  };
  apiKey: string;
}

function Dashboard({ user, apiKey }: DashboardProps) {
  const handleWorkflowCreate = (workflow: Workflow) => {
    console.log('New workflow created:', workflow);
    // Log to your analytics system
    analytics.track('workflow_created', {
      userId: user.id,
      workflowId: workflow.id,
      workflowName: workflow.name
    });
  };

  const handleWorkflowExecute = (execution: Execution) => {
    console.log('Workflow executed:', execution);
    // Log to your analytics system
    analytics.track('workflow_executed', {
      userId: user.id,
      workflowId: execution.workflowId,
      executionId: execution.id,
      status: execution.status
    });
  };

  const handleError = (error: Error) => {
    console.error('Artos error:', error);
    // Log to your error tracking system
    errorTracker.captureException(error, {
      userId: user.id,
      context: 'artos_component'
    });
  };

  return (
    <div className="dashboard">
      <ArtosApp
        apiKey={apiKey}
        userId={user.id}
        userEmail={user.email}
        userRole={user.role}
        theme="light"
        onWorkflowCreate={handleWorkflowCreate}
        onWorkflowExecute={handleWorkflowExecute}
        onError={handleError}
        className="custom-artos-app"
      />
    </div>
  );
}

export default Dashboard;

Authentication Integration

Custom Authentication Layer

Wrap the Artos component with your authentication system:
import React, { createContext, useContext, useEffect, useState } from 'react';
import { ArtosApp } from '@artos/react-component';

// Create authentication context
const AuthContext = createContext();

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Check for existing authentication
    checkAuthStatus();
  }, []);

  const checkAuthStatus = async () => {
    try {
      const token = localStorage.getItem('authToken');
      if (token) {
        const user = await validateToken(token);
        setUser(user);
        setIsAuthenticated(true);
      }
    } catch (error) {
      console.error('Auth check failed:', error);
      localStorage.removeItem('authToken');
    } finally {
      setIsLoading(false);
    }
  };

  const login = async (credentials) => {
    try {
      const response = await fetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(credentials)
      });

      if (response.ok) {
        const { user, token } = await response.json();
        localStorage.setItem('authToken', token);
        setUser(user);
        setIsAuthenticated(true);
        return user;
      } else {
        throw new Error('Login failed');
      }
    } catch (error) {
      console.error('Login error:', error);
      throw error;
    }
  };

  const logout = () => {
    localStorage.removeItem('authToken');
    setUser(null);
    setIsAuthenticated(false);
  };

  return (
    <AuthContext.Provider value={{ user, isAuthenticated, isLoading, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};

// Protected Artos component
function ProtectedArtosApp() {
  const { user, isAuthenticated, isLoading } = useAuth();

  if (isLoading) {
    return (
      <div className="loading-container">
        <div className="spinner" />
        <p>Loading...</p>
      </div>
    );
  }

  if (!isAuthenticated) {
    return <LoginForm />;
  }

  return (
    <div className="protected-app">
      <ArtosApp
        apiKey={process.env.REACT_APP_ARTOS_API_KEY}
        userId={user.id}
        userEmail={user.email}
        userRole={user.role}
        theme="light"
      />
    </div>
  );
}

// Main App component
function App() {
  return (
    <AuthProvider>
      <div className="app">
        <header>
          <h1>My AI Platform</h1>
        </header>
        <main>
          <ProtectedArtosApp />
        </main>
      </div>
    </AuthProvider>
  );
}

export default App;

Role-Based Access Control

Implement role-based access control around the Artos component:
import React from 'react';
import { ArtosApp } from '@artos/react-component';
import { useAuth } from './auth/useAuth';

const ROLE_PERMISSIONS = {
  admin: ['create', 'read', 'update', 'delete', 'execute', 'debug'],
  editor: ['create', 'read', 'update', 'execute'],
  viewer: ['read'],
  guest: []
};

function RoleBasedArtosApp() {
  const { user, isAuthenticated } = useAuth();

  if (!isAuthenticated) {
    return <div>Please log in to access this feature.</div>;
  }

  const userPermissions = ROLE_PERMISSIONS[user.role] || [];

  if (userPermissions.length === 0) {
    return (
      <div className="access-denied">
        <h2>Access Denied</h2>
        <p>You don't have permission to access this feature.</p>
      </div>
    );
  }

  return (
    <div className="rbac-container">
      <ArtosApp
        apiKey="your_api_key"
        userId={user.id}
        userEmail={user.email}
        userRole={user.role}
        customConfig={{
          permissions: userPermissions,
          features: {
            workflowCreation: userPermissions.includes('create'),
            workflowExecution: userPermissions.includes('execute'),
            debugging: userPermissions.includes('debug'),
            analytics: userPermissions.includes('read')
          }
        }}
      />
    </div>
  );
}

export default RoleBasedArtosApp;

Custom Styling and Theming

CSS Variables

The Artos component uses CSS variables for complete customization:
:root {
  /* Primary Brand Colors */
  --artos-primary: #1F477D;
  --artos-primary-light: #2E5A8F;
  --artos-primary-dark: #1A3D6B;
  --artos-primary-contrast: #FFFFFF;
  
  /* Secondary Colors */
  --artos-secondary: #6C757D;
  --artos-secondary-light: #8A9299;
  --artos-secondary-dark: #5A6268;
  --artos-secondary-contrast: #FFFFFF;
  
  /* Background Colors */
  --artos-bg-primary: #FFFFFF;
  --artos-bg-secondary: #F8F9FA;
  --artos-bg-tertiary: #E9ECEF;
  --artos-bg-accent: #F1F3F4;
  
  /* Text Colors */
  --artos-text-primary: #212529;
  --artos-text-secondary: #6C757D;
  --artos-text-muted: #ADB5BD;
  --artos-text-disabled: #DEE2E6;
  
  /* Border Colors */
  --artos-border-primary: #DEE2E6;
  --artos-border-secondary: #E9ECEF;
  --artos-border-focus: #1F477D;
  
  /* Status Colors */
  --artos-success: #28A745;
  --artos-warning: #FFC107;
  --artos-error: #DC3545;
  --artos-info: #17A2B8;
  
  /* Spacing */
  --artos-spacing-xs: 0.25rem;
  --artos-spacing-sm: 0.5rem;
  --artos-spacing-md: 1rem;
  --artos-spacing-lg: 1.5rem;
  --artos-spacing-xl: 2rem;
  --artos-spacing-xxl: 3rem;
  
  /* Typography */
  --artos-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --artos-font-size-xs: 0.75rem;
  --artos-font-size-sm: 0.875rem;
  --artos-font-size-md: 1rem;
  --artos-font-size-lg: 1.125rem;
  --artos-font-size-xl: 1.25rem;
  --artos-font-size-xxl: 1.5rem;
  
  /* Border Radius */
  --artos-border-radius-sm: 0.25rem;
  --artos-border-radius-md: 0.375rem;
  --artos-border-radius-lg: 0.5rem;
  --artos-border-radius-xl: 0.75rem;
  
  /* Shadows */
  --artos-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --artos-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
  --artos-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
  --artos-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  
  /* Transitions */
  --artos-transition-fast: 150ms ease-in-out;
  --artos-transition-medium: 300ms ease-in-out;
  --artos-transition-slow: 500ms ease-in-out;
}

Dark Theme Support

[data-theme="dark"] {
  --artos-primary: #3B82F6;
  --artos-primary-light: #60A5FA;
  --artos-primary-dark: #2563EB;
  
  --artos-bg-primary: #1F2937;
  --artos-bg-secondary: #111827;
  --artos-bg-tertiary: #374151;
  --artos-bg-accent: #4B5563;
  
  --artos-text-primary: #F9FAFB;
  --artos-text-secondary: #D1D5DB;
  --artos-text-muted: #9CA3AF;
  --artos-text-disabled: #6B7280;
  
  --artos-border-primary: #4B5563;
  --artos-border-secondary: #374151;
  --artos-border-focus: #3B82F6;
}

Custom Branding

Complete customization example:
import React from 'react';
import { ArtosApp } from '@artos/react-component';
import './custom-branding.css';

function CustomBrandedArtosApp() {
  return (
    <div className="custom-branded-container">
      <ArtosApp
        apiKey="your_api_key"
        theme="custom"
        className="branded-artos"
        customConfig={{
          branding: {
            companyName: "Your Company",
            primaryColor: "#FF6B35",
            secondaryColor: "#004E89"
          }
        }}
      />
    </div>
  );
}

export default CustomBrandedArtosApp;
/* custom-branding.css */
.branded-artos {
  --artos-primary: #FF6B35;
  --artos-primary-light: #FF8C61;
  --artos-primary-dark: #E55A2B;
  
  --artos-secondary: #004E89;
  --artos-secondary-light: #1A6BA8;
  --artos-secondary-dark: #003A6B;
  
  --artos-font-family: 'Your Custom Font', sans-serif;
  
  /* Custom header styling */
  & .artos-header {
    background: linear-gradient(135deg, #FF6B35 0%, #004E89 100%);
    color: white;
    padding: var(--artos-spacing-lg);
    border-radius: var(--artos-border-radius-lg);
    margin-bottom: var(--artos-spacing-lg);
  }
  
  /* Custom button styling */
  & .artos-button-primary {
    background: linear-gradient(135deg, #FF6B35 0%, #E55A2B 100%);
    border: none;
    color: white;
    border-radius: var(--artos-border-radius-md);
    padding: var(--artos-spacing-sm) var(--artos-spacing-md);
    font-weight: 600;
    transition: all var(--artos-transition-fast);
  }
  
  & .artos-button-primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--artos-shadow-lg);
  }
  
  /* Custom card styling */
  & .artos-card {
    background: var(--artos-bg-primary);
    border: 1px solid var(--artos-border-primary);
    border-radius: var(--artos-border-radius-lg);
    padding: var(--artos-spacing-lg);
    box-shadow: var(--artos-shadow-md);
    transition: all var(--artos-transition-medium);
  }
  
  & .artos-card:hover {
    box-shadow: var(--artos-shadow-xl);
    transform: translateY(-4px);
  }
}

Responsive Design

Ensure the Artos component works well on all devices:
.artos-responsive-container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--artos-spacing-md);
}

/* Tablet styles */
@media (max-width: 768px) {
  .artos-responsive-container {
    padding: var(--artos-spacing-sm);
  }
  
  .branded-artos {
    --artos-font-size-md: 0.875rem;
    --artos-spacing-md: 0.75rem;
    --artos-spacing-lg: 1rem;
  }
}

/* Mobile styles */
@media (max-width: 480px) {
  .artos-responsive-container {
    padding: var(--artos-spacing-xs);
  }
  
  .branded-artos {
    --artos-font-size-md: 0.75rem;
    --artos-spacing-sm: 0.375rem;
    --artos-spacing-md: 0.5rem;
    --artos-spacing-lg: 0.75rem;
  }
  
  .branded-artos .artos-header {
    padding: var(--artos-spacing-md);
    text-align: center;
  }
}

Advanced Integration Patterns

Multi-Tenant Support

Support multiple tenants with different configurations:
import React from 'react';
import { ArtosApp } from '@artos/react-component';
import { useTenant } from './hooks/useTenant';

function MultiTenantArtosApp() {
  const { tenant, isLoading } = useTenant();

  if (isLoading) {
    return <div>Loading tenant configuration...</div>;
  }

  return (
    <div className={`tenant-${tenant.id}`}>
      <ArtosApp
        apiKey={tenant.artosApiKey}
        theme={tenant.theme}
        className={`tenant-${tenant.id}-artos`}
        customConfig={{
          branding: {
            companyName: tenant.name,
            primaryColor: tenant.primaryColor,
            secondaryColor: tenant.secondaryColor
          },
          features: tenant.enabledFeatures,
          limits: tenant.limits
        }}
      />
    </div>
  );
}

export default MultiTenantArtosApp;

Custom Event Handling

Handle all events from the Artos component:
import React, { useCallback } from 'react';
import { ArtosApp } from '@artos/react-component';

function EventHandledArtosApp() {
  const handleArtosEvent = useCallback((eventType, data) => {
    // Central event handler for all Artos events
    console.log(`Artos event: ${eventType}`, data);
    
    // Log to analytics
    analytics.track(`artos_${eventType}`, data);
    
    // Handle specific events
    switch (eventType) {
      case 'workflow_created':
        showNotification('Workflow created successfully', 'success');
        break;
      case 'workflow_executed':
        showNotification('Workflow executed successfully', 'success');
        break;
      case 'error':
        showNotification('An error occurred', 'error');
        errorTracker.captureException(data.error);
        break;
      case 'user_action':
        // Track user interactions
        userBehaviorTracker.track(data.action, data.context);
        break;
      default:
        break;
    }
  }, []);

  return (
    <div className="event-handled-app">
      <ArtosApp
        apiKey="your_api_key"
        onEvent={handleArtosEvent}
        customConfig={{
          eventTracking: {
            enabled: true,
            trackUserInteractions: true,
            trackPerformance: true
          }
        }}
      />
    </div>
  );
}

export default EventHandledArtosApp;

Performance Optimization

Lazy Loading

Lazy load the Artos component to improve initial page load:
import React, { Suspense, lazy } from 'react';
import { LoadingSpinner } from './components/LoadingSpinner';

// Lazy load the Artos component
const ArtosApp = lazy(() => import('@artos/react-component'));

function LazyArtosApp() {
  return (
    <div className="lazy-artos-container">
      <Suspense fallback={<LoadingSpinner message="Loading Artos..." />}>
        <ArtosApp apiKey="your_api_key" />
      </Suspense>
    </div>
  );
}

export default LazyArtosApp;

Memory Management

Implement proper cleanup and memory management:
import React, { useEffect, useRef } from 'react';
import { ArtosApp } from '@artos/react-component';

function OptimizedArtosApp() {
  const artosRef = useRef(null);

  useEffect(() => {
    // Cleanup function
    return () => {
      if (artosRef.current) {
        // Cleanup any resources
        artosRef.current.cleanup();
      }
    };
  }, []);

  return (
    <div className="optimized-artos">
      <ArtosApp
        ref={artosRef}
        apiKey="your_api_key"
        customConfig={{
          performance: {
            enableVirtualization: true,
            lazyLoadImages: true,
            debounceMs: 300,
            maxCacheSize: 100
          }
        }}
      />
    </div>
  );
}

export default OptimizedArtosApp;

Error Handling and Monitoring

Comprehensive Error Boundary

import React from 'react';
import { ArtosApp } from '@artos/react-component';

class ArtosErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      hasError: false, 
      error: null, 
      errorInfo: null 
    };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    this.setState({
      error: error,
      errorInfo: errorInfo
    });

    // Log to error tracking service
    console.error('Artos Error Boundary:', error, errorInfo);
    
    // Send to error tracking service
    if (window.errorTracker) {
      window.errorTracker.captureException(error, {
        extra: errorInfo,
        tags: {
          component: 'artos',
          boundary: 'ArtosErrorBoundary'
        }
      });
    }
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="artos-error-boundary">
          <div className="error-content">
            <h2>Something went wrong</h2>
            <p>The Artos component encountered an error. Please try refreshing the page.</p>
            
            {process.env.NODE_ENV === 'development' && (
              <details style={{ whiteSpace: 'pre-wrap', marginTop: '1rem' }}>
                <summary>Error Details (Development Only)</summary>
                <pre>{this.state.error && this.state.error.toString()}</pre>
                <pre>{this.state.errorInfo.componentStack}</pre>
              </details>
            )}
            
            <div className="error-actions">
              <button 
                onClick={() => window.location.reload()}
                className="error-button-primary"
              >
                Refresh Page
              </button>
              <button 
                onClick={() => this.setState({ hasError: false, error: null, errorInfo: null })}
                className="error-button-secondary"
              >
                Try Again
              </button>
            </div>
          </div>
        </div>
      );
    }

    return this.props.children;
  }
}

function SafeArtosApp() {
  return (
    <ArtosErrorBoundary>
      <ArtosApp 
        apiKey="your_api_key"
        onError={(error) => {
          console.error('Artos component error:', error);
          // Additional error handling
        }}
      />
    </ArtosErrorBoundary>
  );
}

export default SafeArtosApp;

Best Practices

Security Considerations

  1. API Key Management: Never expose API keys in client-side code
  2. Authentication: Always wrap with proper authentication
  3. Authorization: Implement role-based access control
  4. Data Sanitization: Sanitize all user inputs
  5. HTTPS: Always use HTTPS in production

Performance Guidelines

  1. Lazy Loading: Load the component only when needed
  2. Caching: Implement proper caching strategies
  3. Virtualization: Use virtualization for large datasets
  4. Debouncing: Debounce user inputs to reduce API calls
  5. Memory Management: Implement proper cleanup

User Experience

  1. Loading States: Show appropriate loading indicators
  2. Error Messages: Provide clear, actionable error messages
  3. Responsive Design: Ensure mobile compatibility
  4. Accessibility: Follow WCAG guidelines
  5. Performance: Optimize for fast loading and smooth interactions

Troubleshooting

Common Issues

  1. Component Not Loading: Check API key and network connectivity
  2. Styling Issues: Verify CSS variables are properly defined
  3. Authentication Problems: Ensure proper token handling
  4. Performance Issues: Check for memory leaks and optimize renders
  5. Mobile Issues: Test responsive design on various devices

Debug Mode

Enable debug mode for development:
import { ArtosApp } from '@artos/react-component';

function DebugArtosApp() {
  return (
    <ArtosApp
      apiKey="your_api_key"
      customConfig={{
        debug: process.env.NODE_ENV === 'development',
        logging: {
          level: 'verbose',
          includeNetworkRequests: true,
          includeUserActions: true
        }
      }}
    />
  );
}
This comprehensive documentation covers the complete integration of the Artos component as a single, embeddable application that can be fully customized and secured within your existing applications.