Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Plugins

v0 plugins are Vue plugins built with createPlugin. They provide app-wide singletons for features like theming, locale, and logging. For understanding the underlying architecture, see Core.


AdvancedApr 5, 2026

Using Built-in Plugins

Basic Installation

main.ts
import { createApp } from 'vue'
import { createThemePlugin, createLocalePlugin } from '@vuetify/v0'

const app = createApp(App)

// Install plugins
app.use(createThemePlugin())
app.use(createLocalePlugin())

app.mount('#app')

With Options

ts
app.use(
  createThemePlugin({
    default: 'dark',
    themes: {
      light: { dark: false, colors: { primary: '#1976D2' } },
      dark: { dark: true, colors: { primary: '#2196F3' } },
    },
  }),
)

app.use(
  createLocalePlugin({
    default: 'en',
    messages: { en: { hello: 'Hello' } },
  }),
)

Available Plugins

PluginPurposeComposable
createThemePluginCSS variable theming, dark modeuseTheme
createLocalePlugini18n translationsuseLocale
createRtlPluginRTL direction supportuseRtl
createLoggerPluginStructured logginguseLogger
createStoragePluginReactive localStorage/sessionStorageuseStorage
createPermissionsPluginRole-based access controlusePermissions
createBreakpointsPluginResponsive breakpoint detectionuseBreakpoints
createHydrationPluginSSR hydration managementuseHydration
createFeaturesPluginFeature flags with adapter supportuseFeatures
createRulesPluginValidation rule aliases and Standard SchemauseRules
createDatePluginDate utilities with adapter patternuseDate
createNotificationsPluginNotification lifecycle and toast queueuseNotifications
createStackPluginOverlay z-index stackinguseStack
Tip

All plugins are optional. Only install what you need—v0 works without any plugins installed.

Ask AI
Which built-in plugins do I actually need? Can I use v0 without them?

Creating Custom Plugins

Using createPluginContext

createPluginContext is the recommended factory for new plugins. It generates the full [createXContext, createXPlugin, useX] tuple in a single call, eliminating the boilerplate of wiring together createContext and createPlugin manually.

src/plugins/analytics.ts
import { createPluginContext } from '@vuetify/v0'

interface AnalyticsContext {
  track: (event: string, data?: Record<string, unknown>) => void
  identify: (userId: string) => void
}

interface AnalyticsOptions {
  apiKey: string
  debug?: boolean
}

export const [createAnalyticsContext, createAnalyticsPlugin, useAnalytics] =
  createPluginContext<AnalyticsOptions, AnalyticsContext>(
    'my:analytics',
    ({ apiKey, debug = false }) => ({
      track: (event, data) => {
        if (debug) console.log('Track:', event, data)
        // send to analytics service using apiKey
      },
      identify: (userId) => {
        // identify user
      },
    }),
  )
main.ts
app.use(createAnalyticsPlugin({ apiKey: 'xxx', debug: true }))
MyComponent.vue
<script setup>
  import { useAnalytics } from './plugins/analytics'
  const analytics = useAnalytics()
  analytics.track('page_view')
</script>
Tip

createPluginContext also supports persist/restore lifecycle hooks for automatically saving and rehydrating plugin state across page loads. See createPlugin for details.

Manual Approach

For fine-grained control over the plugin lifecycle, use createContext and createPlugin directly:

src/plugins/analytics.ts
import { createContext, createPlugin } from '@vuetify/v0'

interface AnalyticsContext {
  track: (event: string, data?: Record<string, unknown>) => void
  identify: (userId: string) => void
}

// 1. Create the context for DI
const [useAnalytics, provideAnalytics] = createContext<AnalyticsContext>('my:analytics')

// 2. Create the plugin factory
export function createAnalyticsPlugin() {
  const context: AnalyticsContext = {
    track: (event, data) => console.log('Track:', event, data),
    identify: (userId) => console.log('Identify:', userId),
  }

  return createPlugin({
    namespace: 'my:analytics',
    provide: (app) => provideAnalytics(context, app),
  })
}

export { useAnalytics }

Plugin with Options

src/plugins/analytics.ts
interface AnalyticsOptions {
  apiKey: string
  debug?: boolean
}

export function createAnalyticsPlugin(options: AnalyticsOptions) {
  const { apiKey, debug = false } = options

  const context: AnalyticsContext = {
    track: (event, data) => {
      if (debug) console.log('Track:', event, data)
      // Send to analytics service
    },
    identify: (userId) => {
      // Identify user
    },
  }

  return createPlugin({
    namespace: 'my:analytics',
    provide: (app) => provideAnalytics(context, app),
  })
}

// Usage
app.use(createAnalyticsPlugin({ apiKey: 'xxx', debug: true }))

Plugin with Adapter Pattern

For extensible plugins that support multiple backends:

src/plugins/logger.ts
interface LoggerAdapter {
  log: (level: string, message: string) => void
}

interface LoggerContext {
  info: (msg: string) => void
  warn: (msg: string) => void
  error: (msg: string) => void
}

interface LoggerOptions {
  adapter?: LoggerAdapter
}

const consoleAdapter: LoggerAdapter = {
  log: (level, message) => console[level](message),
}

const [useLogger, provideLogger] = createContext<LoggerContext>('my:logger')

export function createLoggerPlugin(options: LoggerOptions = {}) {
  const adapter = options.adapter ?? consoleAdapter

  const context: LoggerContext = {
    info: (msg) => adapter.log('info', msg),
    warn: (msg) => adapter.log('warn', msg),
    error: (msg) => adapter.log('error', msg),
  }

  return createPlugin({
    namespace: 'my:logger',
    provide: (app) => provideLogger(context, app),
  })
}

// Custom adapter example
const sentryAdapter: LoggerAdapter = {
  log: (level, message) => {
    if (level === 'error') Sentry.captureMessage(message)
  },
}

app.use(createLoggerPlugin({ adapter: sentryAdapter }))

Consuming Plugins

vue
<script setup>
  import { useTheme, useLocale } from '@vuetify/v0'

  const theme = useTheme()
  const locale = useLocale()

  // Theme API
  theme.cycle()              // Cycle through themes
  theme.select('dark')       // Select specific theme
  theme.selectedItem.value   // Current theme ticket
  theme.selectedId.value     // 'light' | 'dark'
  theme.isDark.value         // boolean

  // Locale API
  locale.t('hello')
  locale.selectedItem.value  // Current locale ticket
  locale.selectedId.value    // 'en'
</script>

Plugin vs Context

NeedUse
App-wide singleton (one instance)Plugin with app.use()
Multiple instances per subtreeContext with provideContext
Configurable at install timePlugin
Configurable per component treeContext

Best Practices

1. Provide Default Adapters

ts
// Always provide a sensible default
const defaultAdapter = { /* ... */ }
const adapter = options.adapter ?? defaultAdapter

2. Type the Context Interface

ts
// Define what consumers get
interface ThemeContext {
  selectedId: ComputedRef<string>
  select: (id: string) => void
  cycle: () => void
}

3. Handle Missing Installation

ts
const theme = useTheme()
// useTheme throws if createThemePlugin isn't installed
// This is intentional - fail fast
Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/