Building a Next.js 15 App with Dark/Ligh ...

Building a Next.js 15 App with Dark/Light Theme Using Tailwind CSS v4, shadcn/ui

Jul 06, 2025

Creating a modern web application with seamless theme switching has become essential for providing an excellent user experience. In this comprehensive guide, we’ll build a Next.js 15 application from scratch and implement a professional theming system using the latest Tailwind CSS v4, shadcn/ui, and tweakcn.

image

📺 Watch the Complete Video Tutorial

For a detailed walkthrough of this entire process, check out our complete video tutorial: Next.js Theme Setup — Complete Bangla Tutorial

Table of Contents

  1. Setting Up the Next.js Project

  2. Installing and Configuring Tailwind CSS

  3. Setting Up shadcn/ui

  4. Implementing Theme Provider

  5. Creating Theme Toggle Components

  6. Customizing Colors with tweakcn

  7. Advanced Theming Techniques

  8. Testing and Optimization

image

Prerequisites

Before we start, make sure you have:

  • Node.js (v20 or later) — required for Next.js 15

  • Basic knowledge of React 19 and Next.js

  • Understanding of modern CSS and Tailwind CSS

  • A code editor (VS Code recommended)

1. Setting Up the Next.js 15 Project {#setting-up-nextjs}

Let’s start by creating a new Next.js 15 project with TypeScript support:

npx create-next-app@latest my-themed-app --typescript --eslint --app --src-dir
cd my-themed-app

When prompted, choose the following options:

  • ✅ TypeScript

  • ✅ ESLint

  • ❌ Tailwind CSS (we’ll install v4 manually)

  • ✅ src/ directory

  • ✅ App Router

  • ❌ Import alias (we’ll configure this later)

  • ❌ Turbopack (optional, can enable for faster development)

Next.js 15 comes with React 19 and improved performance optimizations out of the box.

2. Installing and Configuring Tailwind CSS v4 {#tailwind-setup}

Tailwind CSS v4 introduces a new CSS-first configuration approach. Let’s install it:

npm install tailwindcss@next @tailwindcss/vite@next

Create a new tailwind.config.ts file:

import type { Config } from 'tailwindcss'
export default {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  darkMode: 'class',
} satisfies Config

Update your next.config.js to support Tailwind CSS v4:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    optimizePackageImports: ['@tailwindcss/vite'],
  },
}
module.exports = nextConfig

