Next.js Dark Mode

Complete setup guide for adding dark mode and theme toggling to Next.js App Router applications using next-themes.

Follow these steps to configure theme switching in your Next.js application.

1. Install next-themes

Install the next-themes package:

pnpm add next-themes

2. Create the Theme Provider

Create a client-side wrapper component around NextThemesProvider:

components/theme-provider.tsx
"use client"
 
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
 
export function ThemeProvider({
  children,
  ...props
}: React.ComponentProps<typeof NextThemesProvider>) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

3. Wrap Your Root Layout

Add the ThemeProvider inside your root layout and add suppressHydrationWarning to the html tag to prevent hydration warnings from browser theme detection:

app/layout.tsx
import { ThemeProvider } from "@/components/theme-provider"
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head />
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

4. Add a Mode Toggle Button

Create a toggle button using Lucide icons and the useTheme hook:

components/mode-toggle.tsx
"use client"
 
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
 
export function ModeToggle() {
  const { theme, setTheme } = useTheme()
 
  return (
    <button
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
      className="inline-flex h-9 w-9 items-center justify-center rounded-md border border-border bg-background text-foreground transition-colors hover:bg-accent"
      aria-label="Toggle theme"
    >
      <Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
      <Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
    </button>
  )
}