Create a tour

Learn how to create a tour in your Nuxt project using the nuxt-tour module.

Add the component

Add <VTour /> to your page and pass an array of steps:

vue

app.vue

<template>
  <div>
    <h1 id="welcome">Welcome</h1>
    <button class="cta">Get started</button>
    <footer data-step="contact">Contact us</footer>

    <VTour :steps="steps" />
  </div>
</template>

<script lang="ts" setup>
  import type { TourStep } from "#nuxt-tour/types";

  const steps: TourStep[] = [
    {
      target: "#welcome",
      title: "Welcome to the app",
      body: "This is your dashboard. Let us show you around.",
    },
    {
      target: ".cta",
      title: "Get started",
      body: "Click here whenever you are ready.",
      popperConfig: { placement: "bottom" },
    },
    {
      target: '[data-step="contact"]',
      title: "Need help?",
      body: "Reach out to us any time.",
    },
  ];
</script>
Limitations
  • The target prop must be a valid CSS selector, a reactive ref, or a direct HTMLElement.
  • The target element must already be in the DOM before the tour starts.
  • If a target cannot be found, the tooltip is centred on the screen instead.

Starting the tour

Three ways to start a tour:

Auto-start on mount

Pass the auto-start prop and the tour begins as soon as the component mounts:

<template>
  <VTour auto-start :steps="steps" />
</template>

Add start-delay (ms) to wait before showing the first step:

<template>
  <VTour auto-start :start-delay="500" :steps="steps" />
</template>

Manual start via template ref

<template>
  <button @click="tour?.startTour()">Start tour</button>
  <VTour ref="tour" :steps="steps" />
</template>

<script lang="ts" setup>
  import { VTour } from "#components";

  const tour = useTemplateRef<InstanceType<typeof VTour>>("tour");
</script>

Start via the composable

useTour lets you control any named tour from any component — even before <VTour /> has mounted:

<template>
  <button @click="start()">Start tour</button>
  <VTour name="onboarding" :steps="steps" />
</template>

<script lang="ts" setup>
  const { start, isPlayed, reset } = useTour("onboarding");
</script>

If start() is called before the component mounts it is queued and fires automatically once the component is ready.

Controlling localStorage

Use the save-to-local-storage prop to choose how progress is persisted:

'end'default
Save only when the tour is fully completed.
'step'
Save after every step — user can close the browser and resume later.
'never'
Never save — the tour shows on every page load. Useful for demos and dev environments.
<template>
  <VTour save-to-local-storage="step" :steps="steps" />
</template>

TTL — re-show after N days

<template>
  <!-- Show the tour again after 30 days -->
  <VTour :ttl="30" :steps="steps" />
</template>

Version-based reset

Bump storageVersion in your nuxt.config to force all users to see the tour again:

ts

nuxt.config.ts

export default defineNuxtConfig({
  tour: { storageVersion: "v2" },
});

Multiple tours

Each <VTour /> with a unique name prop is tracked independently in localStorage:

<template>
  <VTour name="onboarding" :steps="onboardingSteps" />
  <VTour name="feature-x" :steps="featureSteps" />
</template>

Control each tour from anywhere via the composable:

const onboarding = useTour("onboarding");
const featureX = useTour("feature-x");

onboarding.reset();       // clear storage and restart
featureX.markUnplayed();  // mark as not played without restarting