3. Setting Up shadcn/ui {#shadcn-setup}

Now let’s install and configure shadcn/ui for our component system. First, set up path mapping in your tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

Install shadcn/ui CLI and initialize:

npx shadcn@latest init

Choose the following options:

  • Style: New York (recommended for modern look)

  • Base color: Zinc

  • CSS variables: Yes

This will create a components.json file and set up the basic configuration optimized for Next.js 15 and Tailwind CSS v4.

Install the necessary dependencies:

npm install class-variance-authority clsx tailwind-merge lucide-react
npm install @radix-ui/react-dropdown-menu @radix-ui/react-slot

Create your main CSS file src/app/globals.css with Tailwind CSS v4's new import syntax:

@import "tailwindcss";
@theme {
  --color-border: #e2e8f0;
  --color-input: #e2e8f0;
  --color-ring: #3b82f6;
  --color-background: #ffffff;
  --color-foreground: #0f172a;
  --color-primary: #3b82f6;
  --color-primary-foreground: #f8fafc;
  --color-secondary: #f1f5f9;
  --color-secondary-foreground: #0f172a;
  --color-destructive: #ef4444;
  --color-destructive-foreground: #f8fafc;
  --color-muted: #f1f5f9;
  --color-muted-foreground: #64748b;
  --color-accent: #f1f5f9;
  --color-accent-foreground: #0f172a;
  --color-popover: #ffffff;
  --color-popover-foreground: #0f172a;
  --color-card: #ffffff;
  --color-card-foreground: #0f172a;
  --radius: 0.5rem;
}@media (prefers-color-scheme: dark) {
  @theme {
    --color-border: #334155;
    --color-input: #334155;
    --color-ring: #60a5fa;
    --color-background: #0f172a;
    --color-foreground: #f8fafc;
    --color-primary: #60a5fa;
    --color-primary-foreground: #0f172a;
    --color-secondary: #1e293b;
    --color-secondary-foreground: #f8fafc;
    --color-destructive: #dc2626;
    --color-destructive-foreground: #f8fafc;
    --color-muted: #1e293b;
    --color-muted-foreground: #94a3b8;
    --color-accent: #1e293b;
    --color-accent-foreground: #f8fafc;
    --color-popover: #0f172a;
    --color-popover-foreground: #f8fafc;
    --color-card: #0f172a;
    --color-card-foreground: #f8fafc;
  }
}.dark {
  --color-border: #334155;
  --color-input: #334155;
  --color-ring: #60a5fa;
  --color-background: #0f172a;
  --color-foreground: #f8fafc;
  --color-primary: #60a5fa;
  --color-primary-foreground: #0f172a;
  --color-secondary: #1e293b;
  --color-secondary-foreground: #f8fafc;
  --color-destructive: #dc2626;
  --color-destructive-foreground: #f8fafc;
  --color-muted: #1e293b;
  --color-muted-foreground: #94a3b8;
  --color-accent: #1e293b;
  --color-accent-foreground: #f8fafc;
  --color-popover: #0f172a;
  --color-popover-foreground: #f8fafc;
  --color-card: #0f172a;
  --color-card-foreground: #f8fafc;
}@layer base {
  * {
    @apply border-border;
  }
  body {
    @apply bg-background text-foreground;
    font-feature-settings: "rlig" 1, "calt" 1;
  }
}

Start the development server to ensure everything is working:

npm run dev

Create the utility function at src/lib/utils.ts:

import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Install the core components we’ll need:

npx shadcn@latest add button
npx shadcn@latest add dropdown-menu
npx shadcn@latest add card

4. Implementing Theme Provider with Next.js 15 {#theme-provider}

Install the next-themes package which is compatible with React 19:

npm install next-themes

Create a theme provider component at src/components/theme-provider.tsx:

"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"interface ThemeProviderProps {
  children: React.ReactNode
  attribute?: string
  defaultTheme?: string
  enableSystem?: boolean
  disableTransitionOnChange?: boolean
}export function ThemeProvider({ 
  children, 
  attribute = "class",
  defaultTheme = "system",
  enableSystem = true,
  disableTransitionOnChange = false,
  ...props 
}: ThemeProviderProps) {
  return (
    <NextThemesProvider
      attribute={attribute}
      defaultTheme={defaultTheme}
      enableSystem={enableSystem}
      disableTransitionOnChange={disableTransitionOnChange}
      {...props}
    >
      {children}
    </NextThemesProvider>
  )
}

Update your root layout src/app/layout.tsx for Next.js 15:

import type { Metadata } from "next"
import { Inter } from "next/font/google"
import "./globals.css"
import { ThemeProvider } from "@/components/theme-provider"
const inter = Inter({ 
  subsets: ["latin"],
  display: 'swap', // Improved font loading
})export const metadata: Metadata = {
  title: "My Themed App",
  description: "A Next.js 15 app with advanced theming using Tailwind CSS v4",
  keywords: ["Next.js", "React", "Tailwind CSS", "Theme", "Dark Mode"],
}export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={inter.className}>
        <ThemeProvider>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

5. Creating Advanced Theme Toggle Components {#theme-toggle}

Create an enhanced theme toggle component at src/components/theme-toggle.tsx:

"use client"
import * as React from "react"
import { Moon, Sun, Monitor } from "lucide-react"
import { useTheme } from "next-themes"import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"export function ThemeToggle() {
  const { setTheme, theme } = useTheme()
  const [mounted, setMounted] = React.useState(false)  // Prevent hydration mismatch
  React.useEffect(() => {
    setMounted(true)
  }, [])  if (!mounted) {
    return (
      <Button variant="outline" size="icon">
        <div className="h-[1.2rem] w-[1.2rem]" />
        <span className="sr-only">Toggle theme</span>
      </Button>
    )
  }  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="icon">
          <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")}
          className={theme === "light" ? "bg-accent" : ""}
        >
          <Sun className="mr-2 h-4 w-4" />
          <span>Light</span>
        </DropdownMenuItem>
        <DropdownMenuItem 
          onClick={() => setTheme("dark")}
          className={theme === "dark" ? "bg-accent" : ""}
        >
          <Moon className="mr-2 h-4 w-4" />
          <span>Dark</span>
        </DropdownMenuItem>
        <DropdownMenuItem 
          onClick={() => setTheme("system")}
          className={theme === "system" ? "bg-accent" : ""}
        >
          <Monitor className="mr-2 h-4 w-4" />
          <span>System</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}// Alternative simple toggle button
export function SimpleThemeToggle() {
  const { theme, setTheme } = useTheme()
  const [mounted, setMounted] = React.useState(false)  React.useEffect(() => {
    setMounted(true)
  }, [])  if (!mounted) return null  return (
    <Button
      variant="outline"
      size="icon"
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
    >
      <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>
  )
}

6. Creating the Main Application {#main-app}

Update your main page src/app/page.tsx with modern Next.js 15 patterns:

import { ThemeToggle } from "@/components/theme-toggle"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
export default function Home() {
  return (
    <div className="min-h-screen bg-background transition-colors">
      {/* Header */}
      <header className="sticky top-0 z-50 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
        <div className="container mx-auto px-4 py-4 flex justify-between items-center">
          <div className="flex items-center space-x-2">
            <h1 className="text-2xl font-bold bg-gradient-to-r from-primary to-primary/70 bg-clip-text text-transparent">
              My Themed App
            </h1>
            <span className="text-xs bg-primary/10 text-primary px-2 py-1 rounded-full">
              Next.js 15
            </span>
          </div>
          <ThemeToggle />
        </div>
      </header>      {/* Hero Section */}
      <section className="container mx-auto px-4 py-16 text-center">
        <h2 className="text-4xl font-bold mb-4">
          Modern Theming with{" "}
          <span className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
            Tailwind CSS v4
          </span>
        </h2>
        <p className="text-xl text-muted-foreground mb-8 max-w-2xl mx-auto">
          Experience seamless dark/light mode switching with the latest Next.js 15 
          and Tailwind CSS v4 features.
        </p>
        <Button size="lg">
          Get Started
        </Button>
      </section>      {/* Features Grid */}
      <main className="container mx-auto px-4 py-8">
        <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
          <Card className="hover:shadow-lg transition-shadow">
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                ⚡ Next.js 15
              </CardTitle>
              <CardDescription>
                Latest features and performance improvements
              </CardDescription>
            </CardHeader>
            <CardContent>
              <ul className="space-y-2 text-sm">
                <li>✅ React 19 support</li>
                <li>✅ Improved caching</li>
                <li>✅ Better performance</li>
                <li>✅ Turbopack support</li>
              </ul>
              <Button className="mt-4" variant="outline">
                Learn More
              </Button>
            </CardContent>
          </Card>          <Card className="hover:shadow-lg transition-shadow">
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                🎨 Tailwind CSS v4
              </CardTitle>
              <CardDescription>
                New CSS-first configuration approach
              </CardDescription>
            </CardHeader>
            <CardContent>
              <ul className="space-y-2 text-sm">
                <li>✅ @theme directive</li>
                <li>✅ Better performance</li>
                <li>✅ Simplified config</li>
                <li>✅ Enhanced DX</li>
              </ul>
              <Button className="mt-4" variant="outline">
                Explore
              </Button>
            </CardContent>
          </Card>          <Card className="hover:shadow-lg transition-shadow">
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                🌙 Theme System
              </CardTitle>
              <CardDescription>
                Professional dark/light mode implementation
              </CardDescription>
            </CardHeader>
            <CardContent>
              <ul className="space-y-2 text-sm">
                <li>✅ System detection</li>
                <li>✅ Smooth transitions</li>
                <li>✅ Custom colors</li>
                <li>✅ Accessibility ready</li>
              </ul>
              <Button className="mt-4" variant="outline">
                Customize
              </Button>
            </CardContent>
          </Card>
        </div>
      </main>      {/* Footer */}
      <footer className="border-t mt-16">
        <div className="container mx-auto px-4 py-8 text-center text-muted-foreground">
          <p>Built with Next.js 15, Tailwind CSS v4, and shadcn/ui</p>
        </div>
      </footer>
    </div>
  )
}

7. Customizing Colors with tweakcn and Tailwind CSS v4 {#tweakcn-customization}

With Tailwind CSS v4’s new @theme directive, color customization becomes more intuitive. Here's how to work with tweakcn:

Using tweakcn with Tailwind CSS v4

  1. Visit tweakcn.com

  2. Choose your base theme

  3. Customize colors using the visual editor

  4. Copy the generated theme configuration

  5. Convert to Tailwind CSS v4 format

Manual Color Customization with @theme

Create custom color schemes by extending your globals.css:

/* Custom Blue Theme */
@theme blue {
  --color-primary: #2563eb;
  --color-primary-foreground: #ffffff;
  --color-secondary: #3b82f6;
  --color-accent: #dbeafe;
}
/* Custom Green Theme */
@theme green {
  --color-primary: #16a34a;
  --color-primary-foreground: #ffffff;
  --color-secondary: #22c55e;
  --color-accent: #dcfce7;
}/* Custom Purple Theme */
@theme purple {
  --color-primary: #9333ea;
  --color-primary-foreground: #ffffff;
  --color-secondary: #a855f7;
  --color-accent: #f3e8ff;
}

Dynamic Theme Switching

Create a theme context for multiple color schemes:

"use client"
import React, { createContext, useContext, useState } from "react"type ColorTheme = "default" | "blue" | "green" | "purple"interface ColorThemeContextType {
  colorTheme: ColorTheme
  setColorTheme: (theme: ColorTheme) => void
}const ColorThemeContext = createContext<ColorThemeContextType | undefined>(undefined)export function ColorThemeProvider({ children }: { children: React.ReactNode }) {
  const [colorTheme, setColorTheme] = useState<ColorTheme>("default")  React.useEffect(() => {
    document.documentElement.setAttribute("data-color-theme", colorTheme)
  }, [colorTheme])  return (
    <ColorThemeContext.Provider value={{ colorTheme, setColorTheme }}>
      {children}
    </ColorThemeContext.Provider>
  )
}export const useColorTheme = () => {
  const context = useContext(ColorThemeContext)
  if (!context) {
    throw new Error("useColorTheme must be used within ColorThemeProvider")
  }
  return context
}

8. Advanced Theming Techniques with Next.js 15 {#advanced-theming}

Enhanced System Theme Detection

With Next.js 15 and React 19, we can create more sophisticated theme detection:

"use client"
import { useTheme } from "next-themes"
import { useEffect, useState } from "react"export function useAdvancedTheme() {
  const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>('light')
  const [reducedMotion, setReducedMotion] = useState(false)
  const [highContrast, setHighContrast] = useState(false)
  const { theme, setTheme } = useTheme()  useEffect(() => {
    // System theme detection
    const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
    const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
    const contrastQuery = window.matchMedia('(prefers-contrast: high)')    const updateSystemTheme = (e: MediaQueryListEvent) => {
      setSystemTheme(e.matches ? 'dark' : 'light')
    }    const updateMotionPreference = (e: MediaQueryListEvent) => {
      setReducedMotion(e.matches)
      document.documentElement.setAttribute('data-reduced-motion', e.matches.toString())
    }    const updateContrastPreference = (e: MediaQueryListEvent) => {
      setHighContrast(e.matches)
      document.documentElement.setAttribute('data-high-contrast', e.matches.toString())
    }    // Initial setup
    setSystemTheme(darkModeQuery.matches ? 'dark' : 'light')
    setReducedMotion(motionQuery.matches)
    setHighContrast(contrastQuery.matches)    // Add listeners
    darkModeQuery.addEventListener('change', updateSystemTheme)
    motionQuery.addEventListener('change', updateMotionPreference)
    contrastQuery.addEventListener('change', updateContrastPreference)    return () => {
      darkModeQuery.removeEventListener('change', updateSystemTheme)
      motionQuery.removeEventListener('change', updateMotionPreference)
      contrastQuery.removeEventListener('change', updateContrastPreference)
    }
  }, [])  return { 
    systemTheme, 
    currentTheme: theme, 
    setTheme,
    reducedMotion,
    highContrast
  }
}

CSS Container Queries for Responsive Theming

With Tailwind CSS v4, you can use container queries for responsive theming:

@theme {
  /* Container-based responsive theming */
  @container (min-width: 768px) {
    --color-primary: #3b82f6;
  }
  
  @container (min-width: 1024px) {
    --color-primary: #2563eb;
  }
}

Smooth Theme Transitions with CSS View Transitions

Implement smooth transitions using the View Transitions API:

"use client"
import { useTheme } from "next-themes"export function useViewTransitionTheme() {
  const { setTheme } = useTheme()  const setThemeWithTransition = (newTheme: string) => {
    if (!document.startViewTransition) {
      setTheme(newTheme)
      return
    }    document.startViewTransition(() => {
      setTheme(newTheme)
    })
  }  return { setThemeWithTransition }
}

Add the corresponding CSS for view transitions:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.3s;
}
::view-transition-old(root) {
  animation-name: fade-out;
}::view-transition-new(root) {
  animation-name: fade-in;
}@keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

Theme-aware Components with Better Performance

Create optimized theme-aware components:

"use client"
import { useTheme } from "next-themes"
import { memo, useMemo } from "react"
import { Card } from "@/components/ui/card"interface ThemeAwareCardProps {
  children: React.ReactNode
  variant?: "default" | "accent" | "muted"
}export const ThemeAwareCard = memo(function ThemeAwareCard({ 
  children, 
  variant = "default" 
}: ThemeAwareCardProps) {
  const { theme } = useTheme()
  
  const cardStyles = useMemo(() => {
    const baseStyles = "transition-all duration-300"
    
    switch (variant) {
      case "accent":
        return `${baseStyles} bg-accent/50 border-accent`
      case "muted":
        return `${baseStyles} bg-muted/30 border-muted`
      default:
        return `${baseStyles} bg-card border-border`
    }
  }, [variant])  return (
    <Card className={cardStyles}>
      {children}
    </Card>
  )
})

9. Performance Optimization and Testing {#testing}

Preventing FOUC (Flash of Unstyled Content)

Create an optimized theme script for Next.js 15:

// src/components/theme-script.tsx
export function ThemeScript() {
  return (
    <script
      dangerouslySetInnerHTML={{
        __html: `
          (function() {
            try {
              var theme = localStorage.getItem('theme');
              var systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
              var currentTheme = theme === 'system' ? systemTheme : theme;
              
              if (currentTheme === 'dark' || (!theme && systemTheme === 'dark')) {
                document.documentElement.classList.add('dark');
              }
              
              // Set initial color theme
              var colorTheme = localStorage.getItem('color-theme') || 'default';
              document.documentElement.setAttribute('data-color-theme', colorTheme);
            } catch (e) {}
          })();
        `,
      }}
    />
  )
}

Add this to your layout.tsx before the body content:

import { ThemeScript } from "@/components/theme-script"
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <ThemeScript />
      </head>
      <body className={inter.className}>
        {/* ... rest of your layout */}
      </body>
    </html>
  )
}

Testing Theme Implementation

Create comprehensive tests for your theme system:

// __tests__/theme.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { ThemeProvider } from 'next-themes'
import { ThemeToggle } from '@/components/theme-toggle'
describe('Theme System', () => {
  const renderWithTheme = (component: React.ReactElement) => {
    return render(
      <ThemeProvider attribute="class" defaultTheme="light">
        {component}
      </ThemeProvider>
    )
  }  test('theme toggle renders correctly', () => {
    renderWithTheme(<ThemeToggle />)
    expect(screen.getByRole('button')).toBeInTheDocument()
  })  test('theme switching works', () => {
    renderWithTheme(<ThemeToggle />)
    const button = screen.getByRole('button')
    fireEvent.click(button)
    
    const darkOption = screen.getByText('Dark')
    fireEvent.click(darkOption)
    
    expect(document.documentElement).toHaveClass('dark')
  })
})

Performance Monitoring

Monitor theme performance with Next.js 15’s built-in analytics:

// src/lib/analytics.ts
export function trackThemeChange(theme: string) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', 'theme_change', {
      theme_name: theme,
      timestamp: new Date().toISOString(),
    })
  }
}

