Documentation
Framework Setup
Complete integration guide for every supported framework — Next.js, React, Vue, Nuxt, vanilla JS, and React Native.
Framework Setup
Each framework has a specific integration. This page shows the exact setup for each one.
Next.js
Install
npx create-motionwind@2 init --framework=nextOr manually:
npm install motionwind-react@2 motion motionwind-core@2Configure
// next.config.mjs
import { withMotionwind } from "motionwind-react/next";
import motionwindConfig from "./motionwind.config";
export default withMotionwind({}, motionwindConfig);How it works
withMotionwind wraps your Next.js config and adds a webpack rule that runs
the motionwind Babel plugin before SWC. This means:
.tsxand.jsxfiles are scanned foranimate-*classes.- Static tokens are transformed into Motion props.
"use client"andimport { motion } from "motion/react"are added automatically.- Your existing webpack config is preserved.
Turbopack
withMotionwind also supports Turbopack. The same config works for both
webpack and Turbopack builds.
Server Components
Files with animate-* classes automatically get "use client" injected. If
you have a server component that imports a client component with animations,
the boundary is handled automatically.
React + Vite
Install
npx create-motionwind@2 init --framework=reactOr manually:
npm install motionwind-react@2 motion motionwind-core@2Configure
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import motionwind from "motionwind-react/vite";
import motionwindConfig from "./motionwind.config";
export default defineConfig({
plugins: [motionwind(motionwindConfig), react()],
});Important: The motionwind plugin must come before @vitejs/plugin-react.
How it works
The plugin registers a transform hook with enforce: "pre". For every
.jsx or .tsx file containing animate-:
- The file is passed through the motionwind Babel plugin.
- Static classes are transformed into Motion props.
- Source maps are preserved for debugging.
Files without animate- are skipped entirely (fast string check).
Vue + Vite
Install
npx create-motionwind@2 init --framework=vueOr manually:
npm install motionwind-vue@2 motion-v @vueuse/core motionwind-core@2Configure
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import {
createMotionwindTransform,
MotionwindPlugin,
} from "motionwind-vue/vite";
import motionwindConfig from "./motionwind.config";
export default defineConfig({
plugins: [
createMotionwindTransform(motionwindConfig),
vue(),
MotionwindPlugin(motionwindConfig),
],
});Vue needs both the template transform and the plugin.
Dynamic classes in Vue
For dynamic :class bindings, use the <Motionwind> component or
useMotionwind() composable:
<template>
<Motionwind :class="dynamicClasses" />
</template>
<script setup>
import { Motionwind } from "motionwind-vue";
import { ref } from "vue";
const dynamicClasses = ref("animate-hover:scale-105 animate-spring");
</script>Nuxt
Install
npx create-motionwind@2 init --framework=vueThe CLI detects Nuxt and adds the module automatically.
Configure
// nuxt.config.ts
export default defineNuxtConfig({
modules: ["motionwind-vue/nuxt"],
});Dynamic classes in Nuxt
Use the globally registered <Motionwind> component:
<template>
<Motionwind :class="dynamicClasses" />
</template>
<script setup>
const dynamicClasses = ref("animate-hover:scale-105 animate-spring");
</script>Vanilla JavaScript
Install
npx create-motionwind@2 init --framework=vanillaOr manually:
npm install motionwind-vanilla@2 motion motionwind-core@2Configure
import { motionwind } from "motionwind-vanilla";
import motionwindConfig from "./motionwind.config";
motionwind({ config: motionwindConfig });How it works
The vanilla runtime:
- Observes the DOM for elements with
animate-*classes. - Parses classes at runtime using
parseMotionClasses(). - Applies Motion animations directly to DOM elements.
No build step is required. Works with any bundler or no bundler at all.
Limitations
Vanilla JavaScript doesn't support:
- Layout animations (no component model)
- Drag gestures (use Motion directly)
- Variants (use direct animations)
React Native, Expo
Install
npx create-motionwind@2 init --framework=react-nativeOr manually:
npm install motionwind-react-native@2 react-native-reanimated react-native-gesture-handler nativewind motionwind-core@2Configure
import { MotionwindProvider } from "motionwind-react-native";
import motionwindConfig from "./motionwind.config";
export default function App() {
return (
<MotionwindProvider config={motionwindConfig}>
<YourApp />
</MotionwindProvider>
);
}Babel setup
Reanimated's Babel plugin must be enabled:
// babel.config.js
module.exports = {
presets: ["babel-preset-expo"],
plugins: ["react-native-reanimated/plugin"],
};After changing Babel config, clear Metro cache:
npx react-native start --reset-cacheUsing mw.* components
React Native uses runtime components backed by Reanimated:
import { mw } from "motionwind-react-native";
<mw.Pressable className="animate-tap:scale-90 animate-spring">
<mw.Text>Press me</mw.Text>
</mw.Pressable>;Limitations
React Native (beta) doesn't fully support:
- Drag gestures (use Reanimated directly)
- Layout transitions (use Reanimated directly)
- In-view orchestration (use ScrollView + Reanimated)
- SVG animations (use react-native-svg + Reanimated)
These produce warnings, not silent failures.
Troubleshooting
| Problem | Fix |
|---|---|
| Animations don't play | Run npx create-motionwind@2 doctor |
| Vite: plugin error | motionwind plugin must come before React plugin |
| Vue: animations missing | Ensure both transform and plugin are added |
| Nuxt: component not found | Check modules: ["motionwind-vue/nuxt"] in nuxt.config |
| React Native: crash | Enable Reanimated Babel plugin, clear Metro cache |
| Dynamic classes not working | Use mw.* components for dynamic class names |
| Unknown class warnings | Check spelling; run npx create-motionwind@2 doctor |