Vue guide
Install the app-scoped runtime and use typed definitions in plain Vue.
Use Nuxt Tour in plain Vue
Create a definition in src/tours/onboarding.ts:
import { defineTour } from '@lupinum/nuxt-tour/vue'
export default defineTour({
id: 'onboarding',
steps: [{
id: 'create-project',
target: 'create-project',
title: 'Create a project',
content: 'Start your first project here.',
interaction: 'target',
}],
})Install that definition and the theme in src/main.ts:
import { createApp } from 'vue'
import { createTourPlugin } from '@lupinum/nuxt-tour/vue'
import '@lupinum/nuxt-tour/style.css'
import App from './App.vue'
import onboarding from './tours/onboarding'
createApp(App)
.use(createTourPlugin({ tours: [onboarding] }))
.mount('#app')Render one host in src/App.vue. Pass the installed definition to useTour()
so its step IDs remain literal:
<script setup lang="ts">
import { ref } from 'vue'
import { TourHost, useTour } from '@lupinum/nuxt-tour/vue'
import onboarding from './tours/onboarding'
const tour = useTour(onboarding)
const error = ref('')
async function start() {
error.value = ''
try {
await tour.start()
}
catch (cause) {
error.value = cause instanceof Error ? cause.message : 'The tour could not start.'
}
}
</script>
<template>
<button v-tour-target="'create-project'">Create project</button>
<button @click="start">Start tour</button>
<p v-if="error" role="alert">{{ error }}</p>
<TourHost />
</template>The same plugin object can be installed on multiple Vue applications. Each app gets an independent runtime, targets, listeners, and active session.
Vue Router
Pass a Vue Router instance when a definition contains route:
const app = createApp(App)
app.use(router)
app.use(createTourPlugin({ tours: [onboarding], router }))
app.mount('#app')A route without a router rejects with ROUTER_NOT_CONFIGURED; it is never
silently ignored. When the router provides afterEach, navigation outside the
tour cancels the active or starting session.
Dynamic targets
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import { useTourTarget } from '@lupinum/nuxt-tour/vue'
const saveButton = useTemplateRef<HTMLButtonElement>('saveButton')
useTourTarget('save-project', saveButton)
</script>
<template>
<button ref="saveButton">
Save project
</button>
</template>Use v-tour-target="'save-project'" for template targets and useTourTarget()
for dynamic refs. Both register the semantic ID with the current Vue
application, so multiple apps on one page stay isolated. Duplicate visible
registrations fail clearly. HTML and SVG elements are supported. Use an explicit
{ selector } target only for third-party or legacy markup outside Vue.