Accessibility Enhancements

Ensure your themes meet WCAG guidelines:

@theme {
  /* High contrast mode */
  @media (prefers-contrast: high) {
    --color-border: #000000;
    --color-foreground: #000000;
    --color-background: #ffffff;
  }
  
  /* Reduced motion */
  @media (prefers-reduced-motion: reduce) {
    * {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
    }
  }
  
  /* Focus indicators */
  --focus-ring: 2px solid var(--color-primary);
  --focus-ring-offset: 2px;
}
/* Enhanced focus styles */
.focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

Conclusion

Congratulations! You now have a cutting-edge Next.js 15 application with professional theming capabilities using Tailwind CSS v4! This modern setup provides:

🚀 Latest Technology Stack:

  • Next.js 15 with React 19 support and improved performance

  • Tailwind CSS v4 with new @theme directive and enhanced DX

  • shadcn/ui components with perfect theme integration

  • TypeScript for type safety and better development experience

🎨 Advanced Theming Features:

  • Seamless theme switching between light, dark, and system modes

  • CSS-first configuration with Tailwind CSS v4’s new approach

  • Customizable color schemes using modern CSS custom properties

  • System preference detection with real-time updates

  • Smooth transitions and enhanced user experience

⚡ Performance & Accessibility:

  • Zero FOUC (Flash of Unstyled Content) implementation

  • Accessible theme switching following WCAG guidelines

  • Optimized rendering with React 19’s concurrent features

  • Responsive theming with container queries support

