# Setting Up Turborepo Build and Watch Workflow for Pascal Editor: Complete Monorepo Guide

> Master Turborepo build and watch for Pascal Editor. Automatically rebuild core & viewer, then hot-reload your Next.js editor on every file change without cached artifacts.

- Repository: [Pascal/editor](https://github.com/pascalorg/editor)
- Tags: how-to-guide
- Published: 2026-03-25

---

**Running `bun dev` triggers a persistent Turborepo watch pipeline that rebuilds `@pascal-app/core` and `@pascal-app/viewer` on every file change and hot‑reloads the Next.js 16 editor without cached artifacts.**

Pascal Editor is organized as a **Turborepo monorepo** that orchestrates three interconnected packages—a Zustand‑backed core, a React Three Fiber viewer, and a Next.js 16 editor—to enable real‑time geometry editing with instantaneous feedback during development. This guide walks through the exact [`turbo.json`](https://github.com/pascalorg/editor/blob/main/turbo.json) configuration, workspace dependencies, and watch‑mode mechanics that make the repository’s build pipeline efficient and developer‑friendly.

## Understanding the Monorepo Architecture

The repository splits functionality across three distinct workspaces defined in the root [`package.json`](https://github.com/pascalorg/editor/blob/main/package.json):

| Package | Path | Purpose |
|---------|------|---------|
| `@pascal-app/core` | `packages/core/` | Schemas, Zustand scene store (`useScene`), geometry‑generation systems, and spatial queries (no UI) |
| `@pascal-app/viewer` | `packages/viewer/` | 3‑D rendering components built on React Three Fiber, camera controllers, lights, and post‑processing |
| `apps/editor` | `apps/editor/` | Next.js 16 application that composes the viewer, UI panels, tools, and editor‑only systems |

Each package lists its siblings as workspace dependencies (`"workspace:*"`), ensuring that local changes propagate instantly without manual `npm link` operations.

## How Turbo Orchestrates Development

The top‑level [`turbo.json`](https://github.com/pascalorg/editor/blob/main/turbo.json) defines task pipelines that enforce build order and enable persistent watch mode. The `dev` task configuration is the heart of the workflow:

```json
{
  "dev": {
    "dependsOn": ["^build"],
    "cache": false,
    "persistent": true
  }
}

```

- **`dependsOn`: `["^build"]`** – Forces Turbo to compile every dependency (`@pascal-app/core` and `@pascal-app/viewer`) before starting the Next.js dev server.
- **`cache: false`** – Disables Turborepo’s artifact cache during development so you always see the freshest JavaScript/TypeScript output.
- **`persistent: true`** – Keeps the process alive, enabling hot‑reload for the editor when any source file changes.

When you execute `bun dev`, Turbo first runs `^build` across the monorepo, then enters a file‑watcher that recompiles affected packages and signals the Next.js server to refresh.

## One‑Command Quick Start

Install dependencies and start the watch workflow with a single terminal command:

```bash
bun install && bun dev

```

This sequence:
1. Installs all packages using Bun’s workspace‑aware resolver.
2. Builds `@pascal-app/core` and `@pascal-app/viewer` to their respective `dist/` directories.
3. Launches the Next.js development server on **http://localhost:3000**.
4. Enters persistent watch mode, listening for changes in `packages/core/src/`, `packages/viewer/src/`, or `apps/editor/`.

## Under‑the‑Hood Build Pipeline

Understanding the three‑stage pipeline helps debug build issues or optimize hot‑reload times.

### Stage 1: Core and Viewer Compilation

When you modify [`packages/core/src/store/use-scene.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/store/use-scene.ts) or any file in the viewer, Turbo re‑executes the package’s `build` script (defined in [`package.json`](https://github.com/pascalorg/editor/blob/main/package.json)). The output lands in `packages/core/dist/` and `packages/viewer/dist/`, which the Next.js app consumes via workspace `link:` references.

### Stage 2: Next.js Dev Server

The `apps/editor` package starts its Next.js 16 server only after `^build` succeeds. Because the core and viewer are workspace dependencies, Node resolves them directly from `dist/` without publishing to npm.

### Stage 3: Hot Reload Propagation

When `useScene` emits a dirty‑node flag (via `markDirty`), the viewer’s renderers detect the updated Zustand state and trigger a React re‑render. Meanwhile, Turbo’s watch process detects file‑system changes, recompiles the changed package, and the Next.js dev server refreshes the client automatically.

## Adding New Core Systems: A Practical Example

Extend `@pascal-app/core` with a custom `FloorSystem` that regenerates plane geometry when nodes are marked dirty. Create [`packages/core/src/systems/floor-system.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/systems/floor-system.ts):

```typescript
import { useFrame } from '@react-three/fiber'
import { useScene } from '../store/use-scene'
import { useRegistry } from '../hooks/use-registry'
import * as THREE from 'three'

export function FloorSystem() {
  const { nodes, markDirty } = useScene()
  const registry = useRegistry()

  useFrame(() => {
    for (const id of nodes.dirtyNodes) {
      const node = nodes[id]
      if (node.type !== 'floor') continue

      const obj = registry.get(id)
      if (!obj) continue

      obj.geometry?.dispose()
      obj.geometry = new THREE.PlaneGeometry(node.width, node.depth)

      markDirty(id)
    }
  })
}

```

Save the file. Turbo immediately rebuilds `@pascal-app/core`, the viewer picks up the new system export from [`packages/viewer/src/index.ts`](https://github.com/pascalorg/editor/blob/main/packages/viewer/src/index.ts), and the running editor at `localhost:3000` reflects the changes without a manual restart.

## Running Individual Tasks

For scenarios where you need granular control, invoke these standard Turbo tasks:

- `bun run build` – Runs `turbo run build`, ensuring `^build` dependencies execute first for all packages.
- `bun run lint` – Executes Biome linting across every workspace.
- `bun run check-types` – Runs `turbo run check-types` to verify TypeScript integrity in [`packages/core/src/store/use-scene.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/store/use-scene.ts) and other entry points.
- `bun run kill` – Terminates any stray process listening on port 3002 (used by Turborepo’s cache server).

## Summary

- **Pascal Editor** relies on a three‑package Turborepo architecture (`core`, `viewer`, `editor`) managed via [`turbo.json`](https://github.com/pascalorg/editor/blob/main/turbo.json) pipelines.
- The **`dev`** task combines `^build` dependencies, `cache: false`, and `persistent: true` to provide zero‑lag hot reload during geometry editing.
- **Workspace `link:` references** let the Next.js app consume `dist/` output instantly, eliminating the need for manual package publishing during development.
- **Bun** serves as the package manager and task runner; `bun dev` is the only command required to bootstrap the watch workflow.
- Changes to systems like `FloorSystem` propagate automatically through the Zustand store (`useScene`) and trigger React Three Fiber re‑renders without server restarts.

## Frequently Asked Questions

### What triggers a rebuild in the Pascal Editor watch mode?

Turbo’s file watcher monitors `packages/core/src/`, `packages/viewer/src/`, and `apps/editor/` for TypeScript and asset changes. When you save a file—such as [`packages/core/src/store/use-scene.ts`](https://github.com/pascalorg/editor/blob/main/packages/core/src/store/use-scene.ts)—Turbo invalidates the build graph for that package, recompiles to `dist/`, and signals the Next.js dev server to hot‑reload the client.

### Why does the Turborepo dev task disable caching?

The `dev` task sets **`cache: false`** in [`turbo.json`](https://github.com/pascalorg/editor/blob/main/turbo.json) to ensure that every code change immediately produces fresh artifacts in `dist/`. Cached builds would risk serving stale JavaScript during active development of geometry systems or UI components, breaking the hot‑reload contract.

### How do I integrate a new npm package into the build pipeline?

Add the dependency to the specific workspace’s [`package.json`](https://github.com/pascalorg/editor/blob/main/package.json) (e.g., [`apps/editor/package.json`](https://github.com/pascalorg/editor/blob/main/apps/editor/package.json) for UI libraries or [`packages/core/package.json`](https://github.com/pascalorg/editor/blob/main/packages/core/package.json) for math utilities), run `bun install` from the root, and reference the new module in your code. Turbo automatically includes the new dependency graph in subsequent `bun run build` or `bun dev` executions without manual configuration changes.

### Which port does the Next.js editor run on, and how do I stop conflicting processes?

The Next.js development server launches on **port 3000**. If Turborepo’s internal cache server or a zombie Node process blocks port 3002, execute `bun run kill` from the repository root; this script terminates any process listening on that port, allowing `bun dev` to start cleanly.