createPlugin
Factory for creating Vue plugins with typed dependency injection and lifecycle hooks.
Usage
For most cases, use createPluginContext — it generates the full plugin tuple from a factory function:
import { createPluginContext } from '@vuetify/v0'
interface AnalyticsOptions {
trackPageviews?: boolean
}
interface AnalyticsContext {
track: (event: string) => void
}
export const [createAnalyticsContext, createAnalyticsPlugin, useAnalytics] =
createPluginContext<AnalyticsOptions, AnalyticsContext>(
'my:analytics',
(options) => ({
track: (event) => {
if (options.trackPageviews) console.log(event)
},
}),
)app.use(createAnalyticsPlugin({ trackPageviews: true }))<script setup lang="ts">
import { useAnalytics } from './plugins/analytics'
const analytics = useAnalytics()
analytics.track('page_view')
</script>Low-level API
Use createPlugin directly when you need fine-grained control over plugin setup, or when composing with existing createContext instances:
import { createContext, createPlugin } from '@vuetify/v0'
interface MyPluginContext {
app: string
}
export const [useMyContext, provideMyContext] = createContext<MyPluginContext>('provide-namespace')
export function createMyPlugin () {
const context = {
app: 'my-app'
}
return createPlugin({
namespace: 'provide-namespace',
provide: (app: App) => {
provideMyContext(context, app)
},
setup: (app: App) => {
// For everything else not provide related
}
})
} The setup and provide hooks are separated for semantic purposes — provide is for DI context, setup is for side effects (watchers, adapters, globals).
Architecture
createPlugin wraps createContext for Vue plugin registration:
Persistence
Plugins can automatically save and restore state across page reloads using useStorage. Add persist and restore hooks to the plugin config, then consumers opt in with persist: true.
Plugin author
Define what to save and how to restore in the createPluginContext config:
import { createPluginContext } from '@vuetify/v0'
export const [createThemeContext, createThemePlugin, useTheme] =
createPluginContext('v0:theme', createTheme, {
setup: (context, app, options) => {
// adapter setup...
},
// Return the value to save — called reactively
persist: ctx => ctx.selectedId.value,
// Apply saved value on load — called before setup
restore: (ctx, saved) => ctx.select(saved),
})Consumer
app.use(createThemePlugin({ persist: true }))When persist: true is passed, the plugin automatically:
Reads from
useStorageusing the plugin namespace as keyCalls
restorewith the saved value beforesetuprunsWatches the
persistreturn value and writes changes to storage
The default option becomes the true default — it’s only used when no persisted value exists.
Lifecycle
The critical ordering is restore before setup. This means adapters (like the theme CSS variable injector) see the correct restored state on their first run — no flash of wrong values.
Hook signatures
interface PluginContextConfig<O, E> {
/** Return the value to persist — called reactively inside a watch source */
persist?: (context: E) => unknown
/** Restore previously persisted state — called before setup */
restore?: (context: E, saved: unknown) => void
}The persist return value is stored under the plugin namespace key (e.g. v0:theme). restore receives whatever was stored — cast to the expected type inside the hook.
Built-in support
| Plugin | Persists | Storage key |
|---|---|---|
createThemePlugin | Selected theme ID | v0:theme |
createRtlPlugin | RTL direction | v0:rtl |
createLocalePlugin | Selected locale | v0:locale |
Examples
Dashboard Features
This example demonstrates how to create a plugin that manages feature flag state using createPlugin, createContext, and createGroup. The plugin composes a group for selection state instead of reimplementing toggle logic.
File breakdown:
| File | Role |
|---|---|
plugin.ts | Defines the DashboardContext (wrapping a GroupContext), creates the context tuple, and exports the createDashboardPlugin factory |
DashboardProvider.vue | Creates the plugin instance and provides the context, rendering only a slot |
DashboardConsumer.vue | Consumes the context via useDashboard() and uses the group’s toggle(), selectAll(), and unselectAll() methods |
dashboard.vue | Entry point that composes Provider around Consumer |
Key patterns:
Provider components are invisible wrappers that render only a slot
The plugin composes
createGroup— each feature is a ticket with selection state built inIn a real app, the factory would return a plugin for
app.use()— here it returnscontextdirectly for the sandboxConsumers import only from
plugin.ts, never from the Provider
My Dashboard
2 / 5 features enabled
Active features
Functions
createPluginContext
(defaultNamespace: string, factory: (options: Omit<O, "namespace" | "persist">) => E, config?: PluginContextConfig<Omit<O, "namespace" | "persist">, E> | undefined) => readonly [<_E extends E = E>(_options?: O) => ContextTrinity<_E>, (_options?: O) => Plugin, <_E extends E = E>(namespace?: string) => _E]Creates the three standard functions for a plugin composable.