Frameworks

Vue / Nuxt

Integrate FanID gated content into Vue and Nuxt applications.

Installation

npm install @wmt-fanid/widget

Vue 3 (Vite)

Configure the custom element in your Vite config, then initialize the widget:

vite.config.ts
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === 'wmt-fanid-protected',
        },
      },
    }),
  ],
})
main.ts
import { createApp } from 'vue'
import App from './App.vue'
import FanIDWidget from '@wmt-fanid/widget'
import '@wmt-fanid/widget/dist/widget.css'

createApp(App).mount('#app')

FanIDWidget.init({ baseUrl: 'https://your-org.fanid.co' })
Do not set app.config.compilerOptions.isCustomElement at runtime — the runtime-only Vue build does not support it. Configure it in the Vite plugin instead as shown above.

Nuxt

Create a client-only plugin:

plugins/fanid.client.ts
import FanIDWidget from '@wmt-fanid/widget'
import '@wmt-fanid/widget/dist/widget.css'

export default defineNuxtPlugin(() => {
  FanIDWidget.init({ baseUrl: 'https://your-org.fanid.co' })
})

Configure the custom element in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  vue: {
    compilerOptions: {
      isCustomElement: (tag) => tag === 'wmt-fanid-protected',
    },
  },
})

Using in templates

<template>
  <article>
    <h1>{{ article.title }}</h1>

    <wmt-fanid-protected
      placeholder-title="Exclusive Content"
      placeholder-message="Sign in to read this article"
      style-mode="gradient"
      teaser-height="120"
    >
      <div v-html="article.body" />
    </wmt-fanid-protected>
  </article>
</template>

Reactive auth state

Use FanIDWidget.getProfile() and events to build reactive auth state:

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

const profile = ref(null)
const isAuthenticated = ref(false)

async function refreshProfile() {
  profile.value = await window.FanIDWidget.getProfile() ?? null
  isAuthenticated.value = await window.FanIDWidget.isAuthenticated()
}

onMounted(() => {
  window.FanIDWidget.on('auth:login', refreshProfile)
  window.FanIDWidget.on('auth:logout', refreshProfile)
  window.FanIDWidget.on('ready', refreshProfile)
})

onUnmounted(() => {
  window.FanIDWidget.off('auth:login', refreshProfile)
  window.FanIDWidget.off('auth:logout', refreshProfile)
  window.FanIDWidget.off('ready', refreshProfile)
})
</script>

<template>
  <div v-if="isAuthenticated">
    <p>Welcome, {{ profile?.firstName }}!</p>
  </div>
</template>

Programmatic gating

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const statsRef = ref()

onMounted(() => {
  if (statsRef.value) {
    if (window.FanIDWidget.isInitialized()) {
      window.FanIDWidget.gate(statsRef.value, {
        placeholder: { title: 'Premium Stats' },
      })
    } else {
      window.FanIDWidget.on('ready', () => {
        window.FanIDWidget.gate(statsRef.value, {
          placeholder: { title: 'Premium Stats' },
        })
      })
    }
  }
})

onUnmounted(() => {
  if (statsRef.value) {
    window.FanIDWidget.ungate(statsRef.value)
  }
})
</script>

<template>
  <div ref="statsRef">
    <table>...</table>
  </div>
</template>

Show/hide floating widget

<template>
  <button @click="window.FanIDWidget.showFloatingWidget()">Sign In</button>
  <button @click="window.FanIDWidget.hideFloatingWidget()">Close</button>
</template>
Copyright © 2026