Back to blog

Published on Friday, June 13, 2025

How to Configure next-themes in a Next.js App

How to Configure next-themes in a Next.js App

Introduction

Dark mode is now a standard feature in modern web apps. Fortunately, next-themes makes it incredibly easy to implement dark mode in your Next.js application. When combined with Shadcn UI, it creates a smooth developer experience and polished UI.co

In this tutorial, we’ll walk through how to:

  • Install next-themes.
  • Configure it in a Next.js app.
  • Integrate it with Shadcn UI components.
  • Add a theme toggle button.

Install Dependencies

If you haven’t already, set up a Next.js project:

npx create-next-app@latest my-app --typescript
cd my-app

Then, install the required packages:

npm install next-themes

Make sure Shadcn UI is also installed:

npx shadcn-ui@latest init

During setup, choose tailwind as your CSS framework and ensure the theme is set to class in tailwind.config.js.

Configure ThemeProvider

Create a components/theme-provider.tsx file:

"use client";

import React from "react";
import {
    type ThemeProviderProps,
    ThemeProvider as NextThemesProvider,
} from "next-themes";

const ThemeProvider: React.FC<ThemeProviderProps> = ({
    children,
    ...props
}) => {
    return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
};

export default ThemeProvider;

Wrap Your App with ThemeProvider

Update your app/layout.tsx (or _app.tsx if using the pages router):

import type { Metadata } from 'next'

import './globals.css'
import { ThemeProvider } from '@/components/theme-provider'

export const metadata: Metadata = {
  title: 'My App',
  description: 'Using next-themes with Shadcn UI',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className="min-h-screen bg-background font-sans antialiased text-foreground">
        <ThemeProvider
						attribute="class"
						defaultTheme="system"
						enableSystem
				>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

Setup tailwind.config.js

Ensure your Tailwind config is using the class strategy:

module.exports = {
  darkMode: 'class', // Important!
  content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

Add a Theme Toggle Button

You can now add a toggle using Shadcn UI’s Button and Switch components.

'use client'

import React from 'react'
import { useTheme } from 'next-themes'
import { Moon, Sun } from 'lucide-react'

import {
    DropdownMenu,
    DropdownMenuItem,
    DropdownMenuTrigger,
    DropdownMenuContent,
} from '@/components/ui/dropdown-menu'
import { Button } from '@/components/ui/button'

const ThemeToggler: React.FC = () => {
    const { setTheme } = useTheme();

    return (
        <DropdownMenu>
            <DropdownMenuTrigger asChild>
                <Button size="icon" variant="outline">
                    <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
                    <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
                    <span className="sr-only">Toggle theme</span>
                </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
                <DropdownMenuItem onClick={() => setTheme("light")}>
                    Light
                </DropdownMenuItem>
                <DropdownMenuItem onClick={() => setTheme("dark")}>
                    Dark
                </DropdownMenuItem>
                <DropdownMenuItem onClick={() => setTheme("system")}>
                    System
                </DropdownMenuItem>
            </DropdownMenuContent>
        </DropdownMenu>
    );
};

export default ThemeToggler;

Now use it in your navbar or any layout:

// components/navbar.tsx
import ThemeToggle from './theme-toggle'

export default function Navbar() {
  return (
    <nav className="flex justify-end p-4 border-b">
      <ThemeToggle />
    </nav>
  )
}

Conclusion

With just a few steps, you can enable dark mode in your Next.js app using next-themes and Shadcn UI. It's lightweight, customizable, and production-ready.

If you're building a modern UI and want theme support out-of-the-box, this is the cleanest approach.