Dashboard
3
Monthly Revenue
$128,400
+14%
Open Deals
23
Pipeline
Total Contacts
1,847
+31
Win Rate
62%
Goal: 70%

Recent Activity

KR
Kim Reyes closed Acme Corp deal — $42,000
5 minutes ago
Won
TN
Tomas Nguyen added 3 new contacts from webinar
22 minutes ago
New
SB
Follow-up overdue: Bright Solutions proposal
1 hour ago
Overdue
ML
Monthly pipeline report generated
3 hours ago
Report
AP
Alex Park exported Q1 contacts to CSV
Yesterday at 4:32 PM
Export

Quick Actions

Preferences

Dark Mode
Theme follows system

Email Notifications
Deal updates & reminders

Integration Examples

Copy & Paste

Load SUI tokens before speyer-tour.css and the tour inherits dark mode, high contrast, reduced motion, and your full colour system automatically.

<!-- 1. SUI tokens (load first) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-ui@3.5.0/dist/sui-tokens.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-ui@3.5.0/dist/sui-components.min.css">

<!-- 2. Speyer Tour (after SUI) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-tour@3.1.1/dist/speyer-tour.min.css">
<script type="module">
  import { SpeyerTour } from 'https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-tour@3.1.1/dist/speyer-tour.min.js';

  const tour = new SpeyerTour({
    tourId: 'welcome-tour',
    steps: [
      { target: null,         title: 'Welcome!',   content: 'Let\'s take a look around.' },
      { target: '#sidebar',   title: 'Navigation', content: 'All sections here.',    placement: 'right' },
      { target: '#dashboard', title: 'Dashboard',  content: 'Your data lives here.', placement: 'bottom' },
      { target: null,         title: 'All done!',  content: 'You\'re ready to go.' },
    ],
  });
  tour.start(); // Runs once, respects localStorage
</script>

Zero dependencies. The CSS has its own light/dark defaults. Works with Bootstrap, Tailwind, your own stylesheet, or a blank page.

<!-- Just Speyer Tour -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-tour@3.1.1/dist/speyer-tour.min.css">
<script type="module">
  import { SpeyerTour } from 'https://cdn.jsdelivr.net/gh/adrianspeyer/speyer-tour@3.1.1/dist/speyer-tour.min.js';

  const tour = new SpeyerTour({
    tourId:       'onboarding',
    padding:      10,           // px around highlighted element (default: 8)
    tooltipWidth: 340,          // tooltip width in px (default: 320)
    allowClose:   true,         // click dark area to close (default: false)
    steps: [
      { target: '#logo',    title: 'Welcome!', content: 'Here is your app.',  placement: 'bottom' },
      { target: '#nav',     title: 'Navigate', content: 'Sections here.',     placement: 'right' },
      { target: '#actions', title: 'Actions',  content: 'Common tasks here.', placement: 'bottom' },
    ],
  });
  tour.start();
</script>

Hook into every step for analytics, side effects, or triggering UI changes (like opening a menu before the tour highlights something inside it).

const tour = new SpeyerTour({
  tourId: 'onboarding',
  steps: [...],

  onStart: ({ tourId }) =>
    analytics.track('tour_start', { tourId }),

  onStep: ({ tourId, stepIndex, step }) =>
    analytics.track('tour_step', { stepIndex, title: step.title }),

  onComplete: ({ tourId }) =>
    analytics.track('tour_complete', { tourId }),

  onSkip: ({ tourId, stepIndex }) =>
    analytics.track('tour_skip', { at: stepIndex }),
});

// API
tour.start()        // Start (checks localStorage, no-op if done)
tour.start(true)    // Force-start, ignore localStorage
tour.reset()        // Clear flag and restart (silent — no callbacks)
tour.next()         // Advance one step
tour.back()         // Go back one step
tour.close()        // Close now, record as skipped
tour.isActive       // boolean

Pass a labels object to localise all button text and the step counter. Partial overrides are supported — only set what you need.

const tour = new SpeyerTour({
  tourId: 'bienvenue',
  labels: {
    skip:   'Passer',
    back:   'Retour',
    next:   'Suivant',
    finish: 'Terminer',
    stepOf: '{current} sur {total}',
  },
  steps: [
    { target: null,       title: 'Bienvenue !', content: 'Faisons un tour rapide.' },
    { target: '#sidebar', title: 'Navigation',  content: 'Toutes les sections.', placement: 'right' },
    { target: null,       title: 'C\'est fini', content: 'Vous êtes prêt !' },
  ],
});

// Default labels (English):
// SpeyerTour.DEFAULT_LABELS = {
//   skip:   'Skip tour',
//   back:   'Back',
//   next:   'Next',
//   finish: 'Finish',
//   stepOf: '{current} / {total}',
// };