Install maz-ui with Nuxt
Maz-UI Nuxt Module provides zero-configuration setup, intelligent auto-imports, powerful theming capabilities and internationalization.
Model Context Protocol (MCP)
In development, the module can connect the AI coding agents detected in the project (Claude Code, Cursor, Copilot...) to the maz-ui MCP server, which gives them the docs and rules of the installed maz-ui (opt-in with agents: { mcp: true }). See AI Agents.
Check out the documentation of @maz-ui/mcp
Why Choose Maz-UI for Nuxt?
- Zero Configuration - Works out of the box with sensible defaults
- Advanced Theming - Built-in dark mode, custom themes, and CSS variables
- Auto-Import Everything - Components, composables, and directives automatically available
- Performance Optimized - Tree-shaking, lazy loading, and SSR-friendly CSS injection
- Developer Experience - TypeScript support, DevTools integration, and IntelliSense
- Production Ready - SSR/SSG support with client-side hydration
Installation
pnpm add @maz-ui/nuxtnpm install @maz-ui/nuxtyarn add @maz-ui/nuxtpnpx nuxt@latest module add @maz-ui/nuxtAdd the module to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@maz-ui/nuxt']
})That's it! 🎉 All components and composables are now auto-imported and ready to use.
Quick Start
Instant Usage
No imports needed - everything is auto-imported:
<script setup>
// Composables are auto-imported
const { start, stop, pause, resume, remainingTime } = useTimer({
timeout: 4000,
callback: () => console.log('Timeout end')
})
const { toggleDarkMode, isDark } = useTheme()
</script>
<template>
<div class="bg-surface p-8 text-foreground">
<!-- Components are auto-imported -->
<MazBtn color="primary" @click="start">
Start timer ({{ remainingTime }}ms)
</MazBtn>
<!-- Directives work globally -->
<MazBtn @click="toggleDarkMode">
Toggle dark mode ({{ isDark ? '🌙' : '☀️' }})
</MazBtn>
</div>
</template>Configuration
Minimal Setup
For most use cases, no configuration is needed:
export default defineNuxtConfig({
modules: ['@maz-ui/nuxt']
// That's it! 🎉
})Advanced Configuration
Customize everything to your needs:
export default defineNuxtConfig({
modules: ['@maz-ui/nuxt'],
mazUi: {
// General Settings
general: {
autoImportPrefix: 'Maz', // useMazToast instead of useToast
defaultMazIconPath: '/icons', // Default path for <MazIcon />
devtools: true, // Enable DevTools integration
preventIosInputZoom: true, // No zoom on focused fields on iOS
},
// CSS & Styling
css: {
injectCss: true, // Auto-inject Maz-UI styles
},
// Theming System
theme: {
preset: 'maz-ui', // 'maz-ui' | 'pristine' | 'ocean' | 'obsidian' | 'nova' | 'folio' | custom object
strategy: 'runtime', // 'runtime' | 'buildtime'
darkModeStrategy: 'class', // 'class' | 'media'
darkClass: 'dark', // class on <html> when colorMode === 'dark' (default: 'dark')
lightClass: 'light', // class on <html> when colorMode === 'light' (default: 'light')
overrides: {
colors: {
light: { primary: 'oklch(0.65 0.19 254)' },
dark: { primary: 'oklch(0.72 0.18 254)' }
}
},
mode: 'both', // 'light' | 'dark' | 'both'
},
// Translations
translations: {
locale: 'fr',
fallbackLocale: 'en',
messages: {
// override default messages or add new languages:
// the path of a file that exports the messages (loaded when the locale is used)
fr: '~/locales/maz-ui/fr.ts',
// or the messages
nl: { pagination: { navAriaLabel: 'Paginanavigatie' } },
},
},
// Components
components: {
autoImport: true, // All components globally available
},
// Global component defaults (priority: instance prop > defaults[Component] > defaults.global > library default)
defaults: {
global: { roundedSize: 'lg' }, // cross-cutting (roundedSize, size)
MazBtn: { roundedSize: 'full' }, // per-component, wins over global
MazCard: { bordered: false, elevation: true },
},
// Country flags of MazSelectCountry and MazInputPhoneNumber: 'cdn' (default), 'local' (offline) or '/flags/{code}.svg'
flags: 'local',
// Plugins (not enabled by default)
plugins: {
aos: true,
dialog: true,
toast: true,
wait: true,
},
// Composables (enabled by default)
composables: {
useFormValidator: true,
useFreezeValue: true,
useIdleTimeout: false,
useInstanceUniqId: false,
useMountComponent: false,
useReadingTime: false,
useStringMatching: false,
},
// Directives (not enabled by default)
directives: {
vTooltip: true,
vLazyImg: true,
vClickOutside: true,
vFullscreenImg: true,
vZoomImg: true,
},
// AI coding agents (default: { rules: false, mcp: false }, true to enable everything)
agents: { rules: true, mcp: true },
}
})Complete Configuration Reference
General Configuration
const general = {
// Add prefix to all auto-imported composables
autoImportPrefix: 'Maz', // only for composables, generates useMazToast, useMazTheme, etc.
// Default icon path for <MazIcon icon="..." />
defaultMazIconPath: '/icons',
// Enable Nuxt DevTools integration
devtools: true,
// Stop iOS from zooming the page when a form field gets the focus (default: false)
// Adds `maximum-scale=1` to the viewport on iOS only, see the preventIosInputZoom helper of @maz-ui/utils
preventIosInputZoom: false,
}CSS Configuration
const css = {
// Auto-inject Maz-UI base styles
injectCss: true,
}Theme System
The most powerful theming system for Nuxt applications:
const theme = {
// Use predefined presets or create custom ones
preset: 'maz-ui', // 'mazUi' | 'dark' | 'ocean' | CustomThemeObject
// Override specific parts of the theme
overrides: {
colors: {
light: {
primary: 'oklch(0.6 0.18 254)',
secondary: 'oklch(0.96 0.01 254)',
surface: 'oklch(1 0 0)',
foreground: 'oklch(0.16 0.02 254)',
},
dark: {
primary: 'oklch(0.72 0.18 254)',
secondary: 'oklch(0.22 0.02 254)',
surface: 'oklch(0.16 0.02 254)',
foreground: 'oklch(0.96 0.005 254)',
}
},
// Override other theme properties...
},
// Supported color modes to use
mode: 'both', // 'light' | 'dark' | 'both'
// Initial color mode to use (only if mode is 'both')
colorMode: 'auto', // 'light' | 'dark' | 'auto'
// CSS generation strategy
strategy: 'runtime', // 'runtime' (recommended) | 'buildtime'
// Dark mode handling
darkModeStrategy: 'class', // 'class' | 'media'
// Class added to <html> when colorMode === 'dark' (default: 'dark')
darkClass: 'dark',
// Class added to <html> when colorMode === 'light' (default: 'light')
// Mirror of darkClass — used to force `color-scheme: only light`.
lightClass: 'light',
// Persist the active preset name in the `maz-preset` cookie so the
// user's last-used theme is restored on reload. Default: true.
persistPreset: true,
}The server renders the theme of the user: the preset and the color mode come from the maz-color-mode and maz-preset cookies, and the system preference from the Sec-CH-Prefers-Color-Scheme client hint (or the cookie of the previous visit). A blocking script applies the live system preference before the first paint. See the persistence of the user preferences.
Global Component Defaults
Set default prop values once for every component. Resolution priority, per prop: instance prop > defaults[Component] > defaults.global > library default. A global default never overrides a prop set on the instance.
const defaults = {
// Cross-cutting tokens applied to every component that exposes them
global: {
roundedSize: 'lg', // 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'
size: 'sm', // 'mini' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
},
// Per-component defaults, strongly typed as Partial<ComponentNameProps>, win over `global`
MazBtn: { roundedSize: 'full' },
MazCard: { bordered: false, elevation: true },
MazContainer: { bordered: false },
}See the Global component defaults guide for the full list of globalizable props.
Country Flags
Source of the flags of MazSelectCountry and MazInputPhoneNumber. A flag-src set on a component wins.
export default defineNuxtConfig({
mazUi: {
// 'cdn' (default): flagcdn.com
// 'local': flags of @maz-ui/icons, one chunk per flag loaded when visible, no request to a third party
// '/flags/{code}.svg': your own files ({CODE} for uppercase codes)
flags: 'local',
},
})Nothing is added to your build unless flags is 'local'. See MazSelectCountry for the details (Content Security Policy, PWA precache).
Theme Strategies Explained
Runtime (Recommended)
The full theme CSS is generated and injected synchronously on first paint:
- No FOUC - The full stylesheet is rendered in the document head before the first paint
- SSR-friendly - On Nuxt SSR, the CSS is inlined via
useHeadduring server rendering and re-used on the client - Dynamic -
useTheme().updateTheme(...)re-injects the new CSS on the fly
export default defineNuxtConfig({
mazUi: {
theme: {
strategy: 'runtime' // Recommended for most use cases
}
}
})Buildtime
Build-time CSS generation strategy:
- No runtime injection - CSS is generated at build time and must be included manually
- Consumer responsibility - You must handle CSS inclusion in your build process and HTML
- Optimal performance - No client-side CSS generation overhead
- Static themes only - Best for applications without dynamic theme switching
export default defineNuxtConfig({
mazUi: {
theme: {
strategy: 'buildtime' // For static sites with predefined themes
}
}
})Components
const components = {
// Auto-import all 50+ Maz-UI components
autoImport: true,
}Available Components:MazBtn, MazInput, MazSelect, MazDialog, MazToast, MazIcon, MazCard, MazTable, MazChart, MazCarousel, MazGallery, and 50+ more!
🎪 Composables
All composables are auto-imported and ready to use:
const composables = {
// 🎨 Theming
useTheme: true, // Theme management and dark mode
// 🌐 Translations
useTranslations: true, // Translation management
// 📱 Responsive & Detection
useWindowSize: true, // Reactive window dimensions
useBreakpoints: true, // Responsive breakpoints
useUserVisibility: true, // Page visibility detection
useIdleTimeout: true, // User idle detection
// 🛠️ Utilities
useTimer: true, // Timer and countdown
useFormValidator: true, // Form validation
useStringMatching: true, // String utilities
useReadingTime: true, // Reading time calculation
useDisplayNames: true, // Display localized names
useSwipe: true, // Swipe gestures
usePullToRefresh: true, // Pull to refresh gesture
// 🔧 Advanced
useFreezeValue: true, // Freeze reactive values
useInjectStrict: true, // Strict dependency injection
useInstanceUniqId: true, // Unique IDs generation
useMountComponent: true, // Dynamic component mounting
}Plugins
const plugins = {
// Animations
aos: true,
// 🎭 Display modales without any implementation in template
dialog: true,
// 🎭 UI Notifications
toast: true,
// 🔄 Loading States
wait: true,
}Directives
Powerful Vue directives for enhanced functionality:
const directives = {
// Image directives
vLazyImg: { threshold: 0.1 }, // Lazy loading with intersection observer
vZoomImg: true, // Click to zoom images
vFullscreenImg: true, // Fullscreen image viewer
// Interaction directives
vTooltip: { position: 'top' }, // Flexible tooltips
vClickOutside: true, // Detect outside clicks
}AI Agents
Connect your AI coding agents (Claude Code, Cursor, GitHub Copilot, Codex, Windsurf...) to maz-ui, version-matched with the installed maz-ui, so they use its components, composables, icons, helpers and theme tokens instead of re-implementing them:
const agents = {
// Register the maz-ui MCP server in .mcp.json, .cursor/mcp.json, .vscode/mcp.json (default: false)
// Its instructions give the maz-ui rules to the agents
mcp: true,
// Also write the rules in .claude/rules/maz-ui.md and in AGENTS.md, for agents without MCP (default: false)
rules: false,
// 'claude' | 'agents-md' | 'cursor' | 'vscode' (default: the detected agents)
targets: ['claude', 'agents-md'],
// Folder where the files are written, relative to the Nuxt app (default: the root of the workspace)
dir: '../..',
}
// agents: true enables mcp and rules, agents: false disables everythingIn a monorepo, the files are written at the root of the workspace (workspaceDir of Nuxt), where your agents start, not in the Nuxt app: a single .mcp.json serves every app. Set dir to choose another folder.
The module runs in development only (never in CI nor in tests), only for the agents it detects in the project (.claude/, CLAUDE.md, .mcp.json, .cursor/, .vscode/mcp.json, .github/copilot-instructions.md, AGENTS.md, .codex/, .windsurf/...), and keeps the files up to date when you upgrade maz-ui:
.mcp.json,.cursor/mcp.json,.vscode/mcp.json: amaz-uiserver entry, added only when no maz-ui MCP server is already registered- with
rules: true,.claude/rules/maz-ui.md: a Claude Code rule (skipped when Claude readsAGENTS.md, i.e. withoutCLAUDE.md) - with
rules: true,AGENTS.md: a section delimited by<!-- BEGIN:maz-ui -->and<!-- END:maz-ui -->, read by Codex, Cursor, Copilot, Windsurf...
It never overwrites a file it does not own: your CLAUDE.md, your own rules and the other MCP servers are left untouched, and an existing maz-ui server entry (for example pinned to a version) is kept as is. Commit the generated files to share them with your team (check that .claude/ is not in your .gitignore). See the AI agents guide for details.
Advanced Theming
Custom Theme Creation
import { definePreset } from '@maz-ui/themes'
export const customTheme = definePreset({
base: 'maz-ui',
overrides: {
name: 'custom',
foundation: {
'base-font-size': '14px',
'font-family': `Manrope, sans-serif, system-ui, -apple-system`,
'space': '0.25rem',
'border-width': '0.0625rem',
},
scales: {
rounded: { md: '0.7rem' },
},
colors: {
light: {
primary: 'oklch(0.65 0.27 5)', // Custom pink
secondary: 'oklch(0.96 0.01 5)',
surface: 'oklch(1 0 0)',
foreground: 'oklch(0.16 0.02 254)',
muted: 'oklch(0.6 0.01 254)',
accent: 'oklch(0.7 0.05 5)',
destructive: 'oklch(0.6 0.22 27)',
divider: 'oklch(0.92 0.005 254)',
},
dark: {
primary: 'oklch(0.75 0.22 5)',
secondary: 'oklch(0.24 0.02 5)',
surface: 'oklch(0.16 0.02 254)',
foreground: 'oklch(0.96 0.005 254)',
muted: 'oklch(0.6 0.01 254)',
accent: 'oklch(0.3 0.04 5)',
destructive: 'oklch(0.55 0.2 27)',
divider: 'oklch(0.3 0.01 254)',
}
},
},
})
export default defineNuxtConfig({
modules: ['@maz-ui/nuxt'],
mazUi: {
theme: {
preset: customTheme,
strategy: 'runtime',
}
}
})Subtree Overrides with MazUiProvider
You can use MazUiProvider within a Nuxt app to override theme or translations in a specific subtree, while the module handles global defaults.
Troubleshooting
Two versions of maz-ui
If the module warns The app installs maz-ui X and @maz-ui/nuxt uses maz-ui Y, your app and the module load two copies of maz-ui: the options of the module (mazUi.general, mazUi.plugins...) may not apply to the components. Install the same version of maz-ui and @maz-ui/nuxt, they are released together:
npm install maz-ui@latest @maz-ui/nuxt@latestSee Keep the packages on the same version.
Theme System Issues
If you encounter the error "useTheme must be used within MazUi plugin or MazUiTheme plugin installation", ensure that:
- Enable useTheme composable in your configuration:
export default defineNuxtConfig({
mazUi: {
composables: {
useTheme: true,
}
}
})- Theme system is not disabled:
export default defineNuxtConfig({
mazUi: {
theme: {
// theme config, not false
preset: 'maz-ui'
}
}
})