Written by: Geoffrey Callaghan

how to create a Next.js theme

How To Create A Next.Js Theme

Creating a Next.js theme involves designing a set of reusable components, styles, and configurations that can be shared across multiple Next.js projects. Unlike traditional static site generators, Next.js themes are more about creating a reusable UI component library or design system. Here’s a step-by-step guide to help you create a Next.js theme:

Step 1: Set Up Your Environment

  1. Install Node.js and npm: Ensure you have Node.js and npm (or Yarn) installed. You can download and install from nodejs.org.

  2. Create a New Next.js Project: Use the Next.js CLI to create a new project.

    npx create-next-app nextjs-theme
    cd nextjs-theme

Step 2: Organize Your Theme Directory

  1. Create a theme Directory: Inside your Next.js project, create a directory for your theme components, styles, and utilities.

    mkdir theme
    cd theme
    mkdir components styles utils
  2. Create a package.json for Your Theme: Initialize the theme directory as a separate npm package.

    npm init -y

Step 3: Develop Theme Components

  1. Create a Button Component: Create a simple Button component as an example.

    // theme/components/Button.js
    import React from 'react';
    import PropTypes from 'prop-types';
    import './Button.css';
    
    const Button = ({ children, onClick, className }) => (
      <button className={`btn ${className}`} onClick={onClick}>
        {children}
      </button>
    );
    
    Button.propTypes = {
      children: PropTypes.node.isRequired,
      onClick: PropTypes.func,
      className: PropTypes.string,
    };
    
    Button.defaultProps = {
      onClick: () => {},
      className: '',
    };
    
    export default Button;
  2. Create a CSS File for the Button:

    /* theme/components/Button.css */
    .btn {
      padding: 10px 20px;
      border: none;
      border-radius: 4px;
      background-color: #0070f3;
      color: white;
      cursor: pointer;
      transition: background-color 0.3s;
    }
    
    .btn:hover {
      background-color: #005bb5;
    }

Step 4: Create a Theme Provider

  1. Create a Theme Context: Set up a context to provide theme-related data and methods.

    // theme/ThemeContext.js
    import React, { createContext, useContext, useState } from 'react';
    
    const ThemeContext = createContext();
    
    export const useTheme = () => useContext(ThemeContext);
    
    export const ThemeProvider = ({ children }) => {
      const [theme, setTheme] = useState('light');
    
      const toggleTheme = () => {
        setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
      };
    
      return (
        <ThemeContext.Provider value={{ theme, toggleTheme }}>
          {children}
        </ThemeContext.Provider>
      );
    };
  2. Use the Theme Provider in Your App: Wrap your application with the ThemeProvider.

    // pages/_app.js
    import { ThemeProvider } from '../theme/ThemeContext';
    import '../styles/globals.css';
    
    function MyApp({ Component, pageProps }) {
      return (
        <ThemeProvider>
          <Component {...pageProps} />
        </ThemeProvider>
      );
    }
    
    export default MyApp;

Step 5: Using Your Theme Components

  1. Import and Use Theme Components: Use the Button component in your pages or other components.

    // pages/index.js
    import React from 'react';
    import Button from '../theme/components/Button';
    import { useTheme } from '../theme/ThemeContext';
    
    export default function Home() {
      const { theme, toggleTheme } = useTheme();
    
      return (
        <div className={`container ${theme}`}>
          <h1>Welcome to My Themed Next.js App</h1>
          <Button onClick={toggleTheme}>Toggle Theme</Button>
          <style jsx global>{`
            .container {
              padding: 20px;
              text-align: center;
            }
            .container.light {
              background-color: #ffffff;
              color: #000000;
            }
            .container.dark {
              background-color: #000000;
              color: #ffffff;
            }
          `}</style>
        </div>
      );
    }

Step 6: Publish and Share Your Theme

  1. Create an Entry Point for Your Theme: Export your components and context from a single file.

    // theme/index.js
    export { default as Button } from './components/Button';
    export { ThemeProvider, useTheme } from './ThemeContext';
  2. Link Your Theme Locally: In your Next.js project root, create a symlink to the theme package for development purposes.

    npm link ../theme

    In nextjs-theme/package.json, add your theme as a dependency.

    "dependencies": {
      "theme": "file:../theme"
    }
  3. Publish Your Theme: If you want to share your theme, publish it to npm.

    cd theme
    npm publish --access public

Final Steps

  1. Test Your Theme: Test the theme in different projects to ensure it works as expected.

  2. Document Your Theme: Provide clear documentation on how to use and customize your theme in a README.md file.

By following these steps, you can create a reusable Next.js theme that includes components, styles, and context for shared functionality. This allows you to maintain a consistent design across multiple Next.js projects.