@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
Markdown
# 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:**
```
```