Key Improvements in This Setup

Next.js 15 Benefits:

  • Faster build times and improved caching

  • Better TypeScript integration

  • Enhanced App Router performance

  • React 19 concurrent features

Tailwind CSS v4 Advantages:

  • Simplified configuration with @theme directive

  • Better performance and smaller bundle sizes

  • Enhanced developer experience

  • Modern CSS features support

Next Steps to Enhance Your App

  1. Explore Advanced Features:

  • Implement view transitions for smoother theme changes

  • Add container queries for responsive theming

  • Create custom theme variants for different sections

2 . Enhance User Experience:

  • Add theme persistence across sessions

  • Implement user preference learning

  • Create animated theme transitions

3. Extend Functionality:

  • Add more shadcn/ui components

  • Implement theme scheduling (auto dark mode at night)

  • Create custom color palette generator

4. Optimize Performance:

  • Implement code splitting for theme components

  • Add performance monitoring

  • Optimize for Core Web Vitals

5. Testing & Deployment:

  • Write comprehensive theme tests

  • Set up E2E testing with Playwright

  • Deploy to Vercel with optimizations

Additional Resources

🎥 Complete Video Tutorial

For a comprehensive visual walkthrough of this entire process, including live coding and troubleshooting tips, watch our complete tutorial:

Next.js 15 Theme Setup — Complete https://youtu.be/8p4QgBT6ZpwBangla Tutorial

The video demonstrates:

  • Step-by-step setup process

  • Real-time problem solving

  • Best practices and tips

  • Advanced customization techniques

  • Performance optimization strategies

Why Watch the Video?

While this written guide provides all the code and explanations, the video tutorial offers:

  • Visual learning experience with live coding

  • Troubleshooting common issues that you might encounter

  • Additional tips and tricks not covered in the written guide

  • Bengali explanations for better understanding

  • Interactive Q&A in the comments section

Ready to build amazing themed applications? Start coding and don’t forget to share your creations! 🚀

Have questions or need help? Drop a comment on the YouTube video or reach out to the community!

Подобається цей допис?

Купити для Noor Mohammad каву

Більше від Noor Mohammad

КонфіденційністьУмовиПоскаржитись