GuidesWriting Tours

Writing Tours

A Trailguide tour is a plain TypeScript/JSON object. It lives in your codebase, ships with your deployments, and gets reviewed in pull requests.

Tour structure

import type { Trail } from '@trailguide/core'
 
const tour: Trail = {
  id: 'onboarding',        // unique identifier
  title: 'Get started',    // used in analytics
  version: '1.0.0',        // bump when steps change significantly
  theme: {                 // optional: per-trail CSS custom property overrides
    '--trailguide-accent': '#6366f1',
    '--trailguide-radius': '12px',
  },
  steps: [/* ... */],
}

id

A stable unique string. Used as the key for analytics events and for tourStorage to track completion. If you change id all users will see the tour again.

version

Not enforced by the SDK — use it as a convention to track which version of a tour a user has seen, e.g. by storing it alongside the completion flag in your own backend.

theme

An optional map of CSS custom property overrides applied to this trail at runtime. Useful when you want different trails to use different brand colors without touching global CSS.

theme: {
  '--trailguide-accent': '#6366f1',
  '--trailguide-accent-hover': '#4f46e5',
  '--trailguide-radius': '12px',
},

Any variable from the full variable reference can be overridden here. The Pro Editor includes a live theme preview that applies these values in real time.


Step structure

import type { Step } from '@trailguide/core'
 
const step: Step = {
  id: 'step-dashboard',             // unique within the tour
  target: '[data-tour="dashboard"]', // CSS selector for the highlighted element
  placement: 'bottom',               // tooltip position
  title: 'Your dashboard',           // tooltip heading
  content: 'All your work in one place.', // tooltip body text
  optional: false,                   // if true, silently skip if target not found
}

placement

Controls which side of the target the tooltip appears on. Trailguide uses @floating-ui/dom under the hood, so it will flip and shift automatically to stay in viewport.

ValueDescription
'top'Above the target
'bottom'Below the target
'left'Left of the target
'right'Right of the target

optional

When optional: true, if the target element is not found or is not visible, the step is silently skipped instead of showing an error tooltip. Useful for steps that point to elements that only appear in certain states.

{
  id: 'step-pro-badge',
  target: '[data-tour="pro-badge"]',
  placement: 'left',
  title: 'Pro features',
  content: 'Upgrade to unlock these features.',
  optional: true, // skipped for free users who don't have the badge
}

Organizing tours

For small apps, a single tours.ts file works fine. For larger apps, consider co-locating tours with the pages they document:

app/
  dashboard/
    page.tsx
    page.tour.ts   ← tour for this page
  settings/
    page.tsx
    page.tour.ts

Or a shared lib/tours/ directory:

lib/
  tours/
    onboarding.ts
    settings.ts
    analytics.ts
    index.ts        ← re-exports all tours

Trail modes

Every trail has an optional mode field:

const tour: Trail = {
  id: 'onboarding',
  title: 'Get started',
  version: '1.0.0',
  mode: 'both',   // 'tour' | 'test' | 'both'
  steps: [/* ... */],
}
ModeBehavior
'tour'Shows onboarding tooltips to users. This is the default if mode is omitted.
'test'Runs as a Playwright test only. No tooltip UI is shown.
'both'Shows tooltips to users and runs as a Playwright CI test from the same file.

Steps can include action, value, and assert fields for test execution:

{
  id: 'step-create',
  target: '[data-trail-id="create-btn"]',
  placement: 'bottom',
  title: 'Create a project',
  content: 'Click here to get started.',
  action: 'click',
  assert: { type: 'visible' },
}

See the Playwright guide for full setup instructions.


Step types

Every step has a stepType field that controls what UI it renders. The default is element (a tooltip anchored to a page element). All other types are full-screen overlays.

stepTypeDescription
'element'Tooltip anchored to a target element. Default.
'announcement'Full-screen modal with headline, body, optional image, badge, and up to two buttons.
'checklist'Interactive task list. Users check off items before continuing. Supports required vs optional tasks and per-task navigation URLs.
'celebration'Confetti moment. Shows a congratulations card with an emoji, message, and CTA button.
'feedback'In-tour feedback form. Supports stars, thumbs up/down, or NPS (0-10). Optional free-text comment. POSTs the response to a webhook URL you configure.
'redirect'Navigates the user to another URL mid-tour with an optional delay and message overlay. Use it to chain onboarding flows across pages.
'delay'Silent pause. No UI is shown. The tour waits for the configured number of milliseconds before advancing. Useful before navigations or animations settle.
// Announcement step
{
  id: 'announce-feature',
  stepType: 'announcement',
  title: 'Meet the new dashboard',
  content: 'We rebuilt it from scratch. Here is what changed.',
  announcement: {
    badge: 'NEW',
    imageUrl: 'https://cdn.example.com/dashboard-preview.png',
    primaryCta: 'Show me',
    secondaryCta: 'Maybe later',
  },
}
 
// Celebration step
{
  id: 'onboarding-complete',
  stepType: 'celebration',
  title: 'You did it!',
  content: 'Your first project is live.',
  celebration: {
    emoji: '🎉',
    showConfetti: true,
    ctaLabel: 'Go to dashboard',
  },
}
 
// Feedback step
{
  id: 'rate-experience',
  stepType: 'feedback',
  title: 'How did we do?',
  feedback: {
    type: 'stars',
    question: 'How would you rate your onboarding experience?',
    allowComment: true,
    commentPlaceholder: 'Any other thoughts?',
    webhook: 'https://your-api.com/feedback',
    ctaLabel: 'Submit',
  },
}
 
// Checklist step
{
  id: 'getting-started',
  stepType: 'checklist',
  title: 'Get set up',
  checklist: {
    items: [
      { id: 'item-1', label: 'Connect your data source', url: '/settings/data', required: true },
      { id: 'item-2', label: 'Invite your team', url: '/settings/team', required: false },
    ],
    ctaLabel: 'Done',
    allowSkip: false,
  },
}

In the Pro Editor, all step types appear in the drag-and-drop toolbar. Drop any type into any position in the flow. The step editor adapts to show the relevant configuration fields for the selected type.


Versioning strategy

Tours are just data. Treat them like any other content in your codebase:

  • Commit tour changes in the same PR as the feature they document
  • Review tour copy in code review alongside the UI changes
  • Use the version field to communicate breaking changes
  • Export tour JSON for use with Trailguide Pro’s visual editor.

Tip: Keep step id values stable. They are used as the primary key in analytics reports — changing an id breaks historical step-level metrics.