@wrksz/themesv2.0.0-beta.1 · beta
API Reference

getTheme

Read the current theme from a cookie outside React - in proxy, layouts, or server actions.

Edit on GitHub

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:

CallReturnsUse when
getTheme(request)string or inferred theme unionproxy.ts, edge functions
await getTheme()Promise<string> or inferred theme unionServer Components, layouts

Proxy

proxy.ts
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:

proxy.ts
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:

app/layout.tsx
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:

app/layout.tsx
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

OptionTypeDefaultDescription
storageKeystring"theme"Cookie name to read from
defaultThemestring"system"Returned when no valid theme is found. When themes is a readonly tuple, this must be one of those themes or "system"
themesreadonly string[]-When provided, stored values not in the list are ignored and defaultTheme is returned. Use as const for return type inference

On this page