---
title: "Monorepos"
description: "bun workspaces, pnpm workspaces, and Turborepo all work — here's what to know."
---

> Documentation Index
> Fetch the complete documentation index at: https://ramonmalcolm10.github.io/next-bun-compile/llms.txt
> Use this file to discover all available pages before exploring further.

# Monorepos

next-bun-compile handles monorepo layouts automatically. The adapter
assembles its traced output tree with the app path preserved
(e.g. `apps/web/...` relative to the repo root), and the compiled
binary lands at `apps/web/dist/app`.

One monorepo-specific requirement: Next.js resolves `adapterPath`
from **its own package location**, so a nested workspace dependency
needs resolving from the app dir:

```ts
// apps/web/next.config.ts
import { createRequire } from "node:module";
import type { NextConfig } from "next";

const req = createRequire(process.cwd() + "/");

const nextConfig: NextConfig = {
  adapterPath: req.resolve("next-bun-compile"),
};

export default nextConfig;
```

## Bun workspaces

Standard bun workspaces setup, no special config:

```json
// package.json (monorepo root)
{
  "private": true,
  "workspaces": ["apps/*", "packages/*"]
}
```

```json
// apps/web/package.json
{
  "name": "web",
  "scripts": {
"build": "next build"
  },
  "dependencies": {
"@example/shared": "*",
"next": "^16.2",
"next-bun-compile": "^1"
  }
}
```

```bash
bun install                        # at the monorepo root
cd apps/web && bun run build       # produces apps/web/dist/app
```

A full working monorepo + sharp example is in
[Recipes › Monorepo + sharp](/next-bun-compile/next-bun-compile/recipes/monorepo-sharp/).

## pnpm workspaces

Same idea — pnpm's `.pnpm/` hoisted store is handled the same way as
bun's `.bun/` store. next-bun-compile walks both.

## Turborepo

Works as-is. If you use `turbo prune --docker` in CI to slim the
Docker context, the pruned tree still triggers the nested-layout
codepath. next-bun-compile doesn't care about the workspace tool — only
about the standalone layout Next.js produces.

## What next-bun-compile does for monorepos

1. **Preserves the nested layout.** The adapter's assembled tree keys
   files relative to the repo root, so `apps/web` nesting survives
   into the binary's extraction layout.
2. **Merges split `node_modules/`.** Traced outputs can place partial
   package copies at multiple levels; next-bun-compile merges every
   location per file so nothing is lost to hoisting.
3. **Workspace packages survive.** Anything Next.js's trace pulled in
   (including workspace `*`-version deps) gets embedded from wherever
   it landed — including plain data files. A route reading
   `../../packages/shared/fonts/body.ttf` through `fs` works, because
   the binary mirrors the assembled tree and runs from the app dir
   inside it, exactly as `output: "standalone"` does.

## Where the runtime tree lands

The extracted tree keeps its workspace path, so an app at `apps/web`
extracts to `$NBC_RUNTIME_DIR/apps/web`, not `$NBC_RUNTIME_DIR`. That is
what keeps `../../packages/...` resolvable at runtime. The build prints
it:

```
next-bun-compile: monorepo layout — runtime tree extracts to <NBC_RUNTIME_DIR>/apps/web
```

It only matters if you pre-extract with `--extract` or mount a volume
into the tree — see [Docker](/next-bun-compile/guides/docker/). A single-app repo is
unaffected: there is no workspace path, so the tree extracts straight
into `NBC_RUNTIME_DIR` as before.

## Common gotchas

### "Cannot find module 'next-bun-compile'"

Next resolves the bare `adapterPath` string from its own package
location, which in a monorepo may not see your app's nested
dependency. Use the `createRequire(process.cwd() + "/")` pattern
shown above.

### Mixed package managers

If your CI installs with `bun` but your repo also has a stale
`package-lock.json`, Next.js's "multiple lockfiles" warning may
confuse workspace detection. Remove the unused lockfile.

Source: https://ramonmalcolm10.github.io/next-bun-compile/guides/monorepo/index.mdx
