npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

@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.

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

  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
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

# 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:

// 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:

  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

<!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

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)

<!-- 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=production

Vite Integration

For Vite-based projects, use the VITE_ prefix:

# .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:

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:

  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

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:

window.Sherpa('boot', {
  key: 'your-workspace-key',
  // ... other options
});
// Search interface is available but hidden - call showSearch() to display it

Manual 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 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:

<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
// 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-motion settings
  • 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/client
import 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-context

endTour()

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 detected

For 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

  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:

// 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: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:

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

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 folder

Accessing 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:cdn

The 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:

  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: [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-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:

# 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: