Skip to content

Latest commit

 

History

History
146 lines (83 loc) · 8.7 KB

File metadata and controls

146 lines (83 loc) · 8.7 KB

Material UI and Next.js

Version 1.0.0 (Material UI v9)

Version notice: This skill targets Material UI v9 (>=9.0.0 <10.0.0). If you are using a different major version, verify the API details before following this guidance.

Note: This document is for agents and LLMs integrating Material UI with Next.js. Source: docs/data/material/integrations/nextjs/nextjs.md and related integration docs in this repository.


Abstract

Material UI uses Emotion for styles. On Next.js you must wire an Emotion cache so SSR and streaming produce correct CSS (prefer injecting styles into head instead of only body). The @mui/material-nextjs package supplies AppRouterCacheProvider (App Router) and AppCacheProvider / DocumentHeadTags (Pages Router). Material UI components ship as client components ("use client"); they still SSR but are not React Server Components. Match the package import suffix (for example v15-appRouter) to your Next.js major version.


Table of contents

  1. App Router (recommended)
  2. Pages Router
  3. Fonts (next/font)
  4. CSS theme variables and SSR
  5. Other styling stacks (CSS layers)
  6. Next.js Link and component prop
  7. Further reading

App Router (recommended)

Dependencies

Have @mui/material and next installed, then add:

  • @mui/material-nextjs
  • @emotion/cache

Example: pnpm add @mui/material-nextjs @emotion/cache

Root layout

In app/layout.tsx, wrap everything under <body> with AppRouterCacheProvider from the entry that matches your Next major, for example:

import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';

(Use the v1X-appRouter path that matches your Next.js version if not on v15.)

Why: it collects CSS from MUI System during server rendering and streaming so styles attach predictably; it is recommended so styles go to <head> instead of only <body>. See Next.js integration—Configuration.

Optional cache options

Pass options to AppRouterCacheProvider to override Emotion cache options, for example key: 'css' (the default MUI key is mui). See Next.js integration—Custom cache (optional).

URL hooks and Suspense

Dashboards and internal tools often combine MUI client components with URL-driven UI (filters, tabs, pagination) using useSearchParams() from next/navigation.

Next.js expects a <Suspense> boundary around the part of the tree that uses useSearchParams (and similar patterns that opt the route into client-side rendering), otherwise you can get build failures or runtime errors about a missing Suspense boundary.

Practical pattern: keep app/.../page.tsx as a server component when possible; render a client subtree that uses components such as Table, Tabs, or TextField and is tied to the query string inside <Suspense> from that server page. Do not use fallback={null} for UI that occupies layout space (toolbars, filters, and similar); it tends to cause layout shift when the client mounts. Use a fallback that matches the real layout (for example Skeleton with Stack or Box and the same minHeight and rough dimensions as the final UI). Full example: Next.js integration—URL-driven UI and the Suspense boundary.

Official reference: Next.js—useSearchParams (static rendering and Suspense notes vary by major version).


Pages Router

Dependencies

Add @mui/material-nextjs, @emotion/cache, and @emotion/server.

Example: pnpm add @mui/material-nextjs @emotion/cache @emotion/server

_document.tsx

  • Import DocumentHeadTags and documentGetInitialProps from the v15-pagesRouter (or matching v1X-pagesRouter) entry.
  • Render <DocumentHeadTags {...props} /> inside <Head>.
  • Assign getInitialProps to call documentGetInitialProps.

_app.tsx

Wrap the app with AppCacheProvider from the same major entry (for example v15-pagesRouter).

Optional: custom cache and cascade layers

  • Pass a custom emotionCache into documentGetInitialProps options when needed.
  • For @layer, use createEmotionCache({ enableCssLayer: true }) from @mui/material-nextjs, pass it from _document and align _app with the same cache pattern. See Next.js integration—Cascade layers (optional).

TypeScript

Extend Document props with DocumentHeadTagsProps from the same import path. See Next.js integration—TypeScript.


Fonts (next/font)

App Router: theme modules that call createTheme need 'use client' when they are consumed from server components. Use next/font/google (or local fonts), set variable: '--font-…', put className={font.variable} on <html> (or as in docs), and set typography.fontFamily to 'var(--font-…)'. Wrap with ThemeProvider inside AppRouterCacheProvider as needed.

Pages Router: similar pattern in pages/_app.tsx with AppCacheProvider and ThemeProvider.

Details: Next.js integration—Font optimization (App) and Next.js integration—Font optimization (Pages).


CSS theme variables and SSR

Enable cssVariables: true in createTheme when using CSS theme variables. For SSR flicker and InitColorSchemeScript, follow CSS theme variables—Preventing SSR flickering and CSS theme variables overview—Advantages. Add suppressHydrationWarning to <html> when using colorSchemes — the color scheme attribute is written client-side on first render and will otherwise produce a React hydration mismatch.


Other styling stacks (CSS layers)

If you combine MUI with Tailwind CSS, CSS Modules, or other global CSS, set enableCssLayer: true on AppRouterCacheProvider:

<AppRouterCacheProvider options={{ enableCssLayer: true }}>

That wraps MUI output in @layer mui so anonymous layers can override as intended. See Next.js integration—Using other styling solutions and MDN—@layer.


Next.js Link and component prop

Next.js v16: passing next/link directly into component can trigger "Functions cannot be passed directly to Client Components". Fix: a small client re-export:

'use client';
import Link, { LinkProps } from 'next/link';
export default Link;

Import that wrapper and use component={Link} on Button and similar. See Next.js integration—Next.js v16 Client Component restriction.

Pages Router and theme-wide patterns: see Routing libraries—Next.js Pages Router and the material-ui-nextjs-pages-router-ts example.


Further reading

Topic Link
Full integration guide Next.js integration
Example (App Router, TypeScript) material-ui-nextjs-ts
Routing + Link adapters Routing libraries
RSC vs SSR (terminology) React WG discussion

Import path cheat sheet: reference.md.