Skip to content

Commit 99c2541

Browse files
itspradeclaude
andcommitted
fix(themes): RSC-safe initial-appearance subpath for getInitialAppearanceScript
The Next.js example's `app/layout.tsx` is a Server Component. Importing `getInitialAppearanceScript` from the package root pulled in the full client barrel, transitively `react-router`, which exports `useRouteError` that doesn't exist in the React Server Components build — Turbopack RSC bailed with "Export useRouteError doesn't exist in target module". Fix: ship `getInitialAppearanceScript` as a leaf subpath `@tailor-platform/app-shell/initial-appearance`. The source already has no React / react-router imports (only `type` imports from `theme-context` that are erased at compile time), so it's a ~1KB zero-runtime-dep entry — safe to call from any RSC layout. Added to `vite.config.ts` build entries and `package.json` exports. The top-level export remains for non-RSC consumers; docs and the Next.js example use the leaf subpath. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4d4e84d commit 99c2541

4 files changed

Lines changed: 10 additions & 3 deletions

File tree

docs/api/use-theme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,11 @@ Use **`AppShell`**’s **`defaultFont`** prop for the initial value when nothing
181181

182182
`ThemeProvider` writes **`data-theme`** / **`data-font`** to **`<html>`** from a **post-mount effect**. On SSR'd apps that creates a flash of the default palette before the stored preference is applied, plus a React hydration warning.
183183

184-
The package exports **`getInitialAppearanceScript()`** which returns a tiny script string consumers inline in **`<head>`** so the stored preference is applied **before first paint**:
184+
The package exports **`getInitialAppearanceScript()`** which returns a tiny script string consumers inline in **`<head>`** so the stored preference is applied **before first paint**. Import from the leaf subpath **`@tailor-platform/app-shell/initial-appearance`** — it's a zero-React-dep entry, safe to call from Next.js Server Components / RSC.
185185

186186
```tsx
187187
// app/layout.tsx (Next.js App Router)
188-
import { getInitialAppearanceScript } from "@tailor-platform/app-shell";
188+
import { getInitialAppearanceScript } from "@tailor-platform/app-shell/initial-appearance";
189189

190190
export default function RootLayout({ children }) {
191191
return (

examples/nextjs-app/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Metadata } from "next";
22
import { Geist, Geist_Mono } from "next/font/google";
3-
import { getInitialAppearanceScript } from "@tailor-platform/app-shell";
3+
import { getInitialAppearanceScript } from "@tailor-platform/app-shell/initial-appearance";
44
import "@tailor-platform/app-shell/styles";
55
import "./globals.css";
66

packages/core/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
"types": "./dist/app-shell.d.ts",
3434
"default": "./dist/app-shell.js"
3535
},
36+
"./initial-appearance": {
37+
"types": "./dist/initial-appearance.d.ts",
38+
"default": "./dist/initial-appearance.js"
39+
},
3640
"./vite-plugin": {
3741
"types": "./dist/vite-plugin.d.ts",
3842
"default": "./dist/vite-plugin.js"

packages/core/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export default defineConfig(({ mode }) => ({
3737
entry: {
3838
"app-shell": "src/index.ts",
3939
"vite-plugin": "src/vite-plugin.ts",
40+
// Leaf entry for Server-Component-safe usage: pure, zero React / react-router
41+
// imports, so Next.js RSC can call it from `app/layout.tsx`.
42+
"initial-appearance": "src/lib/initial-appearance.ts",
4043
},
4144
formats: ["es"],
4245
},

0 commit comments

Comments
 (0)