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

```

```
