apps/mantine.dev/src/pages/guides/next.mdx
import { Layout } from '@/layout'; import { MDX_DATA } from '@/mdx';
export default Layout(MDX_DATA.NextJs);
Follow the create-next-app guide to create a new Next.js application:
<NpmScript yarnScript="yarn create next-app --typescript" npmScript="npx create-next-app@latest --typescript" />
Install PostCSS plugins and postcss-preset-mantine:
<InstallScript packages="postcss postcss-preset-mantine postcss-simple-vars" dev />
Create a postcss.config.cjs file at the root of your application with the following content:
module.exports = {
plugins: {
'postcss-preset-mantine': {},
'postcss-simple-vars': {
variables: {
'mantine-breakpoint-xs': '36em',
'mantine-breakpoint-sm': '48em',
'mantine-breakpoint-md': '62em',
'mantine-breakpoint-lg': '75em',
'mantine-breakpoint-xl': '88em',
},
},
},
};
Add styles imports and MantineProvider to the pages/_app.tsx file:
// Import styles of packages that you've installed.
// All packages except `@mantine/hooks` require styles imports
import '@mantine/core/styles.css';
import type { AppProps } from 'next/app';
import { createTheme, MantineProvider } from '@mantine/core';
const theme = createTheme({
/** Put your mantine theme override here */
});
export default function App({ Component, pageProps }: AppProps) {
return (
<MantineProvider theme={theme}>
<Component {...pageProps} />
</MantineProvider>
);
}
Create a pages/_document.tsx file with the ColorSchemeScript component.
Note that it's required even if you use only one color scheme in your application.
import { Head, Html, Main, NextScript } from 'next/document';
import { ColorSchemeScript, mantineHtmlProps } from '@mantine/core';
export default function Document() {
return (
<Html lang="en" {...mantineHtmlProps}>
<Head>
<ColorSchemeScript defaultColorScheme="auto" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
All set! Start the development server:
npm run dev
Add MantineProvider, ColorSchemeScript
and styles imports to the app/layout.tsx file:
// Import styles of packages that you've installed.
// All packages except `@mantine/hooks` require styles imports
import '@mantine/core/styles.css';
import { ColorSchemeScript, MantineProvider, mantineHtmlProps } from '@mantine/core';
export const metadata = {
title: 'My Mantine app',
description: 'I have followed setup instructions carefully',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" {...mantineHtmlProps}>
<head>
<ColorSchemeScript />
</head>
<body>
<MantineProvider>{children}</MantineProvider>
</body>
</html>
);
}
All set! Start the development server:
npm run dev
If you use both app and pages router in one application, you need to setup both pages/_app.tsx
and app/layout.tsx files as described above.
import Link from 'next/link';
import { Button } from '@mantine/core';
function Demo() {
return (
<Button component={Link} href="/hello">
Next link button
</Button>
);
}
All Mantine components require context to support default props and Styles API. Mantine components cannot be used as server components. This means that components will render both on the server and client.
Entry points of all @mantine/* packages (index.js files) have the 'use client'; directive at the
top of the file – you don't need to add 'use client'; to your pages/layouts/components.
Some components like Popover have associated compound components (Component.XXX),
where XXX is a compound component name. Compound components cannot be used in server components.
Instead, use the ComponentXXX syntax or add the 'use client'; directive to the top of the file.
Example that won't work in server components:
import { Popover } from '@mantine/core';
// This will throw an error
export default function Page() {
return (
<Popover>
<Popover.Target>Target</Popover.Target>
<Popover.Dropdown>Dropdown</Popover.Dropdown>
</Popover>
);
}
Example with 'use client'; directive:
'use client';
import { Popover } from '@mantine/core';
// No error
export default function Page() {
return (
<Popover>
<Popover.Target>Target</Popover.Target>
<Popover.Dropdown>Dropdown</Popover.Dropdown>
</Popover>
);
}
Example with ComponentXXX syntax:
import {
Popover,
PopoverDropdown,
PopoverTarget,
} from '@mantine/core';
// No error
export default function Page() {
return (
<Popover>
<PopoverTarget>Trigger</PopoverTarget>
<PopoverDropdown>Dropdown</PopoverDropdown>
</Popover>
);
}
To enable tree shaking with app router, enable the experimental optimizePackageImports feature in
your next.config.mjs:
export default {
// ...other configuration
experimental: {
optimizePackageImports: ['@mantine/core', '@mantine/hooks'],
},
};
If you have any issues with Mantine in your Next.js application, please check the Help Center article that covers the most common issues with app router and server components.