UNPKG

@sherpahow/sherpa-sdk

Version:

Sherpa JavaScript SDK for in-app help and product tours. Built with TypeScript, Lit web components, and Nano Stores.

1,494 lines (1,136 loc) â€Ē 43.1 kB
# Sherpa JavaScript SDK A comprehensive JavaScript SDK for in-app help and product tours. Built with TypeScript, Lit web components, and Nano Stores for state management. ## Features - ðŸŽŊ **Context-aware Tours**: Smart tours that adapt to user context and provide personalized recommendations - 🔍 **Natural Language Search**: AI-powered search with floating interface for tours and knowledge base content - ðŸŽĻ **Context Collection Modal**: Gather user context for personalized tour experiences - 📚 **Draggable Docss**: In-app knowledge base documents in resizable, draggable windows - ðŸ’Ą **Interactive Tooltips**: Both informational and actionable tooltips with form auto-fill capabilities - 📍 **Beacons**: Non-intrusive visual indicators to guide user attention - ðŸŽŪ **Control Panel**: Tour navigation and progress tracking - 📊 **Analytics**: Comprehensive event tracking and user behavior analytics - 🔒 **Security**: CSP compliance, origin validation, and secure iframe sandboxing - 🚀 **Performance**: Optimized element resolution, caching, and minimal DOM impact - ðŸ“ą **SPA Support**: Navigation detection and tour state management for single-page applications - 🔗 **Automatic Navigation**: Tours automatically navigate to the correct page using buildUrl configuration - 🌐 **URL Parameter Support**: Start tours directly via URL parameters (?sherpa=tourId) - 🧭 **Router Integration**: Seamless integration with React Router, Next.js Router, and custom routers for SPA navigation without page refreshes ## 🚀 Bundle Optimization & Code Splitting The Sherpa SDK is optimized for minimal initial bundle size using dynamic imports and intelligent component grouping: ### Bundle Sizes #### Standard Build (Single Bundle) - **IIFE Format**: ~186 kB (~40 kB gzipped) - Ready for CDN - **ES Module Format**: ~286 kB (~51 kB gzipped) - For modern bundlers #### Code-Split Build (Optimized Component Grouping) - **Main Bundle**: ~20 kB (~4.5 kB gzipped) - Core SDK with dynamic imports - **Component Chunks** (loaded on-demand): - **Search Components**: ~128 kB (~22 kB gzipped) - Search interface and modal - **Tour Components**: ~45 kB (~9 kB gzipped) - Tooltip, Beacon, Control Panel - **Docs Components**: ~37 kB (~8 kB gzipped) - Knowledge Base document viewer - **Modals**: ~6 kB (~2 kB gzipped) - Context collection and other modals - **Tour Utilities**: ~46 kB (~9 kB gzipped) - Element resolver and recommendation applier ### Performance Benefits 1. **⚡ 90% Smaller Initial Load**: Only ~20 kB vs ~280 kB for the main bundle 2. **ðŸ“Ķ Component-Based Loading**: Load only what users need, when they need it 3. **ðŸŽŊ Better Caching**: Each component chunk cached separately 4. **🏃 Faster TTI**: Dramatically improved Time to Interactive 5. **🧠 Intelligent Prefetching**: Components load based on user interaction patterns ### Component Loading Strategy #### Sequential Loading Priority The SDK implements an intelligent sequential loading strategy: 1. **Search Components** load first when search is accessed - providing immediate search capability 2. **Docs Components** load in the background after search is ready - for smooth Docs viewing 3. **Tour Components** load when tours are started - ensuring seamless tour experiences 4. **Tour Controller** loads lazily only when tours are actually initiated ```mermaid graph TD A[SDK Boot] --> B[Core Bundle Loaded ~21kB] B --> C[User Opens Search] C --> D[Search Components Load ~131kB] D --> E[Search Available Immediately] E --> F[Docs Components Load in Background ~38kB] F --> G[Docss Ready] B --> H[User Starts Tour] H --> I[Tour Controller Instantiated] I --> J[Tour Components Load ~46kB] J --> K[Tour Utilities Load ~47kB] K --> L[Tour Ready] style B fill:#e1f5fe style D fill:#f3e5f5 style F fill:#fff3e0 style J fill:#e8f5e8 ``` #### Separation Benefits - **Search Independence**: Search functionality is available immediately without waiting for Docs or tour components - **Docs On-Demand**: Knowledge base documents load only when users need them, after search is ready - **Tour Optimization**: All tour-related functionality loads together when tours start - **Reduced Initial Bundle**: Core SDK remains minimal for fast page loads ### Build Commands ```bash # Standard build (single bundle) pnpm build # Code-split build (multiple chunks) pnpm build:split # Build both variants pnpm build:all ``` ### Usage #### For Modern Applications (Recommended) Use the code-split ES module build for optimal performance: ```javascript // The core SDK loads instantly import { SherpaSDK } from './sherpa-sdk.0.0.1.esm.js'; const sherpa = new SherpaSDK(); await sherpa.boot({ applyCSSReset: true }); // Components load on-demand when tours start await sherpa.startTour('tour-id', 'context'); ``` #### For CDN/Legacy Support Use the single bundle IIFE build: ```html <script src="https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.min.js"></script> <script> const sherpa = new SherpaSDK(); // All functionality available immediately </script> ``` ## Dynamic Import Architecture The SDK uses dynamic imports with intelligent sequential loading to achieve optimal performance: ### Sequential Loading Strategy The SDK prioritizes components based on user interaction patterns: 1. **Search Components First**: Load immediately when search is accessed, providing instant search capability without dependencies 2. **Docs Components Background**: Load asynchronously after search is ready, ensuring smooth Docs access 3. **Tour Components On-Demand**: Load together when tours start, providing seamless tour experiences 4. **Tour Utilities Lazy**: ElementResolver and RecommendationApplier load dynamically only when tours are initiated ### Component Independence - **Search Standalone**: Search functionality works independently and loads first for immediate availability - **Docs After Search**: Knowledge base components load after search is ready, optimizing the user flow - **Tour Self-Contained**: All tour functionality (tooltip, beacon, control panel) loads together when needed - **Tour Utilities Dynamic**: Element resolution and recommendation utilities load only when needed within tours - **Modals Independent**: Context and other modals remain separate for specific use cases ### Loading Behavior - **Priority-Based Loading**: Most commonly used components (search) load first - **Background Preloading**: Docs components preload after search to reduce perceived latency - **Just-in-Time Tour Loading**: Tour functionality only loads when users start tours - **Dynamic Utility Loading**: ElementResolver and RecommendationApplier load on first tour interaction - **Caching**: Once loaded, all components are cached for subsequent use - **Error Handling**: Graceful fallbacks if dynamic loading fails - **Network Optimization**: Reduces critical path loading while maintaining functionality ## CDN Deployment The Sherpa SDK is available via jsDelivr CDN for easy integration. jsDelivr automatically serves packages published to npm. ### CDN Filename Options The SDK provides two filename formats to optimize caching strategies: #### Versioned Filenames (Recommended for Cache-Busting) - **Format**: `sherpa-sdk.{version}.esm.min.js` - **Example**: `sherpa-sdk.0.0.7.esm.min.js` - **Benefits**: Automatic cache invalidation when versions change - **Use Case**: Production deployments where you want guaranteed updates #### Fixed Filenames (Convenience) - **Format**: `sherpa-sdk.esm.min.js` - **Benefits**: Simple, consistent URLs - **Use Case**: Development or when you want to always use the latest version - **Note**: May be cached by CDN/browsers; use cache purging when needed ### Quick CDN Integration ```html <!DOCTYPE html> <html> <head> <title>My App with Sherpa</title> </head> <body> <!-- Your app content --> <!-- Option 1: Versioned (Cache-busting, Recommended) --> <script type="module" src="https://cdn.jsdelivr.net/npm/@sherpahow/sherpa-sdk@0.0.7/dist/sherpa-sdk.0.0.7.esm.min.js" crossorigin="anonymous" ></script> <!-- Option 2: Fixed filename (Latest, may be cached) --> <script type="module" src="https://cdn.jsdelivr.net/npm/@sherpahow/sherpa-sdk@latest/dist/sherpa-sdk.esm.min.js" crossorigin="anonymous" ></script> <script type="module"> // Import matches the script src above import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpahow/sherpa-sdk@0.0.7/dist/sherpa-sdk.0.0.7.esm.min.js'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, }); </script> </body> </html> ``` ✅ **That's it!** Sherpa is now ready with optimized loading. Components will load automatically as needed: - **Main bundle**: ~20 kB (loads instantly) - **Components load on-demand**: Search (~128 kB), Tour (~45 kB), Docs (~37 kB) ### Available CDN Platforms - **jsDelivr**: `https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/` - **unpkg**: `https://unpkg.com/@sherpa/client@0.0.1/dist/` - **cdnjs**: Available after manual submission to cdnjs ### Build Formats & Sizes **Published Version (Code-Split for Optimal Performance):** - **Main Bundle**: ~20 kB (~4.5 kB gzipped) - Core SDK with dynamic imports - **Component Chunks** (loaded on-demand): - **Search Components**: ~128 kB (~22 kB gzipped) - Search interface and modal - **Tour Components**: ~45 kB (~9 kB gzipped) - Tooltip, Beacon, Control Panel - **Docs Components**: ~37 kB (~8 kB gzipped) - Knowledge Base document viewer - **Modals**: ~6 kB (~2 kB gzipped) - Context collection and other modals - **Tour Utilities**: ~46 kB (~9 kB gzipped) - Element resolver and recommendation applier **Alternative Builds:** - **Single Bundle**: Available as `sherpa-sdk.0.0.1.min.js` (legacy/compatibility) ### Performance Benefits of Code Splitting 1. **⚡ 90% Smaller Initial Load**: Only ~20 kB vs ~280 kB for the main bundle 2. **ðŸ“Ķ Component-Based Loading**: Load only what users need, when they need it 3. **ðŸŽŊ Better Caching**: Each component chunk cached separately 4. **🏃 Faster TTI**: Dramatically improved Time to Interactive 5. **🧠 Intelligent Prefetching**: Components load based on user interaction patterns ### Integration Examples #### ES Modules with Code Splitting (Recommended) ```html <!-- Modern approach with optimal performance --> <script type="module"> import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, }); </script> ``` #### For Legacy Browsers (Single Bundle) ```html <!-- For browsers that don't support ES modules --> <script> (function () { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.min.js'; script.onload = function () { window.Sherpa('boot', { key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, }); }; document.head.appendChild(script); })(); </script> ``` #### Advanced Setup with Preloading ```html <!-- Preload for better performance --> <link rel="dns-prefetch" href="//cdn.jsdelivr.net" /> <link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js" /> <!-- Load SDK --> <script type="module"> import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, debug: true, }); </script> ``` ## Environment Configuration ### Backend API Configuration For production deployments, you'll need to configure the backend API URL where your Sherpa backend is hosted. The SDK supports environment variables for this configuration. #### Environment Variables Create a `.env` file in your project root (copy from `env.example`): ```bash # Backend API Configuration VITE_BACKEND_URL=https://api.sherpa.example.com/api # Development Settings NODE_ENV=production ``` #### Vite Integration For Vite-based projects, use the `VITE_` prefix: ```bash # .env VITE_BACKEND_URL=https://api.sherpa.example.com/api ``` The SDK will automatically detect and use this configuration. #### Manual Configuration You can also configure the backend URL programmatically: ```javascript import { configureAPIClient } from '@sherpahow/sherpa-sdk'; // Configure for production configureAPIClient({ backendUrl: 'https://api.sherpa.example.com/api', serviceKey: 'your-service-key', }); ``` #### Environment Detection The SDK automatically determines which API client to use: - **Development** (`NODE_ENV=development`): Uses mock API client with sample data - **Production** (`NODE_ENV=production`): Uses real API client with configured backend URL #### API Client Options ```javascript import { createAPIClient } from '@sherpahow/sherpa-sdk'; // Force production client with custom URL const prodClient = createAPIClient({ backendUrl: 'https://api.sherpa.example.com/api', }); ``` ### Development vs Production - **Development**: Mock client provides sample tours and data for development - **Production**: Real client connects to your Sherpa backend for live data ## Search Functionality ### Overview The Sherpa SDK includes a powerful search system that allows users to discover tours and knowledge base content using natural language queries. The search interface consists of: 1. **Floating Search Bar**: A persistent, unobtrusive search button that expands into a full search interface 2. **Search Modal**: A comprehensive search interface with recommendations and results 3. **Context Modal**: A personalization interface for collecting tour context before starting 4. **Docs Viewer**: Draggable, resizable windows for viewing knowledge base content ### Search Flow ```mermaid graph TD A[Floating Search Bar] --> B[Click or Cmd+K] B --> C[Search Modal Opens] C --> D[Show Recommendations] C --> E[User Searches] E --> F[Display Results] F --> G[Tour Selected] F --> H[Docs Selected] G --> I[Context Modal Opens] I --> J[Basic Tour] I --> K[Custom Tour with Context] H --> L[Open Draggable Docs] L --> M[Multiple Documents Supported] ``` ### Keyboard Shortcuts - **`Cmd/Ctrl + K`**: Open search modal - **`Esc`**: Close current modal or Docs - **`Ctrl + Enter`**: Start custom tour with context (in context modal) ### Search API #### Automatic Search Initialization The search interface is available immediately after SDK initialization but is hidden by default to prevent blocking user interactions: ```javascript window.Sherpa('boot', { key: 'your-workspace-key', // ... other options }); // Search interface is available but hidden - call showSearch() to display it ``` #### Manual Search Control ```javascript // Show search interface window.Sherpa('showSearch'); // Hide search interface window.Sherpa('hideSearch'); ``` #### Search Events Listen for search-related events: ```javascript // Search shown window.Sherpa('onShowSearch', () => { console.log('Search interface opened'); }); // Search hidden window.Sherpa('onHideSearch', () => { console.log('Search interface closed'); }); ``` ## Knowledge Base Documents ### Overview The SDK provides a powerful system for displaying knowledge base documents in draggable, resizable windows within your application. Documents can contain HTML content, external URLs, or custom content. ### Key Features - **Draggable Interface**: Click and drag documents by their header - **Resizable Windows**: Resize documents using the handle in the bottom-right corner - **Window Management**: Smart positioning with cascade layout for multiple documents - **Minimize/Restore**: Collapse documents to header-only view - **Z-index Management**: Automatic focus management when clicking on documents - **Loading States**: Visual feedback during document loading - **Error Handling**: Graceful error states for failed loads - **Iframe Sandboxing**: Secure iframe sandboxing for external content ### Docs API #### Opening Documents ```javascript // Open a document with HTML content window.Sherpa('openDocs', { id: 'user-guide', title: 'User Guide', content: '<html><body><h1>User Guide</h1><p>Content here...</p></body></html>', }); // Open a document with external URL window.Sherpa('openDocs', { id: 'api-docs', title: 'API Documentation', url: 'https://api.example.com/docs', }); // Open with custom positioning and sizing window.Sherpa( 'openDocs', { id: 'help-center', title: 'Help Center', }, { position: { x: 200, y: 150 }, size: { width: 800, height: 600 }, }, ); ``` #### Programmatic Control ```javascript // Close a specific document window.Sherpa('closeDocs', 'document-id'); // Close all open documents window.Sherpa('closeAllDocs'); // Check if any documents are open const hasOpenDocs = sdk.hasOpenDocs(); ``` #### Document Object Structure ```typescript interface Docs { id: string; // Unique identifier title: string; // Display title in header url?: string; // External URL to load content?: string; // HTML content to display } ``` ### Integration with Search Docss automatically integrate with the search system: ```javascript // Listen for Docs requests from search document.addEventListener('docs-open', event => { const { docsId, title } = event.detail; // Fetch document content from your API fetch(`/api/docs/${docsId}`) .then(response => response.json()) .then(doc => { window.Sherpa('openDocs', { id: docsId, title: title, content: doc.html_content, }); }); }); ``` ### Customization #### Styling and Theming The Docs components use CSS custom properties for theming: ```css :root { --sherpa-docs-surface: rgba(31, 41, 55, 0.98); --sherpa-docs-border: rgba(255, 255, 255, 0.2); --sherpa-docs-text: #ffffff; --sherpa-docs-text-muted: #d1d5db; --sherpa-docs-primary: #3b82f6; --sherpa-docs-danger: #ef4444; --sherpa-docs-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4); } ``` #### Window Behavior ```javascript // Docs management is now integrated into UIManager // Access through the main SDK interface // Get list of open documents const hasOpenDocs = window.Sherpa('hasOpenDocs'); // Close specific document window.Sherpa('closeDocs', 'document-id'); // Close all documents window.Sherpa('closeAllDocs'); // Documents automatically handle focus management and z-index ordering // when clicked or interacted with ``` ### Accessibility The Docs system includes comprehensive accessibility features: - **Keyboard Navigation**: Full keyboard support for window controls - **Focus Management**: Proper focus handling when opening/closing documents - **Screen Reader Support**: ARIA labels and semantic markup - **High Contrast**: Sufficient color contrast ratios - **Reduced Motion**: Respects `prefers-reduced-motion` settings ### Security Docss are displayed in sandboxed iframes with restricted permissions: ```html <iframe sandbox="allow-same-origin allow-scripts allow-forms"></iframe> ``` This provides security while allowing necessary functionality for document interaction. #### CSP and Cross-Origin Handling The Docs system intelligently handles Content Security Policy (CSP) restrictions and cross-origin issues: 1. **Direct Loading**: First attempts to load external URLs directly in the iframe 2. **CSP Detection**: Automatically detects when direct loading is blocked by CSP or cross-origin restrictions 3. **Proxy Fallback**: Falls back to a proxy service (AllOrigins) when direct loading fails 4. **User Notification**: Shows a subtle notification when proxy mode is active ```javascript // The system automatically handles CSP fallback: window.Sherpa('openDocs', { id: 'external-docs', title: 'External Documentation', url: 'https://external-site.com/docs', // Will try direct first, then proxy if blocked }); ``` **Security Features:** - Automatic CSP compliance detection - Secure iframe sandboxing with minimal required permissions - Proxy service only used when necessary (not by default) - Timeout protection against slow-loading content - Memory leak prevention with automatic blob URL cleanup ### Example Implementation ```html <!DOCTYPE html> <html> <head> <title>My App with Sherpa Docss</title> </head> <body> <div id="app"> <!-- Your application content --> <button onclick="openHelpDoc()">Open Help Document</button> </div> <script> // Initialize SDK window.Sherpa('boot', { key: 'your-workspace-key', user: { id: 'user-123' }, }); function openHelpDoc() { window.Sherpa('openDocs', { id: 'help-main', title: 'Getting Started Guide', content: ` <html> <head><title>Help</title></head> <body> <h1>Getting Started</h1> <p>Welcome to our application!</p> <p>Here's how to get started...</p> </body> </html> `, }); } // Handle multiple document types function openMultipleHelp() { const docs = [ { id: 'faq', title: 'FAQ', url: '/help/faq.html' }, { id: 'guide', title: 'User Guide', url: '/help/guide.html' }, { id: 'api', title: 'API Docs', url: 'https://api.example.com/docs' }, ]; docs.forEach((doc, index) => { setTimeout(() => { window.Sherpa('openDocs', doc); }, index * 200); // Stagger opening for better UX }); } </script> </body> </html> ``` ### Demo A complete demo showcasing all Docs features is available at `src/dev/search-demo.html`, including: - Sample Docss with different content types - Drag and resize interactions - Multiple document management - Integration with search functionality ### Customization #### Search Recommendations The search interface automatically shows personalized recommendations based on: - Current page URL - User information - Previous tour history - Available content #### Tour Context Collection When users select a tour from search results, they can provide additional context: ```javascript // Example of tour context that users might provide: { role: "ė‹ ėž… 링뛐", department: "ėļė‚ŽíŒ€", situation: "ė—°ë§ė •ė‚° ėē˜ëĶŽ ė‹œ ėžėĢž ė‹Īėˆ˜í•˜ëŠ” ëķ€ëķ„ė„ ėĪ‘ė ė ėœžëĄœ ė•Œęģ  ė‹ķėŒ", requirements: "대량 ėē˜ëĶŽ ė‹œ ėĢžė˜ė‚Ží•­ë„ í•Ļęŧ˜ ė„Ī멅í•īėĢžė„ļėš”" } ``` #### Knowledge Base Integration Docss can be opened from search results. The SDK dispatches events that your application can handle: ```javascript // Listen for Docs requests document.addEventListener('docs-open', event => { const { docsId, title } = event.detail; // Handle Docs opening (e.g., create draggable iframe) openDocs(docsId, title); }); ``` #### Styling and Theming The search components use CSS custom properties for theming: ```css :root { --sherpa-primary: #3b82f6; --sherpa-primary-hover: #2563eb; --sherpa-success: #22c55e; --sherpa-surface: rgba(31, 41, 55, 0.9); --sherpa-text: #ffffff; --sherpa-text-muted: #d1d5db; --sherpa-border: rgba(255, 255, 255, 0.2); --sherpa-backdrop: rgba(0, 0, 0, 0.2); --sherpa-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4); } ``` #### Accessibility The search interface includes comprehensive accessibility features: - **Keyboard Navigation**: Full keyboard support with logical tab order - **Screen Reader Support**: Proper ARIA labels and announcements - **Focus Management**: Automatic focus handling and restoration - **Reduced Motion**: Respects `prefers-reduced-motion` settings - **High Contrast**: Sufficient color contrast ratios #### Example Implementation ```html <!DOCTYPE html> <html> <head> <title>My App with Sherpa Search</title> </head> <body> <div id="app"> <!-- Your application content --> </div> <!-- Sherpa SDK Loader --> <script> // Sherpa loader script (see installation section) </script> <script> // Initialize SDK with search window.Sherpa('boot', { key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, debug: true, }); // Optional: Listen for search events window.Sherpa('onShowSearch', () => { console.log('User opened search'); // Track search usage analytics.track('search_opened'); }); // Optional: Handle Docs requests document.addEventListener('docs-open', event => { const { docsId, title } = event.detail; // Create draggable iframe or redirect to Docs window.open(`/docs/${docsId}`, '_blank'); }); </script> </body> </html> ``` #### Demo A complete demo is available at `src/dev/search-demo.html` which showcases: - Natural language search queries - Tour personalization flow - Knowledge base integration - Keyboard shortcuts - Responsive design ## Installation ### Quick Start with jsDelivr CDN The fastest way to get started is using our jsDelivr CDN with optimized code splitting: ```html <!DOCTYPE html> <html> <head> <title>My App with Sherpa</title> </head> <body> <!-- Your app content --> <!-- Sherpa SDK (Code-Split Version) --> <script type="module" src="https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js" integrity="sha384-ugBM3nlFVMI/bXFC9mJXN/SGxQLlxqhv5S4qKeoqtEotKxYqi7jleYjHt91+EBLH" crossorigin="anonymous" ></script> <script type="module"> import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, }); </script> </body> </html> ``` ✅ **That's it!** Sherpa is now ready with optimized loading. Components will load automatically as needed: - **Main bundle**: ~20 kB (loads instantly) - **Components load on-demand**: Search (~128 kB), Tour (~45 kB), Docs (~37 kB) ### Script Tag (Recommended) Add the Sherpa SDK to your website using the loader script: ```html <script> (function () { var w = window; if (w.Sherpa) { return w.console.error('Sherpa script included twice.'); } var ch = function () { ch.c?.(arguments); }; ch.q = []; ch.c = function (args) { ch.q?.push(args); }; ch.version = '1.0.0'; w.Sherpa = ch; function l() { if (w.SherpaInitialized) { return; } w.SherpaInitialized = true; var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.crossOrigin = 'anonymous'; s.integrity = 'sha384-[HASH]'; s.src = 'https://cdn.sherpa.how/client.js'; s.onerror = function () { console.error('Failed to load Sherpa SDK. Check CSP settings.'); }; var x = document.getElementsByTagName('script')[0]; if (x && x.parentNode) { x.parentNode.insertBefore(s, x); } else { document.head.appendChild(s); } } if (document.readyState === 'complete') { l(); } else { w.addEventListener('DOMContentLoaded', l); w.addEventListener('load', l); } })(); </script> ``` ### NPM Package ```bash npm install @sherpa/client ``` ```javascript import SherpaSDK from '@sherpa/client'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, }); ``` ## Quick Start ### 1. Initialize the SDK ```javascript // Using the global Sherpa function (script tag method) window.Sherpa('boot', { key: 'your-workspace-key', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com', }, locale: 'ko', debug: true, }); ``` ### 2. Start a Tour ```javascript window.Sherpa('startTour', 'tour-id', 'User wants to learn how to use the dashboard'); ``` ### 3. Track Events ```javascript window.Sherpa('track', 'button_clicked', { button_id: 'save-profile', section: 'user-settings', }); ``` ### 4. Open Docss ```javascript window.Sherpa('openDocs', { id: 'user-guide', title: 'User Guide', content: '<h1>Getting Started</h1><p>Welcome to our platform!</p>', }); ``` ## API Reference ### Core Methods #### `boot(options, callback?)` Initialize the SDK with configuration options. ```javascript window.Sherpa( 'boot', { key: 'workspace-key', // Required: Your workspace key user: { // Optional: User information id: 'user-123', name: 'John Doe', email: 'john@example.com', }, locale: 'ko', // Optional: Locale setting debug: true, // Optional: Enable debug logging }, error => { if (error) { console.error('Boot failed:', error); } else { console.log('SDK initialized successfully'); } }, ); ``` #### `startTour(tourId, context, metadata?)` Start a tour with personalized context. The SDK automatically handles navigation if the current page doesn't match the tour's `buildUrl`. ```javascript window.Sherpa('startTour', 'onboarding-tour', 'New user needs help setting up their profile', { source: 'welcome-modal', user_type: 'premium', }); ``` **Automatic Navigation:** - If the current URL doesn't match the tour's `buildUrl`, the SDK will automatically navigate to the correct page - Tour parameters are preserved across navigation using `sessionStorage` - The tour starts automatically after the page loads **URL Parameter Support:** Tours can also be started directly via URL parameters: ```html <!-- Start tour via URL parameter --> https://yourapp.com/dashboard?sherpa=onboarding-tour <!-- Start tour with custom context --> https://yourapp.com/dashboard?sherpa=onboarding-tour:custom-context ``` #### `endTour()` End the currently active tour. ```javascript window.Sherpa('endTour'); ``` #### `showSearch()` / `hideSearch()` Control the floating search interface. ```javascript window.Sherpa('showSearch'); window.Sherpa('hideSearch'); ``` #### Docs Methods Control knowledge base documents programmatically. ```javascript // Open a Docs window.Sherpa( 'openDocs', { id: 'help-guide', title: 'Help Guide', content: '<html>...</html>', // or url: 'https://...' }, { position: { x: 100, y: 100 }, // Optional positioning size: { width: 600, height: 500 }, // Optional sizing }, ); // Close specific document window.Sherpa('closeDocs', 'document-id'); // Close all documents window.Sherpa('closeAllDocs'); ``` #### `track(eventName, properties?)` Track custom analytics events. ```javascript window.Sherpa('track', 'feature_used', { feature: 'export-data', format: 'csv', timestamp: Date.now(), }); ``` ## Integration Requirements for Client Applications ### Router Integration for SPA Navigation For Single Page Applications (SPAs), you can integrate Sherpa SDK with your router to enable seamless navigation without full page refreshes. #### Automatic Router Detection (Recommended) The SDK automatically detects and integrates with most popular routers without any configuration: ```typescript // No setup needed - SDK auto-detects router const tourController = TourController.getInstance(); await tourController.startTour('tour-id', 'context'); // Automatically uses SPA navigation if router is detected ``` For manual control, use the Universal Router Adapter: ```typescript import { UniversalRouterAdapter, TourController } from '@sherpa/client'; const routerAdapter = new UniversalRouterAdapter(); const tourController = TourController.getInstance(); tourController.setRouterAdapter(routerAdapter); ``` #### React Router Integration (Manual) ```tsx import React, { useEffect } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { TourController, ReactRouterAdapter } from '@sherpa/client'; function App() { const navigate = useNavigate(); const location = useLocation(); useEffect(() => { const routerAdapter = new ReactRouterAdapter(navigate, location); const tourController = TourController.getInstance(); tourController.setRouterAdapter(routerAdapter); return () => { tourController.setRouterAdapter(null); }; }, [navigate, location]); return <YourAppContent />; } ``` #### Next.js Integration ```tsx import { useEffect } from 'react'; import { useRouter } from 'next/router'; import { TourController, NextRouterAdapter } from '@sherpa/client'; export function SherpaProvider({ children }) { const router = useRouter(); useEffect(() => { const routerAdapter = new NextRouterAdapter(router); const tourController = TourController.getInstance(); tourController.setRouterAdapter(routerAdapter); return () => { tourController.setRouterAdapter(null); }; }, [router]); return <>{children}</>; } ``` ### Automatic Tour Navigation The Sherpa SDK automatically handles page navigation when a tour's `buildUrl` doesn't match the current URL. This feature works out-of-the-box with no additional client-side code required. #### How It Works 1. **Tour Start**: When `startTour()` is called, the SDK compares the current URL with the tour's `buildUrl` 2. **Smart Navigation**: The SDK uses multiple navigation strategies with automatic fallbacks: - **SPA Navigation**: Uses router adapters for seamless navigation without page reloads - **Content Verification**: Verifies that actual HTML content has loaded, not just URL changes - **Automatic Fallback**: Falls back to full page navigation when SPA navigation fails 3. **Parameter Preservation**: Tour parameters are stored in `sessionStorage` during navigation 4. **Auto-Resume**: After page load, the SDK automatically detects and starts the pending tour #### Client Application Requirements **✅ No Additional Code Required** The navigation feature works automatically with: - **Single Page Applications (SPAs)**: React, Angular, Next.js, SvelteKit - **Multi-Page Applications (MPAs)**: Traditional server-rendered applications - **Hybrid Applications**: Mixed SPA/MPA architectures - **Static Sites**: JAMstack and static site generators **✅ Supported URL Formats** The SDK handles both absolute and relative URLs in `buildUrl`: ```javascript // Absolute URLs "buildUrl": "https://yourapp.com/dashboard" // Relative URLs "buildUrl": "/dashboard" "buildUrl": "/users/profile?tab=settings" ``` **✅ URL Parameter Integration** Tours can be started directly via URL parameters without any additional setup: ```html <!-- These work automatically --> https://yourapp.com?sherpa=tour-id https://yourapp.com/page?sherpa=tour-id:context ``` #### Enhanced Navigation Features **🔄 Multiple Navigation Strategies** The SDK automatically tries multiple navigation approaches in order: 1. **Router Adapter Navigation**: Uses configured SPA router (React Router, etc.) 2. **Auto-Detected SPA Navigation**: Automatically detects and uses framework routers 3. **History API Navigation**: Uses browser History API for SPA-like navigation 4. **Full Page Navigation**: Traditional page reload as final fallback **🔍 Content Verification** The SDK doesn't just check URL changes - it verifies that actual content has loaded: - **Content Hash Verification**: Compares page content before and after navigation - **Title Change Detection**: Monitors document title changes - **Framework-Specific Indicators**: Checks for framework-specific DOM elements - **Loading State Detection**: Waits for loading indicators to disappear - **Lazy Loading Support**: Handles content that loads asynchronously **⚡ Intelligent Fallbacks** When SPA navigation fails or content doesn't load properly: - **Automatic Detection**: Detects when URL changes but content doesn't load - **Graceful Fallback**: Automatically switches to full page navigation - **Error Recovery**: Continues tour execution after successful fallback navigation - **Logging**: Provides detailed console logs for debugging navigation issues #### Advanced Configuration (Optional) For advanced use cases, you can customize the navigation behavior: ```javascript // Custom navigation handling (optional) window.addEventListener('beforeunload', event => { // Custom logic before navigation if (sherpaNavigationInProgress) { // Allow navigation for Sherpa tours return; } }); ``` #### Security Considerations - **Same-Origin Policy**: Navigation only works within the same origin for security - **HTTPS**: Secure contexts are maintained during navigation - **Session Storage**: Tour parameters are stored securely and expire after 5 minutes #### Troubleshooting **Tour doesn't start after navigation:** - Check that the SDK is properly initialized on the target page - Verify that `sessionStorage` is available and not blocked - Ensure the target page loads the Sherpa SDK - Check browser console for navigation verification logs **Navigation doesn't occur:** - Verify the `buildUrl` format in your tour configuration - Check browser console for navigation errors and fallback messages - Ensure the target URL is accessible and returns valid HTML - For SPAs, verify that the router is properly configured **SPA navigation fails:** - Check console logs for "Navigation verification failed" messages - Verify that your SPA router is properly handling the navigation - Ensure content actually changes after navigation (not just URL) - The SDK will automatically fall back to full page navigation **Content doesn't load after navigation:** - Check for loading indicators that might be preventing content detection - Verify that the target page has meaningful content changes - For lazy-loaded content, ensure it loads within the verification timeout - Check for JavaScript errors that might prevent content rendering ## License MIT License - see LICENSE file for details. ## Development ### Build Configuration The SDK uses aggressive minification via terser for optimal bundle sizes. To prevent method mangling issues across chunks, critical SDK methods are protected in the reserved list: #### Protected Methods The following methods are protected from mangling in `vite.config.ts`: ```javascript const reservedList = [ // SDK Core Methods 'getInstance', // Singleton pattern preservation 'boot', // SDK initialization 'shutdown', // SDK cleanup 'startTour', // Tour initiation 'endTour', // Tour termination 'nextStep', // Tour navigation 'previousStep', // Tour navigation 'goToStep', // Tour navigation 'showSearch', // UI control 'hideSearch', // UI control 'track', // Analytics 'updateUser', // User management 'openDocs', // Docs management 'closeDocs', // Docs management 'closeAllDocs', // Docs management // Framework Methods (already included) 'addEventListener', 'querySelector', 'render', 'update', 'connectedCallback', 'disconnectedCallback', 'get', 'set', 'subscribe', 'atom', 'computed', 'map', 'action', 'listen', ]; ``` #### Adding New Protected Methods When adding new public methods that are called across chunks, add them to the `reservedList` in `vite.config.ts` to prevent terser from mangling them: ```javascript // ❌ Without protection - will be mangled to single letters class MyClass { async newPublicMethod() { /* ... */ } } // ✅ With protection - method name preserved const reservedList = [ // ... existing methods 'newPublicMethod', // Add here ]; ``` ### Common Issues #### Method Not Found Errors If you see errors like `n.Y is not a function` or `this.O.o is not a function`, it means a method is being mangled across chunks. Fix by: 1. Identify the original method name from the source code 2. Add it to the `reservedList` in `vite.config.ts` 3. Rebuild with `pnpm build` #### Cross-Chunk Method Calls When methods are called across different chunks (main bundle → component chunks), they must be in the reserved list to maintain consistent naming. ## Support - Documentation: https://sherpa.how/docs - Issues: https://github.com/sherpa/sherpa-js/issues - Email: support@sherpa.how ## Publishing & CDN ### For Maintainers #### Automated Version Bump & Publish (Recommended) Use the automated bump-and-publish script for streamlined releases: ```bash # Patch release (1.0.0 → 1.0.1) to production pnpm run bump-publish # Minor release (1.0.0 → 1.1.0) to production pnpm run bump-publish minor # Major release (1.0.0 → 2.0.0) to production pnpm run bump-publish major # Beta/dev releases (adds -dev suffix) pnpm run bump-publish patch dev pnpm run bump-publish minor beta # Dry run to see what would happen pnpm run bump-publish major --dry-run ``` **What the script does:** 1. ✅ Validates git status and shows current branch 2. 📝 Bumps version in package.json (semver compliant) 3. 🏗ïļ Builds the project (production or beta build) 4. 🔐 Generates CDN integrity hashes 5. ðŸ“Ķ Commits version bump to git 6. 🚀 Publishes to npm with appropriate tag (`latest` or `beta`) 7. 🏷ïļ Creates and pushes git tag (production only) 8. 📊 Shows installation and CDN usage instructions **Script Options:** - `--bump, -b`: Version bump type (`patch`, `minor`, `major`) - `--target, -t`: Publish target (`production`, `dev`, `beta`) - `--dry-run, -d`: Show what would be done without executing - `--help, -h`: Show help message #### Manual Publishing (Legacy) To publish manually: ```bash # 1. Update version in package.json # 2. Test everything pnpm test && pnpm type-check # 3. Build and prepare for publishing pnpm run prepublishOnly # 4. Publish to npm (requires permissions) pnpm run publish:npm # 5. Verify on jsDelivr (wait 1-5 minutes) # https://cdn.jsdelivr.net/npm/@sherpa/client@VERSION/ ``` ### For Users **CDN Integration (Recommended):** ```html <script type="module"> import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/client@0.0.1/dist/sherpa-sdk.0.0.1.esm.js'; const sdk = new SherpaSDK(); await sdk.boot({ key: 'your-workspace-key' }); </script> ``` **npm Installation:** ``` ```