{"id":20548396,"url":"https://github.com/react18-tools/nextjs-darkmode","last_synced_at":"2025-04-14T10:52:58.406Z","repository":{"id":243490417,"uuid":"810915004","full_name":"react18-tools/nextjs-darkmode","owner":"react18-tools","description":"A lightweight library for managing dark mode, accommodating both user preferences and the system preference.","archived":false,"fork":false,"pushed_at":"2025-04-11T01:53:57.000Z","size":5341,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T02:48:57.110Z","etag":null,"topics":["dark-mode","dark-theme","frontend","javascript","nextjs","nextjs14","nodejs","react-server-components","react18","react18-tools","typescript"],"latest_commit_sha":null,"homepage":"https://nextjs-darkmode-jade.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,"zenodo":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-06-05T15:34:35.000Z","updated_at":"2025-04-11T01:54:01.000Z","dependencies_parsed_at":"2024-06-09T10:56:49.901Z","dependency_job_id":"feef82b2-1288-46fe-beb2-a8ce01b73033","html_url":"https://github.com/react18-tools/nextjs-darkmode","commit_stats":null,"previous_names":["react18-tools/nextjs-darkmode"],"tags_count":19,"template":false,"template_full_name":"react18-tools/turborepo-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-darkmode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-darkmode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-darkmode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react18-tools%2Fnextjs-darkmode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react18-tools","download_url":"https://codeload.github.com/react18-tools/nextjs-darkmode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248868807,"owners_count":21174755,"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":["dark-mode","dark-theme","frontend","javascript","nextjs","nextjs14","nodejs","react-server-components","react18","react18-tools","typescript"],"created_at":"2024-11-16T02:13:18.323Z","updated_at":"2025-04-14T10:52:58.384Z","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 Darkmode \u003cimg src=\"https://github.com/react18-tools/nextjs-darkmode/blob/main/popper.png?raw=true\" style=\"height: 40px\"/\u003e\n\n[![test](https://github.com/react18-tools/nextjs-darkmode/actions/workflows/test.yml/badge.svg)](https://github.com/react18-tools/nextjs-darkmode/actions/workflows/test.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/ebffdafb7f4984d742b6/maintainability)](https://codeclimate.com/github/react18-tools/nextjs-darkmode/maintainability) [![codecov](https://codecov.io/gh/react18-tools/nextjs-darkmode/graph/badge.svg)](https://codecov.io/gh/react18-tools/nextjs-darkmode) [![Version](https://img.shields.io/npm/v/nextjs-darkmode.svg?colorB=green)](https://www.npmjs.com/package/nextjs-darkmode) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/d18m/nextjs-darkmode.svg)](https://www.npmjs.com/package/nextjs-darkmode) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/nextjs-darkmode) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/from-referrer/)\n\nNextjs Darkmode is a versatile library crafted to fully utilize React 18 server components, ensuring a seamless dark mode experience in Next.js applications. Lightweight and efficient, it respects both user preferences and system settings through the prefers-color-scheme media query, and integrates effortlessly with React/Vite, Remix, and Next.js.\n\n## Motivation\n\nThe `nextjs-themes` library was initially created to achieve a similar functionality to `next-themes` with React Server Components. While effective, it felt bulky for those supporting only dark/light mode. Thus, `nextjs-darkmode` was developed to offer a minimal footprint while utilizing Next.js Server Components, avoiding any flash of unthemed content, and ensuring theme synchronization with the server.\n\n\u003e For migration guide please refer [Project Wiki](https://github.com/react18-tools/nextjs-darkmode/wiki/1.-Migration-guide)\n\n\u003cdetails\u003e\n\u003csummary\u003e\n\u003ch2 style=\"display:inline-block\"\u003eFeatures\u003c/h2\u003e\n\u003c/summary\u003e\n\n- ✅ Simple API to toggle between dark and light modes\n\n- ✅ Perfect dark mode with just 2 lines of code\n\n- ✅ Compatible with Tailwind CSS, StyledComponents, emotion, Material UI, ...\n\n- ✅ Secure by design - we support `nonce` when you want to apply Content Security Policy\n\n- ✅ Fully treeshakable (e.g., `import from nextjs-darkmode/hooks`)\n\n- ✅ Full TypeScript support\n\n- ✅ Utilizes React 18 Server components\n\n- ✅ Compatible with all React 18 build systems/tools/frameworks\n\n- ✅ System setting with `prefers-color-scheme`\n\n- ✅ Supports 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\n\n- ✅ Apply custom transitions when changing themes\n\n- ✅ Manipulate theme via the `useMode` hook\n\n- ✅ Comprehensive documentation with [Typedoc](https://react18-tools.github.io/nextjs-darkmode)\n\nFeel free to [request new features](https://github.com/react18-tools/nextjs-darkmode/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=feature_request.md\u0026title=), [discuss](https://github.com/react18-tools/nextjs-darkmode/discussions), or [report bugs](https://github.com/react18-tools/nextjs-darkmode/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=bug_report.md\u0026title=).\n\nPlease consider starring [this repository](https://github.com/react18-tools/nextjs-darkmode) and sharing it with your friends.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\n\u003ch2 style=\"display:inline-block\"\u003eGetting Started\u003c/h2\u003e\n\u003c/summary\u003e\n\n### Installation\n\n```bash\n$ pnpm add nextjs-darkmode\n```\n\n**_or_**\n\n```bash\n$ npm install nextjs-darkmode\n```\n\n**_or_**\n\n```bash\n$ yarn add nextjs-darkmode\n```\n\n### Import Styles\n\n\u003e PLease make sure you set `\"moduleResolution\"` to `\"Bundler\"`, `\"Node16\"` or `\"NodeNext\"` in your tsconfig file for export field in package.json to work properly. (Ref)[https://stackoverflow.com/a/74462490/23175171]\n\n\u003e You may need to import styles from `nextjs-darkmode/dist/index.css` depending on your bundler configuration.\n\nImport styles globally or within layout component.\n\n```css\n/* globals.css */\n@import \"nextjs-darkmode/css\";\n```\n\n```tsx\n// layout.tsx\nimport \"nextjs-darkmode/css\";\n```\n\n### Lite Version\n\nFor a lighter version, use `nextjs-darkmode-lite`:\n\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/nextjs-darkmode-lite)](https://www.npmjs.com/package/nextjs-darkmode-lite) [![Version](https://img.shields.io/npm/v/nextjs-darkmode-lite.svg?colorB=green)](https://www.npmjs.com/package/nextjs-darkmode-lite) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/d18m/nextjs-darkmode-lite.svg)](https://www.npmjs.com/package/nextjs-darkmode-lite)\n\n```bash\n$ pnpm add nextjs-darkmode-lite\n```\n\n**_or_**\n\n```bash\n$ npm install nextjs-darkmode-lite\n```\n\n**_or_**\n\n```bash\n$ yarn add nextjs-darkmode-lite\n```\n\n\u003e You need `r18gs` as a peer-dependency.\n\n\u003c/details\u003e\n\n## Usage\n\n\u003e Please explore `examples` and `packages/shared-ui` for more working examples. (updates coming soon...)\n\n### SPA (e.g., Vite, CRA) and Next.js pages directory\n\nModify `_app` to add dark mode support:\n\n```js\nimport { Core } from \"nextjs-darkmode\"; // for better tree-shaking\nimport { Switch } from \"nextjs-darkmode/switch\";\n\nfunction MyApp({ Component, pageProps }) {\n  return (\n    \u003c\u003e\n      \u003cCore /\u003e\n      \u003cheader\u003e\n        \u003cSwitch /\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\n\nUpdate `app/layout.jsx` to add `Core` component.\n\n```tsx\n// app/layout.jsx\nimport { Core } from \"nextjs-darkmode\"; // for better tree-shaking\n\nexport default function Layout({ children }) {\n  return (\n    \u003chtml lang=\"en\"\u003e\n      \u003chead /\u003e\n      \u003cbody\u003e\n        \u003cCore /\u003e\n        {children}\n      \u003c/body\u003e\n    \u003c/html\u003e\n  );\n}\n```\n\n### Switch\n\nAn elegant color switch to toggle color schemes:\n\n```tsx\n\u003cSwitch /\u003e\n```\n\n### HTML \u0026 CSS\n\nFully support dark mode, including system preference with `prefers-color-scheme`. The dark/light mode is synced between tabs and modifies the `className` and data-attributes on the `html` elemnt.\n\n```css\n:root {\n  --background: white;\n  --foreground: black;\n}\n\n.dark {\n  --background: black;\n  --foreground: white;\n}\n\n/* or */\n\n[data-rm=\"dark\"] {...}\n```\n\n#### Using the data-attributes\n\ndata-attributes are very helpful when you want to customize styles in a CSS module file (`styles.module.css`)\n\n`data-rm` -\u003e Resolved Mode\n\n`data-m` -\u003e User's preference\n\n`data-sm` -\u003e System preference\n\n#### Content Security Policy\n\nIf you are using CSP rules for CSS files, you can pass `nonce` argument to the `Core` component. If `nonce` is not supplied transition styles will not be applied. This may allow patched transitions throught the page in some cases.\n\n```tsx\n\u003cCore nonce={yourNonce} t=\"transition: all .5s\" /\u003e\n```\n\n### Images\n\nShow different images based on the current theme:\n\n```ts\nimport Image from \"next/image\";\nimport { useMode } from \"nextjs-darkmode/hooks\";\n\nfunction ThemedImage() {\n  const { resolvedMode } = useMode();\n  let src;\n\n  switch (resolvedMode) {\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### useMode\n\nThe `useMode` hook provides mode information:\n\n```js\nimport { useMode } from \"nextjs-darkmode\";\n\nconst ThemeChanger = () =\u003e {\n  const { resolvedMode, setMode } = useMode();\n\n  return (\n    \u003cdiv\u003e\n      The current resolved mode is: {resolvedMode}\n      \u003cbutton onClick={() =\u003e setMode(\"light\")}\u003eLight Mode\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setMode(\"dark\")}\u003eDark Mode\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n`useMode` hook returns the following object:\n\n```ts\nexport interface UseModeInterface {\n  mode: ColorSchemePreference;\n  systemMode: ResolvedScheme;\n  resolvedMode: ResolvedScheme;\n  setMode: (mode: ColorSchemePreference) =\u003e void;\n}\n```\n\n### Force per page mode\n\nApply appropriate class names and data attributes to force a mode for the page:\n\n```tsx\nexport default function Page() {\n  return \u003cdiv className=\"dark ndm-scoped data-rm='dark'\"\u003e...\u003c/div\u003e;\n}\n```\n\n### With Styled Components and any CSS-in-JS\n\nNext Themes works with any library. For example, with Styled Components:\n\n```js\n// pages/_app.js\nimport { createGlobalStyle } from \"styled-components\";\nimport { Core } from \"nextjs-darkmode\";\n\n// Your theming variables\nconst GlobalStyle = createGlobalStyle`\n  :root {\n    --fg: #000;\n    --bg: #fff;\n  }\n\n  [data-rm=\"dark\"] {\n    --fg: #fff;\n    --bg: #000;\n  }\n`;\n\nfunction MyApp({ Component, pageProps }) {\n  return (\n    \u003c\u003e\n      \u003cGlobalStyle /\u003e\n      \u003cCore /\u003e\n      \u003cComponent {...pageProps} /\u003e\n    \u003c/\u003e\n  );\n}\n```\n\n### With Tailwind\n\nIn `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\nNow 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`nextjs-darkmode` is designed to be fully tree-shakable, including only the code you use. For instance, if you only use the `useMode` hook, the rest of the library's code will be removed during the build process.\n\n## Contributing\n\nWe welcome contributions! Check out the [Contributing Guide](https://github.com/react18-tools/nextjs-darkmode/blob/main/CONTRIBUTING.md) for more details.\n\n### 🤩 Don't forget to star [this repo](https://github.com/react18-tools/nextjs-darkmode)!\n\nExplore hands-on courses to get started with Turborepo:\n\n- [React and Next.js with TypeScript](https://mayank-chaudhari.vercel.app/courses/react-and-next-js-with-typescript)\n- [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/1de49d3f98af85faaf462974a990ac2f51d13041.svg \"Repobeats analytics image\")\n\n## License\n\n[MPL-2.0](https://github.com/react18-tools/nextjs-darkmode/blob/main/LICENSE)\n\nFeel free to use, modify, and distribute this library under the MPL-2.0 license.\n\nPlease 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-darkmode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact18-tools%2Fnextjs-darkmode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact18-tools%2Fnextjs-darkmode/lists"}