Skip to content

Dependency Patches


Plugins sometimes rely on Astro configuration fields that change between major versions. Rather than forking a dependency or waiting for an upstream release, bun patch lets you apply a minimal fix that survives reinstalls. This guide explains the workflow and documents every active patch in the project.

Bun’s built-in patching creates a diff file in patches/ and records it in package.json under patchedDependencies. Every bun install re-applies the patch automatically.

Terminal window
bun patch <package-name>

This prints a path (usually node_modules/<package-name>) and tells you to edit files there.

Make your changes directly in node_modules/<package-name>/. Keep edits minimal — touch only the lines that fix the problem.

Terminal window
bun patch --commit 'node_modules/<package-name>'

Bun generates patches/<package-name>@<version>.patch and adds a patchedDependencies entry to package.json. Both files should be committed to version control.

Run bun install in a clean environment (or delete node_modules and reinstall) to confirm the patch re-applies correctly.

starlight-site-graph — output path detection

Section titled “starlight-site-graph — output path detection”

Package: starlight-site-graph@0.5.0 File: integration.ts Problem: Ghost client/ entries in backlinks

The starlight-site-graph plugin scans built HTML to generate a sitemap with backlinks. It needs to know where Astro writes HTML output. The original code checked config.output === "server" to detect SSR mode and use config.build.client as the output path:

// Original (Astro 4 pattern)
} else if (config.adapter?.name === "@astrojs/node" && config.output === "server") {
outputPath = fileURLToPath(config.build.client!);
}

In Astro 5, config.output is always "static" even with an SSR adapter. The condition never matched, so the plugin fell back to config.outDir (dist/). When it walked dist/, it found HTML under dist/client/ and computed paths like client/electron-terminal/... — pages that don’t exist. These ghost entries appeared as broken backlinks in the right sidebar.

Fix: Check for the presence of an adapter and config.build.client rather than testing config.output:

// Patched (works with Astro 5)
} else if (config.adapter && config.build.client) {
outputPath = fileURLToPath(config.build.client);
}

This works for any SSR adapter, not just @astrojs/node, and doesn’t depend on the config.output field that Astro 5 removed from its adapter contract.

Verification: After building, check dist/client/sitegraph/sitemap.json for entries starting with client/. A clean build should have none.

starlight-site-graph — process globals in browser

Section titled “starlight-site-graph — process globals in browser”

Workaround type: Vite define in astro.config.mjs (no patch file) Problem: Uncaught ReferenceError: process is not defined

The plugin’s client-side bundle pulls in micromatch, which depends on picomatch. Both libraries reference process.platform and process.version — Node globals that don’t exist in the browser. The error fires at page load and breaks the site graph widget entirely.

Fix: Vite’s define option replaces these references with static values at build time, so the compiled JS never touches process:

astro.config.mjs
vite: {
define: {
'process.platform': JSON.stringify(''),
'process.version': JSON.stringify('0.0.0'),
},
},

Empty string for process.platform and a dummy version string are safe here. picomatch only reads these values to detect Windows path separators (\\ vs /). In a browser context path-separator detection is irrelevant — all URLs use forward slashes.

Verification: Run bun run build, then open the site in a browser and check the console for ReferenceError. A clean build produces no process-related errors.

Patch when the fix is small (a few lines), the root cause is clear, and the upstream package is otherwise healthy. Patches are easy to maintain and easy to remove once upstream catches up.

Fork when you need structural changes, the upstream is unmaintained, or your patch would span multiple files with interdependencies that a diff can’t express cleanly.

Wait when the issue is cosmetic, the upstream has an open PR addressing it, or the workaround is simpler than maintaining a patch (e.g., a config change or a post-build script).

When an upstream release fixes the issue:

  1. Update the package version in package.json
  2. Delete the corresponding file from patches/
  3. Remove the entry from patchedDependencies
  4. Run bun install and verify the build