@sherpahow/sherpa-sdk
v0.0.17
Published
Sherpa JavaScript SDK for in-app help and product tours. Built with TypeScript, Lit web components, and Nano Stores.
Maintainers
Readme
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
- ⚡ 90% Smaller Initial Load: Only ~20 kB vs ~280 kB for the main bundle
- 📦 Component-Based Loading: Load only what users need, when they need it
- 🎯 Better Caching: Each component chunk cached separately
- 🏃 Faster TTI: Dramatically improved Time to Interactive
- 🧠 Intelligent Prefetching: Components load based on user interaction patterns
Component Loading Strategy
Sequential Loading Priority
The SDK implements an intelligent sequential loading strategy:
- Search Components load first when search is accessed - providing immediate search capability
- Docs Components load in the background after search is ready - for smooth Docs viewing
- Tour Components load when tours are started - ensuring seamless tour experiences
- Tour Controller loads lazily only when tours are actually initiated
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:#e8f5e8Separation 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
# Standard build (single bundle)
pnpm build
# Code-split build (multiple chunks)
pnpm build:split
# Build both variants
pnpm build:allUsage
For Modern Applications (Recommended)
Use the code-split ES module build for optimal performance:
// 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:
<script src="https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/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:
- Search Components First: Load immediately when search is accessed, providing instant search capability without dependencies
- Docs Components Background: Load asynchronously after search is ready, ensuring smooth Docs access
- Tour Components On-Demand: Load together when tours start, providing seamless tour experiences
- 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
<!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/[email protected]/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/[email protected]/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: '[email protected]',
},
});
</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/[email protected]/dist/ - unpkg:
https://unpkg.com/@sherpa/[email protected]/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
- ⚡ 90% Smaller Initial Load: Only ~20 kB vs ~280 kB for the main bundle
- 📦 Component-Based Loading: Load only what users need, when they need it
- 🎯 Better Caching: Each component chunk cached separately
- 🏃 Faster TTI: Dramatically improved Time to Interactive
- 🧠 Intelligent Prefetching: Components load based on user interaction patterns
Integration Examples
ES Modules with Code Splitting (Recommended)
<!-- Modern approach with optimal performance -->
<script type="module">
import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/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: '[email protected]',
},
});
</script>For Legacy Browsers (Single Bundle)
<!-- For browsers that don't support ES modules -->
<script>
(function () {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/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: '[email protected]',
},
});
};
document.head.appendChild(script);
})();
</script>Advanced Setup with Preloading
<!-- Preload for better performance -->
<link rel="dns-prefetch" href="//cdn.jsdelivr.net" />
<link
rel="modulepreload"
href="https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/dist/sherpa-sdk.0.0.1.esm.js"
/>
<!-- Load SDK -->
<script type="module">
import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/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: '[email protected]',
},
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):
# Backend API Configuration
VITE_BACKEND_URL=https://api.sherpa.example.com/api
# Development Settings
NODE_ENV=productionVite Integration
For Vite-based projects, use the VITE_ prefix:
# .env
VITE_BACKEND_URL=https://api.sherpa.example.com/apiThe SDK will automatically detect and use this configuration.
Manual Configuration
You can also configure the backend URL programmatically:
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
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:
- Floating Search Bar: A persistent, unobtrusive search button that expands into a full search interface
- Search Modal: A comprehensive search interface with recommendations and results
- Context Modal: A personalization interface for collecting tour context before starting
- Docs Viewer: Draggable, resizable windows for viewing knowledge base content
Search Flow
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 modalEsc: Close current modal or DocsCtrl + 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:
window.Sherpa('boot', {
key: 'your-workspace-key',
// ... other options
});
// Search interface is available but hidden - call showSearch() to display itManual Search Control
// Show search interface
window.Sherpa('showSearch');
// Hide search interface
window.Sherpa('hideSearch');Search Events
Listen for search-related events:
// 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
// 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
// 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
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:
// 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:
: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
// 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 withAccessibility
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-motionsettings
Security
Docss are displayed in sandboxed iframes with restricted permissions:
<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:
- Direct Loading: First attempts to load external URLs directly in the iframe
- CSP Detection: Automatically detects when direct loading is blocked by CSP or cross-origin restrictions
- Proxy Fallback: Falls back to a proxy service (AllOrigins) when direct loading fails
- User Notification: Shows a subtle notification when proxy mode is active
// 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
<!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:
// 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:
// 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:
: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-motionsettings - High Contrast: Sufficient color contrast ratios
Example Implementation
<!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: '[email protected]',
},
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:
<!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/[email protected]/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/[email protected]/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: '[email protected]',
},
});
</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:
<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
npm install @sherpa/clientimport SherpaSDK from '@sherpa/client';
const sdk = new SherpaSDK();
await sdk.boot({
key: 'your-workspace-key',
user: {
id: 'user-123',
name: 'John Doe',
email: '[email protected]',
},
});Quick Start
1. Initialize the SDK
// Using the global Sherpa function (script tag method)
window.Sherpa('boot', {
key: 'your-workspace-key',
user: {
id: 'user-123',
name: 'John Doe',
email: '[email protected]',
},
locale: 'ko',
debug: true,
});2. Start a Tour
window.Sherpa('startTour', 'tour-id', 'User wants to learn how to use the dashboard');3. Track Events
window.Sherpa('track', 'button_clicked', {
button_id: 'save-profile',
section: 'user-settings',
});4. Open Docss
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.
window.Sherpa(
'boot',
{
key: 'workspace-key', // Required: Your workspace key
user: {
// Optional: User information
id: 'user-123',
name: 'John Doe',
email: '[email protected]',
},
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.
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:
<!-- 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-contextendTour()
End the currently active tour.
window.Sherpa('endTour');showSearch() / hideSearch()
Control the floating search interface.
window.Sherpa('showSearch');
window.Sherpa('hideSearch');Docs Methods
Control knowledge base documents programmatically.
// 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.
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:
// No setup needed - SDK auto-detects router
const tourController = TourController.getInstance();
await tourController.startTour('tour-id', 'context');
// Automatically uses SPA navigation if router is detectedFor manual control, use the Universal Router Adapter:
import { UniversalRouterAdapter, TourController } from '@sherpa/client';
const routerAdapter = new UniversalRouterAdapter();
const tourController = TourController.getInstance();
tourController.setRouterAdapter(routerAdapter);React Router Integration (Manual)
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
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
- Tour Start: When
startTour()is called, the SDK compares the current URL with the tour'sbuildUrl - 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
- Parameter Preservation: Tour parameters are stored in
sessionStorageduring navigation - 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:
// 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:
<!-- These work automatically -->
https://yourapp.com?sherpa=tour-id https://yourapp.com/page?sherpa=tour-id:contextEnhanced Navigation Features
🔄 Multiple Navigation Strategies
The SDK automatically tries multiple navigation approaches in order:
- Router Adapter Navigation: Uses configured SPA router (React Router, etc.)
- Auto-Detected SPA Navigation: Automatically detects and uses framework routers
- History API Navigation: Uses browser History API for SPA-like navigation
- 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:
// 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
sessionStorageis 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
buildUrlformat 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
Hot Reloading & CDN Server
The client SDK includes a development server that provides hot reloading and CDN-like serving of the dist folder:
Development Server Features
- Hot Reloading: Automatically rebuilds when source files change
- CDN-like Serving: Serves dist folder with proper CORS headers
- Cache Control: No-cache headers for development
- File Listing: JSON API to list available files
Starting the Development Server
# Start dev server with hot reloading and CDN serving
pnpm dev
# This runs:
# - Vite build in watch mode
# - Express server on port 4100 serving dist folderAccessing the Development CDN
- CDN Server:
http://localhost:4100/ - SDK Files:
http://localhost:4100/dist/[filename] - List Files API:
http://localhost:4100/(returns JSON with file list)
Example Usage
<!-- Load SDK from local CDN server -->
<script type="module">
import { SherpaSDK } from 'http://localhost:4100/dist/sherpa-sdk.0.0.14.esm.min.js';
const sdk = new SherpaSDK();
await sdk.boot({
key: 'your-workspace-key',
user: {
id: 'user-123',
name: 'John Doe',
email: '[email protected]',
},
});
</script>Development Scripts
# Main development command (hot reload + CDN server)
pnpm dev
# Alternative: Old Vite dev server (port 4000)
pnpm dev:old
# Watch and build only
pnpm build:watch
# CDN server only
pnpm serve:cdnThe development server watches for changes in the dist folder and logs updates to the console. Files are served with CORS headers enabled, making it perfect for testing SDK integration across different domains during 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:
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:
// ❌ 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:
- Identify the original method name from the source code
- Add it to the
reservedListinvite.config.ts - 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: [email protected]
Publishing & CDN
For Maintainers
Automated Version Bump & Publish (Recommended)
Use the automated bump-and-publish script for streamlined releases:
# 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-runWhat the script does:
- ✅ Validates git status and shows current branch
- 📝 Bumps version in package.json (semver compliant)
- 🏗️ Builds the project (production or beta build)
- 🔐 Generates CDN integrity hashes
- 📦 Commits version bump to git
- 🚀 Publishes to npm with appropriate tag (
latestorbeta) - 🏷️ Creates and pushes git tag (production only)
- 📊 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:
# 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):
<script type="module">
import { SherpaSDK } from 'https://cdn.jsdelivr.net/npm/@sherpa/[email protected]/dist/sherpa-sdk.0.0.1.esm.js';
const sdk = new SherpaSDK();
await sdk.boot({ key: 'your-workspace-key' });
</script>npm Installation:
