From 1f92d74f0c816621daeb4aa80e0e274a8b79fc82 Mon Sep 17 00:00:00 2001 From: hkonsti <45428767+hkonsti@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:54:22 -0700 Subject: [PATCH] fix(docs): ship import map in prod and remove dead theme toggle The fiddles' import map was injected by reading src/generated/modules.json via fs.readFileSync at render time. Next's file tracing doesn't follow that computed path, so the file is dropped from the production server bundle, the read throws, and the import map silently disappears - breaking every fiddle's runtime import('@revideo/2d') with 'bare specifier ... not remapped'. Import the manifest statically so Next bundles it in. Also hide Nextra's sidebar theme switch (darkMode={false}): the docs are hard-forced to dark, so the toggle did nothing. --- packages/docs/src/app/layout.tsx | 4 +++ .../components/site/revideo-import-map.tsx | 30 +++++++------------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/docs/src/app/layout.tsx b/packages/docs/src/app/layout.tsx index eca2f1e4..36973ae6 100644 --- a/packages/docs/src/app/layout.tsx +++ b/packages/docs/src/app/layout.tsx @@ -87,6 +87,10 @@ export default async function RootLayout({children}: {children: React.ReactNode} docsRepositoryBase="https://github.com/redotvideo/revideo/blob/main/packages/docs" sidebar={{defaultMenuCollapseLevel: 1}} pageMap={pageMap} + // The docs are dark-only (forcedTheme below), so hide the theme + // switch Nextra otherwise renders in the sidebar footer — a toggle + // that has no effect. + darkMode={false} nextThemes={{defaultTheme: "dark", forcedTheme: "dark"}} > {children} diff --git a/packages/docs/src/components/site/revideo-import-map.tsx b/packages/docs/src/components/site/revideo-import-map.tsx index e8fa5ede..874c2e28 100644 --- a/packages/docs/src/components/site/revideo-import-map.tsx +++ b/packages/docs/src/components/site/revideo-import-map.tsx @@ -1,5 +1,13 @@ -import fs from 'node:fs'; -import path from 'node:path'; +// Statically imported (rather than read via `fs` at render time) so Next +// bundles it into the server output. A runtime `fs.readFileSync` of a computed +// path isn't picked up by Next's file tracing, so it's dropped from the +// production build and the import map silently disappears - which breaks the +// fiddles' `import('@revideo/2d')` with "bare specifier ... not remapped". +// +// The manifest is generated by scripts/copy-modules.mjs, which runs before +// `next build`/`next dev` (see package.json). It maps `@revideo/core` / +// `@revideo/2d` to the hashed ESM bundles copied into public/modules. +import manifest from '@/generated/modules.json'; // Keep in sync with `basePath` in next.config.ts. const BASE_PATH = '/revideo'; @@ -10,24 +18,6 @@ const BASE_PATH = '/revideo'; * bundles copied into public/modules by scripts/copy-modules.mjs. */ export function RevideoImportMap() { - let manifest: Record; - try { - manifest = JSON.parse( - fs.readFileSync( - path.join(process.cwd(), 'src', 'generated', 'modules.json'), - 'utf8', - ), - ); - } catch { - // Without the manifest the fiddles cannot load the runtime; skip the - // import map instead of failing the whole site. - console.warn( - 'src/generated/modules.json is missing - run `npm run modules:copy` ' + - 'to enable the interactive fiddles.', - ); - return null; - } - const importMap = { imports: { '@revideo/core': `${BASE_PATH}${manifest['@revideo/core']}`,