{"id":20548408,"url":"https://github.com/react18-tools/nextjs-themes-ultra","last_synced_at":"2025-07-19T05:03:23.410Z","repository":{"id":224013812,"uuid":"761568593","full_name":"react18-tools/nextjs-themes-ultra","owner":"react18-tools","description":"🤟 👉 Theme with confidence and [Unleash the Power of React Server Components](https://medium.com/javascript-in-plain-english/unleash-the-power-of-react-server-components-eb3fe7201231) ","archived":false,"fork":false,"pushed_at":"2025-04-08T16:14:26.000Z","size":6308,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T17:26:38.311Z","etag":null,"topics":["frontend","javascript","nextjs","nextjs13","nextjs14","nodejs","react18","theme"],"latest_commit_sha":null,"homepage":"https://nextjs-themes-ultra.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/react18-tools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"contributing.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["react18-tools","mayank1513"],"polar":"mayank1513","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://pages.razorpay.com/mayank1513"]}},"created_at":"2024-02-22T04:26:36.000Z","updated_at":"2025-04-08T16:14:31.000Z","dependencies_parsed_at":"2024-02-27T17:29:44.083Z","dependency_job_id":"e702a168-14c6-44ca-8afe-b761420515c7","html_url":"https://github.com/react18-tools/nextjs-themes-ultra","commit_stats":{"total_commits":921,"total_committers":2,"mean_commits":460.5,"dds":"0.0032573289902280145","last_synced_commit":"9d60a68e8f6750ae302fd9b3e68163be04b864f8"},"previous_names":["react18-tools/nextjs-themes-ultralight","react18-tools/nextjs-themes-ultra"],"tags_count":6,"template":false,"template_full_name":"react18-tools/turborepo-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-themes-ultra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-themes-ultra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-themes-ultra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-themes-ultra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react18-tools","download_url":"https://codeload.github.com/react18-tools/nextjs-themes-ultra/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248852181,"owners_count":21171842,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frontend","javascript","nextjs","nextjs13","nextjs14","nodejs","react18","theme"],"created_at":"2024-11-16T02:13:21.929Z","updated_at":"2025-04-14T10:53:08.645Z","avatar_url":"https://github.com/react18-tools.png","language":"TypeScript","funding_links":["https://github.com/sponsors/react18-tools","https://github.com/sponsors/mayank1513","https://polar.sh/mayank1513","https://pages.razorpay.com/mayank1513"],"categories":[],"sub_categories":[],"readme":"# Nextjs-Themes-Ultra \u003cimg src=\"https://github.com/react18-tools/nextjs-themes-ultra/blob/main/popper.png?raw=true\" style=\"height: 40px\"/\u003e\n\n[![test](https://github.com/react18-tools/nextjs-themes-ultra/actions/workflows/test.yml/badge.svg)](https://github.com/react18-tools/nextjs-themes-ultra/actions/workflows/test.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/85f6447e649201924a2c/maintainability)](https://codeclimate.com/github/react18-tools/nextjs-themes-ultra/maintainability) [![codecov](https://codecov.io/gh/react18-tools/nextjs-themes-ultra/graph/badge.svg)](https://codecov.io/gh/react18-tools/nextjs-themes-ultra) [![Version](https://img.shields.io/npm/v/nthul.svg?colorB=green)](https://www.npmjs.com/package/nthul) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/d18m/nthul.svg)](https://www.npmjs.com/package/nthul) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/nthul) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/from-referrer/)\n\nNextjs-Themes-Ultra is a comprehensive library designed to unlock the full potential of React 18 server components.\n🤟 👉 [Unleash the Power of React Server Components](https://medium.com/javascript-in-plain-english/unleash-the-power-of-react-server-components-eb3fe7201231)\n\n\u003e A canonical package with a longer and more descriptive name is also published as `nextjs-themes-ultra`\n\n## Motivation\n\nI created the `nextjs-themes` library to achieve functionality similar to `next-themes` with React Server Components. While it worked well, I encountered issues with tree-shaking and noticed some rarely used functions could be removed or replaced to improve performance and readability.\n\nI had plans to update the main library [`nextjs-themes`](https://github.com/react18-tools/nextjs-themes), but it required ensuring minimal changes to the existing APIs. Therefore, I created a new library that has the potential to be a better alternative in most cases.\n\n## Features\n\n✅ Perfect dark mode with just 2 lines of code\n\n✅ Works with Tailwind CSS\n\n✅ Fully tree-shakable (`import from nthul/client/theme-switcher`)\n\n✅ Designed for excellence\n\n✅ Full TypeScript support\n\n✅ Unleash the full power of React 18 Server components\n\n✅ System setting with `prefers-color-scheme`\n\n✅ Themed browser UI with `color-scheme`\n\n✅ Support for Next.js 13 \u0026 14 `appDir`\n\n✅ No flash on load (supports SSG, SSR, ISG, and Server Components)\n\n✅ Sync theme across tabs and windows (can opt-out by passing `dontSync` to `ThemeSwitcher`)\n\n✅ Apply custom transitions when changing themes\n\n✅ Force pages to specific themes (requires assigning `className`, detailed techniques coming soon)\n\n✅ Manipulate theme via the `useTheme` hook\n\n✅ Documented with [Typedoc](https://react18-tools.github.io/nextjs-themes-ultra) ([Docs](https://react18-tools.github.io/nextjs-themes-ultra))\n\n✅ Use combinations of `th-` and `dark` or `light` classes for dark/light variants of themes\n\n✅ Avoids storing cookies when not using the corresponding `ServerTarget`\n\n✅ Compatible with all build systems/tools/frameworks for React 18\n\n\u003e Feel free to [request](https://github.com/react18-tools/nextjs-themes-ultra/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=feature_request.md\u0026title=) or [discuss](https://github.com/react18-tools/nextjs-themes-ultra/discussions) new features, or [report bugs](https://github.com/react18-tools/nextjs-themes-ultra/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=bug_report.md\u0026title=).\n\n\u003e \u003cimg src=\"https://github.com/react18-tools/nextjs-themes-ultra/blob/main/popper.png?raw=true\" style=\"height: 20px\"/\u003e Please consider starring [this repository](https://github.com/react18-tools/nextjs-themes-ultra) and sharing it with your friends.\n\n## Install\n\n\u003e A canonical package with a longer and more descriptive name is also published as `nextjs-themes-ultra`\n\n```bash\n$ pnpm add nthul\n```\n\n**_or_**\n\n```bash\n$ npm install nthul\n```\n\n**_or_**\n\n```bash\n$ yarn add nthul\n```\n\n## Want a Lite Version? [![npm bundle size](https://img.shields.io/bundlephobia/minzip/nthul-lite)](https://www.npmjs.com/package/nthul-lite) [![Version](https://img.shields.io/npm/v/nthul-lite.svg?colorB=green)](https://www.npmjs.com/package/nthul-lite) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/d18m/nthul-lite.svg)](https://www.npmjs.com/package/nthul-lite)\n\n```bash\n$ pnpm add nthul-lite\n```\n\n**_or_**\n\n```bash\n$ npm install nthul-lite\n```\n\n**_or_**\n\n```bash\n$ yarn add nthul-lite\n```\n\n\u003e You need `r18gs` as a peer-dependency\n\n## Usage\n\n\u003e Please explore `examples` and `packages/shared-ui` for working examples. (updates coming soon...)\n\n### SPA (e.g., Vite, CRA) and Next.js pages directory (No server components)\n\nTo add dark mode support, modify `_app` as follows:\n\n```js\nimport { ThemeSwitcher, ColorSwitch } from \"nthul/client\"; // for better tree-shaking\n\nfunction MyApp({ Component, pageProps }) {\n  return (\n    \u003c\u003e\n      \u003cThemeSwitcher /\u003e\n      \u003cheader\u003e\n        \u003cColorSwitch /\u003e\n      \u003c/header\u003e\n      \u003cComponent {...pageProps} /\u003e\n    \u003c/\u003e\n  );\n}\n\nexport default MyApp;\n```\n\n⚡🎉Boom! Just a couple of lines and your dark mode is ready, complete with a color switch for user preferences. Check out examples for advanced usage.\n\n\u003e For `vite` or any other build tool, find a similar root component, e.g., `\u003cApp /\u003e` in `CRA` and `vite`.\n\n### With Next.js `app` router (Server Components)\n\nIf your app serves mostly static content, you can avoid SSR overhead. When using this approach, use CSS general sibling combinator (~) to ensure your themed CSS is applied properly. See (HTML \u0026 CSS)[#html--css].\n\nUpdate your `app/layout.jsx` to add `ThemeSwitcher` and `ServerTarget`. `ServerTarget` avoids a flash of un-themed content on reload.\n\n```tsx\n// app/layout.jsx\nimport { ThemeSwitcher } from \"nthul/client/theme-switcher\"; // for better tree-shaking\nimport { ServerTarget } from \"nthul/server/nextjs\";\n\nexport default function Layout({ children }) {\n  return (\n    \u003chtml lang=\"en\"\u003e\n      \u003chead /\u003e\n      \u003cbody\u003e\n        /** use ServerTarget as first element inside body */\n        \u003cServerTarget /\u003e\n        \u003cThemeSwitcher /\u003e\n        {children}\n      \u003c/body\u003e\n    \u003c/html\u003e\n  );\n}\n```\n\nYou just added multiple theme and color-scheme modes and can use Server Component! Isn't that awesome?\n\n### ColorSwitch\n\nAn elegant color switch to toggle color schemes (\"dark\" | \"light\" | \"system\").\n\n```tsx\n\u003cColorSwitch /\u003e\n```\n\n### HTML \u0026 CSS\n\nYour Next.js app fully supports dark mode, including system preference with `prefers-color-scheme`. The theme is also synced between tabs. By default, `nthul` modifies the `className` on the `html` element, which you can use to style your app:\n\n```css\n:root {\n  --background: white;\n  --foreground: black;\n}\n\n.dark {\n  --background: black;\n  --foreground: white;\n}\n\n/* for custom themes */\n\n.th-theme1 {\n  --background: red;\n  --foreground: yellow;\n}\n\n/* for custom theme with dark and light variants */\n\n.dark.th-theme2 {\n  --background: blue;\n  --foreground: white;\n}\n\n.light.th-theme2 {\n  --background: white;\n  --foreground: blue;\n}\n\n/* for scoped containers add .nth-scoped call as well - required only when using containerized themes. */\n.nth-scoped.th-.dark {\n  ...\n}\n\n.nth-scoped.th-theme.dark {\n  ...\n}\n```\n\nSee the [Example CSS file](https://github.com/react18-tools/nextjs-themes-ultra/blob/main/packages/shared-ui/src/globals.css).\n\n#### When using `ServerTarget`\n\nWhen using `ServerTarget`, use the CSS general sibling combinator (~) since `ServerTarget` does not wrap your app.\n\nReplace `.selector` with a combination of selectors from the description above.\n\n```css\n.selector,\n.selector *,\n.selector ~ *,\n.selector ~ * * {\n  --th-variable: value;\n}\n```\n\nWe encourage using this pattern to define your theme variables in CSS to avoid unwanted overrides.\n\n## Images\n\nYou can also show different images based on the current theme.\n\n```jsx\nimport Image from \"next/image\";\nimport { useTheme } from \"nthul/hooks\";\n\nfunction ThemedImage() {\n  const { resolvedColorScheme } = useTheme();\n  let src;\n\n  switch (resolvedColorScheme) {\n    case \"light\":\n      src = \"/light-mode-image.png\";\n      break;\n    case \"dark\":\n      src = \"/dark-mode-image.png\";\n      break;\n    default:\n      src = \"/default-image.png\";\n      break;\n  }\n\n  return \u003cImage src={src} alt=\"Themed Image\" /\u003e;\n}\n```\n\n### useTheme\n\nIn case your components need to know the current theme and be able to change it. The `useTheme` hook provides theme information:\n\n```js\nimport { useTheme } from \"nthul\";\n\nconst ThemeChanger = () =\u003e {\n  const { theme, setTheme } = useTheme();\n\n  return (\n    \u003cdiv\u003e\n      The current theme is: {theme}\n      \u003cbutton onClick={() =\u003e setTheme(\"light\")}\u003eLight Mode\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setTheme(\"dark\")}\u003eDark Mode\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n`useTheme` hook will return following object.\n\n```ts\ninterface UseTheme {\n  theme: string;\n  colorSchemePreference: \"dark\" | \"light\" | \"system\";\n  systemColorScheme: \"dark\" | \"light\";\n  resolvedColorScheme: \"dark\" | \"light\";\n  setColorSchemePreference: (colorSchemePreference: ColorSchemePreference) =\u003e void;\n  setTheme: (theme: string) =\u003e void;\n}\n```\n\n## Force per page theme and color-scheme\n\nWe have not added any components or hooks for forcing `theme` and `color-scheme` per page or per element basis. As this is a rarely used scenario. However, you can acheive this by applying appropreate calssNames.\n\n```tsx\n// force a theme for the page\nexport default function Page() {\n  return \u003cdiv className=\"dark nth-scoped th-theme1\"\u003e...\u003c/div\u003e;\n}\n```\n\n\u003e We are open to listening your feedback - [Discussions](https://github.com/react18-tools/nextjs-themes-ultra/discussions)\n\n### With Styled Components and any CSS-in-JS\n\nNext Themes is completely CSS independent, it will work with any library. For example, with Styled Components you just need to `createGlobalStyle` in your custom App:\n\n```js\n// pages/_app.js\nimport { createGlobalStyle } from \"styled-components\";\nimport { ThemeSwitcher } from \"nthul\";\n\n// Your themeing variables\nconst GlobalStyle = createGlobalStyle`\n  :root {\n    --fg: #000;\n    --bg: #fff;\n  }\n\n  [data-theme=\"dark\"] {\n    --fg: #fff;\n    --bg: #000;\n  }\n`;\n\nfunction MyApp({ Component, pageProps }) {\n  return (\n    \u003c\u003e\n      \u003cGlobalStyle /\u003e\n      \u003cThemeSwitcher /\u003e\n      \u003cComponent {...pageProps} /\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n### With Tailwind\n\nIn your `tailwind.config.js`, set the dark mode property to class:\n\n```js\n// tailwind.config.js\nmodule.exports = {\n  darkMode: \"class\",\n};\n```\n\n⚡🎉Boom! You are ready to use darkTheme in tailwind.\n\n\u003e Caution! Your class must be set to `\"dark\"`, which is the default value we have used for this library. Tailwind, as of now, requires that class name must be `\"dark\"` for dark-theme.\n\nThat's it! Now you can use dark-mode specific classes:\n\n```tsx\n\u003ch1 className=\"text-black dark:text-white\"\u003e\n```\n\n## Performance\n\n`nthul` is designed to be fully tree-shakable and only includes the code you use. For example, if you only use the `useTheme` hook, the rest of the library's code will be removed during the build process.\n\n## Contributing\n\nWe welcome contributions! Please check out the [Contributing Guide](https://github.com/react18-tools/nextjs-themes-ultra/blob/main/CONTRIBUTING.md) for more details.\n\n### 🤩 Don't forget to star [this repo](https://github.com/react18-tools/nextjs-themes-ultra)!\n\nLooking for a hands-on course to get started with Turborepo? Check out [React and Next.js with TypeScript](https://mayank-chaudhari.vercel.app/courses/react-and-next-js-with-typescript) and [The Game of Chess with Next.js, React, and TypeScript](https://www.udemy.com/course/game-of-chess-with-nextjs-react-and-typescrypt/?referralCode=851A28F10B254A8523FE).\n\n![Repo Stats](https://repobeats.axiom.co/api/embed/85eec5cd9a0ede65ac366f834ada1a170ef775c8.svg \"Repobeats analytics image\")\n\n## License\n\n[MPL-2.0](https://github.com/react18-tools/nextjs-themes-ultra/blob/main/LICENSE)\n\nFeel free to use, modify, and distribute this library as per the terms of the MPL-2.0 license.\n\n\u003e \u003cimg src=\"https://github.com/react18-tools/nextjs-themes-ultra/blob/main/popper.png?raw=true\" style=\"height: 20px\"/\u003e Please consider enrolling in [our courses](https://mayank-chaudhari.vercel.app/courses) or [sponsoring](https://github.com/sponsors/mayank1513) our work.\n\n\u003chr /\u003e\n\n\u003cp align=\"center\" style=\"text-align:center\"\u003ewith 💖 by \u003ca href=\"https://mayank-chaudhari.vercel.app\" target=\"_blank\"\u003eMayank Kumar Chaudhari\u003c/a\u003e\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact18-tools%2Fnextjs-themes-ultra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact18-tools%2Fnextjs-themes-ultra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact18-tools%2Fnextjs-themes-ultra/lists"}