A dark mode should paint the reader's theme on the first frame, switch without re-rendering the page, and let one section disagree with the rest. Most manage one or two of those three jobs. This article builds all three with Box Kite, shows what each line costs, and is explicit about the one piece the library leaves to you.
The examples here are screenshots; they run live in the original article .
The problem
Somebody opens your server-rendered page at night with their system set to dark. The HTML arrives, the browser paints it — white — and a moment later JavaScript runs, reads the preference and repaints everything dark. That flash is the most-reported dark-mode bug there is: the long-running Next.js discussion on it has dozens of replies, and a newer one opened because the usual fixes broke in the App Router.
The fixes people reach for each trade one problem for another:
Keep the theme in React state and pass it to every component.…