From f47b519a561e99f6e33da8036e249e8a77e79563 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:41:09 +0000 Subject: [PATCH 1/4] Initial plan From 7fc853eefeaf3bbb4d6179b50ab3ad41c784a820 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:46:52 +0000 Subject: [PATCH 2/4] Add rwsdk (RedwoodJS SDK) support to @navita/vite-plugin Co-authored-by: Zn4rK <873043+Zn4rK@users.noreply.github.com> --- packages/vite-plugin/package.json | 5 ++ packages/vite-plugin/src/rwsdk.ts | 94 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 packages/vite-plugin/src/rwsdk.ts diff --git a/packages/vite-plugin/package.json b/packages/vite-plugin/package.json index b987b53..2d41842 100644 --- a/packages/vite-plugin/package.json +++ b/packages/vite-plugin/package.json @@ -19,6 +19,11 @@ "import": "./dist/remix.mjs", "require": "./dist/remix.cjs", "types": "./src/remix.ts" + }, + "./rwsdk": { + "import": "./dist/rwsdk.mjs", + "require": "./dist/rwsdk.cjs", + "types": "./src/rwsdk.ts" } }, "publishConfig": { diff --git a/packages/vite-plugin/src/rwsdk.ts b/packages/vite-plugin/src/rwsdk.ts new file mode 100644 index 0000000..4445f15 --- /dev/null +++ b/packages/vite-plugin/src/rwsdk.ts @@ -0,0 +1,94 @@ +import * as fsp from "node:fs/promises"; +import * as path from "node:path"; +import type { Plugin } from "vite"; +import type { Options } from "./index"; +import { navita, VIRTUAL_MODULE_ID } from "./index"; + +export function navitaRwsdk(options?: Options): Plugin[] { + let projectRootDir: string; + let base: string; + + const navitaPlugin = navita(options); + + return [ + navitaPlugin, + { + name: "navita-rwsdk", + enforce: "post", + + configResolved(config) { + projectRootDir = config.root; + base = config.base; + }, + + async renderChunk(code) { + // Only run during the linker pass on the worker environment + // @ts-expect-error - environment exists at runtime in Vite 6+ + const environmentName = this.environment?.name; + + if (environmentName !== "worker" || process.env.RWSDK_BUILD_PASS !== "linker") { + return null; + } + + // Read the client manifest to find the navita CSS path + const manifestPath = path.resolve( + projectRootDir, + "dist", + "client", + ".vite", + "manifest.json" + ); + + let manifestContent: string; + try { + manifestContent = await fsp.readFile(manifestPath, "utf-8"); + } catch { + console.warn("[navita-rwsdk] Could not read client manifest, skipping CSS replacement"); + return null; + } + + const manifest = JSON.parse(manifestContent) as Record; + + // Find the navita CSS file in the manifest + let navitaCssPath: string | null = null; + + for (const [key, value] of Object.entries(manifest)) { + // Check if this is the navita CSS entry directly + if (key.includes("navita") && key.endsWith(".css")) { + navitaCssPath = (base || "/") + value.file; + break; + } + // Also check if it's referenced in the css array of any entry + if (value.css) { + for (const cssFile of value.css) { + if (cssFile.includes("navita")) { + navitaCssPath = (base || "/") + cssFile; + break; + } + } + if (navitaCssPath) break; + } + } + + if (!navitaCssPath) { + console.warn("[navita-rwsdk] Could not find navita CSS in manifest"); + return null; + } + + // Replace virtual:navita.css references with the actual hashed path + let newCode = code; + newCode = newCode.replaceAll(`/${VIRTUAL_MODULE_ID}`, navitaCssPath); + newCode = newCode.replaceAll(VIRTUAL_MODULE_ID, navitaCssPath); + + if (newCode !== code) { + return { code: newCode, map: null }; + } + + return null; + }, + }, + ]; +} From c9cf6d4f50379eea88f7459f272a6bc052badf79 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:56:21 +0000 Subject: [PATCH 3/4] Add rwsdk integration documentation Co-authored-by: Zn4rK <873043+Zn4rK@users.noreply.github.com> --- documentation/200-integrations/240-rwsdk.md | 88 +++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 documentation/200-integrations/240-rwsdk.md diff --git a/documentation/200-integrations/240-rwsdk.md b/documentation/200-integrations/240-rwsdk.md new file mode 100644 index 0000000..8a6e74f --- /dev/null +++ b/documentation/200-integrations/240-rwsdk.md @@ -0,0 +1,88 @@ +--- +title: rwsdk +description: +--- + +# rwsdk + +A plugin for integrating Navita with [rwsdk](https://rwsdk.com/) (RedwoodJS SDK). + +> Navita has first-class support for rwsdk! It works with Cloudflare Workers SSR! 🎉 + +## Installation + +```bash +npm install --save-dev @navita/vite-plugin +``` + +## Setup + +Add the plugin to your Vite configuration, along with any desired [plugin configuration](#configuration). + +```js +// vite.config.mts +import { defineConfig } from "vite"; +import { redwood } from "rwsdk/vite"; +import { cloudflare } from "@cloudflare/vite-plugin"; +import { navitaRwsdk } from "@navita/vite-plugin/rwsdk"; + +export default defineConfig({ + plugins: [ + navitaRwsdk({ + // configuration + }), + cloudflare({ viteEnvironment: { name: "worker" } }), + redwood(), + ], +}); +``` + +Please note that the import is different from the Vite plugin. The rwsdk plugin is based on, and uses the Vite plugin, +but we've added some extra functionality to make it better suited for rwsdk's build architecture. + +### Using Navita styles + +In your `Document.tsx`, add a link to the virtual Navita stylesheet: + +```tsx +// src/Document.tsx +export const Document: React.FC<{ children: React.ReactNode }> = ({ children }) => ( + + + + + + +
{children}
+ + + +); +``` + +The plugin will automatically replace the virtual path with the hashed CSS file path during the build process. + +## How it works + +rwsdk has a unique build architecture with three passes: + +1. **Client build**: Standard Vite client build that outputs assets to `dist/client/` +2. **Worker build**: Server-side worker bundle that renders React components +3. **Linker pass**: A special build pass that processes the worker bundle and replaces asset placeholders with hashed paths from the client manifest + +The base Navita plugin works correctly for the client build - CSS is emitted and registered in the Vite manifest. +The rwsdk plugin adds a `renderChunk` hook that runs during the linker pass to replace `/virtual:navita.css` references +with the actual hashed filename from the client manifest. + +## Configuration + +> The rwsdk plugin is based on the Vite plugin, so you can use the same configuration options. + +The plugin accepts the following as optional configuration: + +#### `importMap?: { callee: string, source: string }[]` +*Default*: `import { importMap } from "@navita/css"` + +ImportMap is a feature that allows you to extend the functionality of Navita. + +If you provide your own, it will be merged with the default importMap. From 9a560b29590bfe49937ec6fdae69e580578f034b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:59:02 +0000 Subject: [PATCH 4/4] Add changeset for rwsdk support Co-authored-by: Zn4rK <873043+Zn4rK@users.noreply.github.com> --- .changeset/add-rwsdk-support.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/add-rwsdk-support.md diff --git a/.changeset/add-rwsdk-support.md b/.changeset/add-rwsdk-support.md new file mode 100644 index 0000000..145ec9e --- /dev/null +++ b/.changeset/add-rwsdk-support.md @@ -0,0 +1,5 @@ +--- +"@navita/vite-plugin": minor +--- + +Add rwsdk (RedwoodJS SDK) support via new `@navita/vite-plugin/rwsdk` export