{"_id":"@capsbharg/sparkguide-js","_rev":"2-6531aa033cc61e0c190d3a2a0cc02506","name":"@capsbharg/sparkguide-js","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@capsbharg/sparkguide-js","version":"1.0.0","keywords":["sparkguide","sparkguide-js","onboarding","user-onboarding","in-app-onboarding","customer-onboarding","saas-onboarding","onboarding-flow","onboarding-library","onboarding-toolkit","product-tour","product-tours","guided-tour","guided-tours","feature-tour","feature-adoption","feature-discovery","feature-announcement","user-activation","user-engagement","user-guide","walkthrough","walkthroughs","step-by-step-guide","tour","tours","tooltip","tooltips","hotspot","hotspots","spotlight","coach-marks","coachmarks","modal","modals","popover","popovers","banner","banners","announcement","checklist","checklists","progress-checklist","getting-started-checklist","segmentation","user-segmentation","targeting","event-tracking","analytics-events","localstorage","persistence","ui-widget","ui-components","vanilla-js","vanilla-javascript","javascript","typescript","no-dependencies","zero-dependencies","dependency-free","lightweight","small-bundle","framework-agnostic","browser-library","dom","spa","single-page-application","web-app","webapp","saas","saas-tools","developer-tools","open-source","mit-license"],"license":"MIT","_id":"@capsbharg/sparkguide-js@1.0.0","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"dist":{"shasum":"6ca033b6ec6317528ff56803d375fa56f46340fb","tarball":"https://registry.npmjs.org/@capsbharg/sparkguide-js/-/sparkguide-js-1.0.0.tgz","fileCount":10,"integrity":"sha512-r2Or9//dvvSKOXSDNJZozRbQDpQswMh0TeHihPQs+oo7pumxQuS3Ziggp2M3uLJ3qwKi3Uc6SlyUst6hAkuv2Q==","signatures":[{"sig":"MEYCIQDXGvC4Czw/qheXBEMEJwlYfavF/2UzUMg0tPXTIyegOAIhANOT8scNnLvVh+xwnuSWRwZ5F7Dhq34IntvwFa14TAFs","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":407994},"main":"dist/index.js","types":"dist/index.d.ts","unpkg":"dist/iife/index.js","module":"dist/esm/index.js","browser":"dist/iife/index.js","engines":{"node":">=16"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"scripts":{"dev":"tsup src/index.js --format esm --watch --out-dir dist","build":"tsup src/index.js --format esm,cjs,iife --global-name SparkGuide --dts --minify --sourcemap --out-dir dist --legacy-output","prepublishOnly":"npm run build"},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"_npmVersion":"10.7.0","description":"Lightweight, framework-agnostic in-app onboarding toolkit: product tours, tooltips, hotspots, checklists, modals and banners — pure JavaScript, no dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"22.2.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/sparkguide-js_1.0.0_1787380099419_0.8482936581532086","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@capsbharg/sparkguide-js","version":"1.0.1","description":"Lightweight, framework-agnostic in-app onboarding toolkit: product tours, tooltips, hotspots, checklists, modals and banners — pure JavaScript, no dependencies.","main":"dist/index.js","module":"dist/esm/index.js","unpkg":"dist/iife/index.js","browser":"dist/iife/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"tsup src/index.js --format esm,cjs,iife --global-name SparkGuide --dts --minify --sourcemap --out-dir dist --legacy-output","dev":"tsup src/index.js --format esm --watch --out-dir dist","prepublishOnly":"npm run build","site:build":"npm run build && node scripts/build-site.js","site:preview":"npm run site:build && npx --yes serve _site"},"keywords":["sparkguide","sparkguide-js","onboarding","user-onboarding","in-app-onboarding","customer-onboarding","saas-onboarding","onboarding-flow","onboarding-library","onboarding-toolkit","product-tour","product-tours","guided-tour","guided-tours","feature-tour","feature-adoption","feature-discovery","feature-announcement","user-activation","user-engagement","user-guide","walkthrough","walkthroughs","step-by-step-guide","tour","tours","tooltip","tooltips","hotspot","hotspots","spotlight","coach-marks","coachmarks","modal","modals","popover","popovers","banner","banners","announcement","checklist","checklists","progress-checklist","getting-started-checklist","segmentation","user-segmentation","targeting","event-tracking","analytics-events","localstorage","persistence","ui-widget","ui-components","vanilla-js","vanilla-javascript","javascript","typescript","no-dependencies","zero-dependencies","dependency-free","lightweight","small-bundle","framework-agnostic","browser-library","dom","spa","single-page-application","web-app","webapp","saas","saas-tools","developer-tools","open-source","mit-license"],"license":"MIT","author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"repository":{"type":"git","url":"git+https://github.com/Capsbharg/sparkguide-js.git"},"bugs":{"url":"https://github.com/Capsbharg/sparkguide-js/issues"},"homepage":"https://capsbharg.github.io/sparkguide-js/","devDependencies":{"tsup":"^8.5.1","typescript":"^5.9.3"},"engines":{"node":">=16"},"_id":"@capsbharg/sparkguide-js@1.0.1","gitHead":"8283f6fcc47d143947b7ab7d42715af3ca9fa9eb","_nodeVersion":"22.2.0","_npmVersion":"10.7.0","dist":{"integrity":"sha512-C86aIrrtU4AA1ZEfiuAXbuAvKEBBwqsvVa0qHy8zZp4SLOSpIw/dNHEF+AdI8WaoCq9Hw88bHSAfY3NNycJxeA==","shasum":"956fe49ccf716398b29e4dc30228e50a570734e0","tarball":"https://registry.npmjs.org/@capsbharg/sparkguide-js/-/sparkguide-js-1.0.1.tgz","fileCount":10,"unpackedSize":410812,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC7ME9lefy0CZ6XHTpxTQkK4WyidFp93k1z+Mmq3nDs+wIhAJVNMdUWNqh9OY3QXZlMLt24CEfeoTeh9ifot+7LwbHe"}]},"_npmUser":{"name":"capsbharg-2026","email":"capsbharg@gmail.com"},"directories":{},"maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sparkguide-js_1.0.1_1787381607654_0.1166428720159629"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-22T06:28:19.252Z","modified":"2026-08-22T06:53:27.993Z","1.0.0":"2026-08-22T06:28:19.611Z","1.0.1":"2026-08-22T06:53:27.842Z"},"license":"MIT","keywords":["sparkguide","sparkguide-js","onboarding","user-onboarding","in-app-onboarding","customer-onboarding","saas-onboarding","onboarding-flow","onboarding-library","onboarding-toolkit","product-tour","product-tours","guided-tour","guided-tours","feature-tour","feature-adoption","feature-discovery","feature-announcement","user-activation","user-engagement","user-guide","walkthrough","walkthroughs","step-by-step-guide","tour","tours","tooltip","tooltips","hotspot","hotspots","spotlight","coach-marks","coachmarks","modal","modals","popover","popovers","banner","banners","announcement","checklist","checklists","progress-checklist","getting-started-checklist","segmentation","user-segmentation","targeting","event-tracking","analytics-events","localstorage","persistence","ui-widget","ui-components","vanilla-js","vanilla-javascript","javascript","typescript","no-dependencies","zero-dependencies","dependency-free","lightweight","small-bundle","framework-agnostic","browser-library","dom","spa","single-page-application","web-app","webapp","saas","saas-tools","developer-tools","open-source","mit-license"],"description":"Lightweight, framework-agnostic in-app onboarding toolkit: product tours, tooltips, hotspots, checklists, modals and banners — pure JavaScript, no dependencies.","maintainers":[{"name":"capsbharg-2026","email":"capsbharg@gmail.com"}],"readme":"# ✨ SparkGuide\n\n**Product tours, tooltips, hotspots, checklists, modals, and banners — in\npure JavaScript, with zero dependencies.**\n\nSparkGuide is a small, framework-agnostic toolkit for building in-app user\nonboarding: the kind of guided tours, spotlight tooltips, and progress\nchecklists that help new users find their way around a product. Drop it into\nany web app — React, Vue, Svelte, a server-rendered app, or no framework at\nall — with a single import and no build-step requirement.\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](#license)\n[![Dependencies: none](https://img.shields.io/badge/dependencies-none-brightgreen.svg)](#install)\n[![Bundle size](https://img.shields.io/badge/gzipped-~7.4kb-informational.svg)](#build)\n\n**📖 [Documentation](https://capsbharg.github.io/sparkguide-js/) · 🎮 [Live Demo](https://capsbharg.github.io/sparkguide-js/demo.html) · 💻 [Source on GitHub](https://github.com/Capsbharg/sparkguide-js)**\n\n> These links go live once this repo is pushed to `github.com/Capsbharg/sparkguide-js`\n> with GitHub Pages enabled (**Settings → Pages → Source: GitHub Actions**).\n> Until then, run `npm run site:preview` to try the docs site and demo locally\n> — see [Documentation site](#documentation-site) below.\n\n---\n\n## Why SparkGuide?\n\n- **🪶 Tiny and dependency-free.** ~7.4 KB gzipped. No React, no Vue, no\n  runtime dependencies at all — just DOM APIs.\n- **🧩 Framework-agnostic.** Works anywhere JavaScript runs in a browser.\n  Ships ESM, CommonJS, and an IIFE build for plain `<script>` tags.\n- **🕸️ SPA-safe.** Targets are resolved with a `MutationObserver`, so it's\n  safe to point a step at an element that hasn't rendered yet — and if that\n  element later disappears (a route change unmounts it, say), the step is\n  skipped automatically instead of breaking.\n- **🎯 Built-in segmentation.** Target a flow at a URL pattern, a piece of\n  page state, or arbitrary user attributes (plan, role, whatever you track)\n  — no separate targeting engine needed.\n- **💾 Persistence out of the box.** Progress is saved to `localStorage`\n  automatically. A user who reloads mid-tour resumes exactly where they left\n  off; a completed or dismissed tour doesn't come back uninvited.\n- **🎨 Themeable in one object.** Colors, radius, font, and z-index are all\n  configurable — no CSS file to import or override.\n- **📖 100% open source, MIT licensed.** Free to use, modify, and ship in\n  your own product.\n\n---\n\n## Table of contents\n\n- [Install](#install)\n- [Quick start](#quick-start)\n- [Feature guide](#feature-guide)\n  - [Product tours (flows)](#-product-tours-flows)\n  - [Step types: tooltip, hotspot, modal](#-step-types-tooltip-hotspot-modal)\n  - [Standalone modals](#-standalone-modals)\n  - [Standalone hotspots](#-standalone-hotspots)\n  - [Banners](#-banners)\n  - [Checklists](#-checklists)\n  - [Segmentation & targeting](#-segmentation--targeting)\n  - [Events](#-events)\n  - [Theming](#-theming)\n  - [Persistence & replaying tours](#-persistence--replaying-tours)\n- [Full API reference](#full-api-reference)\n- [Try the demo](#try-the-demo)\n- [Documentation site](#documentation-site)\n- [Project layout](#project-layout)\n- [Build](#build)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Install\n\n```bash\nnpm install @capsbharg/sparkguide-js\n```\n\nOr drop it straight into a page with no build step at all:\n\n```html\n<script src=\"https://unpkg.com/@capsbharg/sparkguide-js/dist/iife/index.js\"></script>\n<script>\n  const guide = new SparkGuide.SparkGuide({ theme: { primaryColor: '#4f46e5' } });\n</script>\n```\n\n## Quick start\n\n```js\nimport { SparkGuide } from '@capsbharg/sparkguide-js';\n\nconst guide = new SparkGuide({\n  theme: { primaryColor: '#4f46e5' },   // optional branding\n  storageKey: 'myapp_onboarding',       // localStorage namespace\n  user: { plan: 'pro' }                 // used for segment targeting\n});\n\nguide.addFlow('welcome-tour', {\n  segment: { user: { plan: ['pro', 'trial'] } }, // optional targeting\n  steps: [\n    { type: 'modal', title: 'Welcome 👋', content: 'Let’s take a quick tour.' },\n    {\n      target: '#dashboard-nav',\n      title: 'Your dashboard',\n      content: 'Everything starts here.',\n      placement: 'bottom'\n    },\n    {\n      target: '.create-project-btn',\n      title: 'Create a project',\n      content: 'Click here to get started.',\n      placement: 'top',\n      advanceOn: 'click'   // auto-advances when the user clicks the target\n    }\n  ]\n});\n\nguide.start('welcome-tour');\n\nguide.on('flow:complete', (flowId) => trackEvent('onboarding_complete', flowId));\nguide.on('flow:dismiss', (flowId) => trackEvent('onboarding_dismissed', flowId));\n```\n\nProgress is persisted to `localStorage` automatically — a completed or\ndismissed flow won't be shown again, and an in-progress flow resumes exactly\nwhere the user left off.\n\n---\n\n## Feature guide\n\n### 🚶 Product tours (flows)\n\nA **flow** is an ordered sequence of steps — the thing most people mean by\n\"product tour.\" Register one with `addFlow`, then start it.\n\n```js\nguide.addFlow('reports-tour', {\n  steps: [\n    { type: 'modal', title: 'New: Reports', content: 'Here’s what changed.' },\n    { target: '#reports-table', content: 'Your saved reports now live here.' }\n  ]\n});\n\nguide.start('reports-tour');                    // start (or resume) it\nguide.start('reports-tour', { resume: false });  // always replay from step 0\nguide.startMatching();                           // start every flow whose\n                                                  // segment matches — great\n                                                  // for a page-load hook\nguide.dismiss('reports-tour');                   // close it early\nguide.resetFlow('reports-tour');                 // clear its saved progress\n```\n\n`startMatching()` is the method most apps call once on page load: it walks\nevery registered flow, checks its `segment` rule against the current user,\nand shows the first one that matches and hasn't already been seen. If more\nthan one flow matches, they run **one at a time** — each is awaited until\nit's completed or dismissed before the next one starts, so you never get two\ntours' overlays stacked on top of each other.\n\n### 🖱️ Step types: tooltip, hotspot, modal\n\nEach step in a flow renders one of three components. The type is inferred\nfrom the step's shape unless you set `type` explicitly:\n\n| step looks like | renders as |\n|---|---|\n| has a `target`, no `type` | **Tooltip** — spotlight overlay + positioned card |\n| `type: 'hotspot'` | **Hotspot** — a pulsing dot; click it to reveal the content |\n| `type: 'modal'`, or no `target` | **Modal** — centered dialog, not anchored to anything |\n\n```js\n{\n  type: 'tooltip' | 'hotspot' | 'modal', // default: tooltip if `target` set, else modal\n  target: '#css-selector',               // omit for modal steps\n  title: 'string',\n  content: 'string',\n  placement: 'top' | 'bottom' | 'left' | 'right', // default 'bottom'\n  advanceOn: 'click',                    // optional: auto-advance when the target is clicked\n  showOverlay: true                      // tooltip-only: set false to skip the dimmed backdrop\n}\n```\n\n**Tooltips** dim the rest of the page and cut out a \"spotlight\" around the\ntarget, with Back/Next (or Finish, on the last step) buttons.\n\n**Hotspots** are non-blocking — no dimmed backdrop, just a small pulsing\nindicator. Clicking it opens a popover with the content and, inside a flow,\nthe same Back/Next navigation as a tooltip.\n\n**Modals** are centered dialogs, ideal for a flow's opening \"Welcome\" screen\nsince they don't need to anchor to any element on the page.\n\nAll three auto-track the target's position on scroll/resize, and — since\ntargets are resolved asynchronously — a step whose target never appears (or\ndisappears mid-step, e.g. an SPA route change) is skipped automatically\nrather than getting the tour stuck.\n\n### 🪟 Standalone modals\n\nNot every dialog needs to be part of a multi-step flow:\n\n```js\nguide.showModal({\n  title: 'Heads up',\n  content: 'Your trial ends in 3 days.',\n  primaryLabel: 'Got it',\n  secondaryLabel: 'Remind me later',\n  onPrimary: () => trackEvent('trial_notice_ack'),\n  onSecondary: () => scheduleReminder()\n});\n```\n\n`onPrimary`/`onSecondary`/`onClose` are all optional — every control on the\nmodal (the X, clicking outside, and both buttons) closes it regardless of\nwhether you pass a callback.\n\n### 📍 Standalone hotspots\n\nFor a lightweight \"psst, try this\" nudge outside of any flow:\n\n```js\nguide.showHotspot({\n  target: '#new-feature-icon',   // a selector (waits for it to appear) or an Element\n  title: 'New: Dark mode',\n  content: 'Toggle it from here.',\n  placement: 'right'\n});\n```\n\n### 📣 Banners\n\nA persistent top-of-page bar for announcements:\n\n```js\nguide.showBanner({\n  content: 'New: Roadmap & feature requests are here.',\n  actionLabel: 'See what shipped',\n  onAction: () => (window.location.href = '/changelog'),\n  onClose: () => trackEvent('banner_dismissed')\n});\n```\n\nCalling `showBanner` again replaces the current banner with a new one.\n\n### ✅ Checklists\n\nA floating \"getting started\" checklist with a progress bar. Items can be\nchecked off by the user, or completed programmatically from your own app\ncode in response to a real action:\n\n```js\nguide.addChecklist('getting-started', {\n  title: 'Getting started',\n  items: [\n    { id: 'invite', label: 'Invite your team' },\n    { id: 'project', label: 'Create your first project' },\n    { id: 'integration', label: 'Connect an integration' }\n  ]\n});\n\n// later, wherever the real action happens in your app:\ncreateProjectButton.addEventListener('click', () => {\n  guide.completeChecklistItem('getting-started', 'project');\n});\n```\n\nThe checklist minimizes to a small floating button and remembers which items\nare done across reloads. `checklist:complete` fires once, the moment the\nlast item is checked — not again if an item is later unchecked and rechecked.\n\n### 🎯 Segmentation & targeting\n\nAny flow's `segment` option decides who sees it. All rules given are AND'd\ntogether:\n\n```js\nguide.addFlow('admin-only-tour', {\n  segment: {\n    urlMatches: 'contains:/dashboard',   // or 'equals:/app', or a RegExp\n    elementExists: '#admin-panel',       // only if this element is on the page\n    user: { role: 'admin', plan: ['pro', 'enterprise'] } // value or array of allowed values\n  },\n  steps: [ /* ... */ ]\n});\n```\n\nTell SparkGuide who the current user is with `identify()` (merges into\nwhatever you passed at construction time), and re-check segments any time:\n\n```js\nguide.identify({ plan: 'pro' });   // e.g. right after an upgrade\nguide.startMatching();             // re-evaluate and show anything newly unlocked\n```\n\nYou can also call the matcher directly — handy for building your own\n\"would this flow show right now?\" debug panel:\n\n```js\nimport { Targeting } from '@capsbharg/sparkguide-js';\n\nTargeting.matches(\n  { user: { plan: 'free' }, elementExists: '#upgrade-banner' },\n  { user: { plan: 'free', role: 'member' } }\n); // => true\n```\n\n### 📡 Events\n\nSubscribe with `guide.on(event, handler)` (returns an unsubscribe function).\n\n| event | fires when |\n|---|---|\n| `flow:start` | a flow begins |\n| `flow:complete` | a flow finishes its last step |\n| `flow:dismiss` | a flow is closed early |\n| `step:show` | a step renders — `(flowId, stepIndex, step)` |\n| `step:complete` | a step is passed — `(flowId, stepIndex, step)` |\n| `checklist:item` | a checklist item is toggled — `(checklistId, itemId, done)` |\n| `checklist:complete` | every item in a checklist is done |\n\n```js\nguide.on('step:show', (flowId, index, step) => {\n  analytics.track('onboarding_step_viewed', { flowId, index });\n});\n```\n\n### 🎨 Theming\n\nPass a `theme` object at construction — everything is exposed as a CSS\ncustom property under the hood, so no separate stylesheet is ever needed:\n\n```js\nnew SparkGuide({\n  theme: {\n    primaryColor: '#4f46e5',     // buttons, progress bars, the hotspot dot\n    textColor: '#1f2933',\n    backgroundColor: '#ffffff',\n    overlayColor: 'rgba(15, 23, 42, 0.55)',\n    borderRadius: '10px',\n    fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n    zIndex: 999999\n  }\n});\n```\n\nCreating a second `SparkGuide` instance with a different theme (e.g. after a\nuser switches workspaces) updates the shared stylesheet in place — the\nnewest theme always wins.\n\n### 💾 Persistence & replaying tours\n\nProgress lives in `localStorage`, namespaced by `storageKey`, so it's safe to\nrun multiple independent guides (e.g. one per logged-in account) side by\nside on the same origin.\n\n- **`resume: true`** (the default, used by `start()` and `startMatching()`)\n  skips a flow that's already been completed *or* dismissed — closing a tour\n  early means \"don't show me this again,\" not \"ask me later.\"\n- **`resume: false`** is an explicit \"run this now\" — it always replays the\n  flow from step 0, regardless of history. Use it for a \"Replay tour\" button\n  in a help menu.\n- **`resetFlow(id)`** clears a flow's saved state entirely, as if the user\n  had never seen it — useful for a \"reset my onboarding\" debug action.\n\n---\n\n## Full API reference\n\n### `new SparkGuide(config)`\n\n| option | type | description |\n|---|---|---|\n| `theme` | object | see [Theming](#-theming) |\n| `storageKey` | string | `localStorage` namespace, default `\"sparkguide\"` |\n| `user` | object | arbitrary attributes used by `segment` targeting rules |\n\n### Instance methods\n\n```js\nguide.on(event, handler)              // subscribe; returns an unsubscribe fn\nguide.off(event, handler)\nguide.identify(user)                  // merge new attributes into the current user\n\nguide.addFlow(id, { steps, segment })\nguide.start(id, { resume: true })\nguide.startMatching()\nguide.dismiss(id)\nguide.resetFlow(id)\n\nguide.addChecklist(id, { title, items })\nguide.completeChecklistItem(checklistId, itemId)\n\nguide.showBanner(opts)\nguide.showModal(opts)\nguide.showHotspot(opts)               // async — target may be a selector\n\nguide.destroy()                       // remove all rendered UI (keeps saved progress)\n```\n\n### Named exports\n\nBesides the default `SparkGuide` class, the package also exports its\nbuilding blocks for advanced use — building a custom step type, writing your\nown targeting rule, etc.:\n\n```js\nimport {\n  SparkGuide, Guide, EventBus, ProgressStore, Targeting,\n  Tooltip, Hotspot, Modal, Banner, Checklist, ElementFinder\n} from '@capsbharg/sparkguide-js';\n```\n\n---\n\n## Try the demo\n\n**🎮 [Try it live](https://capsbharg.github.io/sparkguide-js/demo.html)** — no\ninstall required (live once Pages is enabled, see [Documentation site](#documentation-site)).\n\nA full mock \"Acme\" SaaS app that exercises every feature is included in\n[`demo/`](demo/). It lets you switch between four sample personas (varying by\nplan and role) and four accent-color themes, and shows a live event log plus\na \"targeting sandbox\" that evaluates real segmentation rules against\nwhichever persona is selected.\n\nTo run it locally instead:\n\n```bash\nnpm install\nnpm run build\nnpx serve .           # any static file server works — the demo uses ES module imports\n```\n\nThen open `http://localhost:3000/demo/index.html` (or whatever port `serve` prints).\n\n## Documentation site\n\nThe [`docs/`](docs/) folder is a small, dependency-free static site — a\nhome page, Getting Started, the full Feature Guide, API Reference, and a\npage embedding the live demo — with per-page SEO metadata (titles,\ndescriptions, Open Graph tags, JSON-LD, `sitemap.xml`, `robots.txt`).\n\nPreview it locally exactly as it deploys (this assembles `docs/`, `demo/`,\nand a fresh `dist/` build into `_site/` and serves it):\n\n```bash\nnpm run site:preview\n```\n\nIt deploys automatically via [`.github/workflows/deploy-docs.yml`](.github/workflows/deploy-docs.yml)\non every push to `master`/`main` that touches the site, publishing to\n`https://capsbharg.github.io/sparkguide-js/` (the Pages URL for\n[github.com/Capsbharg/sparkguide-js](https://github.com/Capsbharg/sparkguide-js)).\nTo enable it:\n\n1. Push this repo to `github.com/Capsbharg/sparkguide-js`.\n2. In **Settings → Pages**, set **Source** to **GitHub Actions**.\n\nIf you fork this to a different org/repo (or use a custom domain), update the\ncanonical/OG URLs in `docs/*.html`, `docs/sitemap.xml`, and `docs/robots.txt`\nto match.\n\n## Project layout\n\n```\nsrc/\n  core/          Guide (flow orchestrator), EventBus, ElementFinder\n  components/    Tooltip, Modal, Hotspot, Banner, Checklist\n  positioning/   PositionEngine (placement + viewport collision)\n  storage/       ProgressStore (localStorage persistence)\n  segmentation/  Targeting (segment/rule matching)\n  styles/        theme.js (injected CSS, all class names prefixed `sg-`)\ndemo/\n  index.html     Mock \"Acme\" SaaS app exercising every feature\n  data.js        Sample personas/projects/team used to drive the demo's segmentation\ndocs/\n  index.html, getting-started.html, guide.html, api.html, demo.html\n                 The documentation site (see \"Documentation site\" above)\n  sitemap.xml, robots.txt, 404.html\nscripts/\n  build-site.js  Assembles docs/ + demo/ + dist/ into _site/ for Pages\n.github/workflows/\n  deploy-docs.yml  Builds and deploys the docs site to GitHub Pages\n```\n\n## Build\n\n```bash\nnpm install\nnpm run build   # outputs dist/index.js (cjs), dist/esm/index.js, dist/iife/index.js, .d.ts\nnpm run dev     # watch mode, ESM only\n```\n\n## Contributing\n\nIssues and pull requests are welcome at\n[github.com/Capsbharg/sparkguide-js](https://github.com/Capsbharg/sparkguide-js).\nA few ideas that would make good first contributions:\n\n- An in-app survey / NPS widget\n- A resource center (searchable help hub widget)\n- Additional `placement` collision strategies in `PositionEngine`\n\n## License\n\nMIT — free to use, modify, and ship in your own project, commercial or\notherwise.\n","readmeFilename":"README.md","homepage":"https://capsbharg.github.io/sparkguide-js/","repository":{"type":"git","url":"git+https://github.com/Capsbharg/sparkguide-js.git"},"author":{"name":"CapsBharg","email":"capsbharg@gmail.com"},"bugs":{"url":"https://github.com/Capsbharg/sparkguide-js/issues"}}