getTheme
Read the current theme from a cookie outside React - in proxy, layouts, or server actions.
Last updated on
getTheme reads the current theme from a cookie. Available in @wrksz/themes/next.
Breaking · v2.0.0-beta.1 In 2.0.0-beta.1, ThemeProvider no longer calls getTheme / cookies() for you. Use this helper only when server markup must know the theme. See Upgrading from 1.x.
Two variants depending on context:
| Call | Returns | Use when |
|---|---|---|
getTheme(request) | string or inferred theme union | proxy.ts, edge functions |
await getTheme() | Promise<string> or inferred theme union | Server Components, layouts |
Proxy
import { NextResponse } from "next/server";
import { getTheme } from "@wrksz/themes/next";
export function proxy(request: Request) {
const theme = getTheme(request, { defaultTheme: "dark" });
const response = NextResponse.next();
response.headers.set("x-theme", theme);
return response;
}Typed themes
Pass your theme list as a readonly tuple to get a narrowed return type:
import { getTheme } from "@wrksz/themes/next";
const themes = ["light", "dark", "high-contrast"] as const;
export function proxy(request: Request) {
const theme = getTheme(request, {
themes,
defaultTheme: "light",
});
// theme: "light" | "dark" | "high-contrast"
}Async usage in layouts works the same way:
const theme = await getTheme({
themes: ["light", "dark"] as const,
defaultTheme: "system",
});
// theme: "light" | "dark" | "system"When themes is omitted, getTheme returns string because an existing cookie can contain any stored value.
Layout - apply class directly on <html>
Breaking · v2.0.0-beta.1 Required more often in 2.0.0-beta.1 because the provider no longer injects the cookie class for you.
Use this pattern when server-rendered markup itself must depend on the theme:
import { ThemeProvider, getTheme } from "@wrksz/themes/next";
export const instant = false;
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const theme = await getTheme({ defaultTheme: "dark" });
return (
<html lang="en" className={theme} suppressHydrationWarning>
<body>
<ThemeProvider storage="cookie" defaultTheme="dark">
{children}
</ThemeProvider>
</body>
</html>
);
}getTheme() calls the request-time cookies() API. With Cache Components enabled, reading it
for the root <html> class blocks prerendering, so this example opts out with
export const instant = false. For Instant Navigations, keep ThemeProvider static and let its
bootstrap read the cookie before paint. If only a subtree needs server theme data, move the
getTheme() call into an async child wrapped in <Suspense> so the rest of the App Shell remains
prefetchable.
Options
| Option | Type | Default | Description |
|---|---|---|---|
storageKey | string | "theme" | Cookie name to read from |
defaultTheme | string | "system" | Returned when no valid theme is found. When themes is a readonly tuple, this must be one of those themes or "system" |
themes | readonly string[] | - | When provided, stored values not in the list are ignored and defaultTheme is returned. Use as const for return type inference |