Good morning, Jane 👋
Here's your pipeline at a glance.
Monthly Revenue
$128,400
+14%
Open Deals
23
Pipeline
Total Contacts
1,847
+31
Win Rate
62%
Goal: 70%
Recent Activity
KR
Won
TN
New
SB
Overdue
ML
Report
AP
Export
Quick Actions
Preferences
Dark Mode
Theme follows system
Email Notifications
Deal updates & reminders
Integration Examples
Copy & PasteLoad 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}',
// };