# Configure the Bundler URL: /docs/guides/bundler-configuration Configure the Bundler [#configure-the-bundler] Configure the esbuild bundler for JS/TS kernels (Replicad, OpenCASCADE, Manifold, JSCAD). The bundler resolves imports, bundles code, and executes it inside the worker. You can customize extensions, and for advanced use cases, define custom bundlers. Prerequisites [#prerequisites] * [Install @taucad/runtime](../getting-started/installation) * Completed the [Quick Start](../getting-started/quick-start) * [Choose a Kernel](./choosing-a-kernel) -- Understand which kernels use bundlers Goal [#goal] Configure the esbuild bundler for your JS/TS kernels, understand how bundling integrates with kernel selection, and optionally register custom modules or define a custom bundler. Steps [#steps] 1. Import esbuild from @taucad/runtime/bundler [#1-import-esbuild-from-taucadruntimebundler] The default bundler is created via the `esbuild()` factory: ```typescript import { esbuild } from '@taucad/runtime/bundler'; ``` 2. Add the Bundler to createRuntimeClient [#2-add-the-bundler-to-createruntimeclient] Pass the bundler in the `bundlers` array. JS/TS kernels (Replicad, OpenCASCADE, Manifold, JSCAD) require a bundler to resolve imports and execute code: ```typescript import { createRuntimeClient, fromMemoryFS } from '@taucad/runtime'; import { replicad } from '@taucad/runtime/kernels'; import { esbuild } from '@taucad/runtime/bundler'; const client = createRuntimeClient({ kernels: [replicad()], bundlers: [esbuild()], fileSystem: fromMemoryFS(), }); ``` 3. Configure EsbuildOptions [#3-configure-esbuildoptions] Use `EsbuildOptions` to override the default file extensions: ```typescript import { esbuild } from '@taucad/runtime/bundler'; const bundler = esbuild({ extensions: ['ts', 'tsx'] }); ``` Default extensions are `['ts', 'js', 'tsx', 'jsx']`. Restrict to TypeScript only if your project uses no `.js`/`.jsx` files. 4. Understand How Bundling Works with JS/TS Kernels [#4-understand-how-bundling-works-with-jsts-kernels] The flow for Replicad, OpenCASCADE, Manifold, and JSCAD: 1. **detectImports**: The bundler runs a lightweight pass (externals mode) to discover bare-specifier imports (e.g., `replicad`, `@jscad/modeling`). This drives kernel selection. 2. **Kernel initialization**: The selected kernel registers built-in modules (WASM-loaded libraries) via `runtime.bundler.registerModule`. 3. **bundle**: Full production bundle with all registered modules resolved. Produces runnable ESM code. 4. **execute**: The bundled code is run via dynamic import (Blob URL in browser, data URL in Node.js). Kernels access the bundler through `runtime.bundler` and `runtime.execute`. You do not call these directly; the kernel lifecycle handles it. 5. Custom Module Registration (Kernel Authors) [#5-custom-module-registration-kernel-authors] If you build a custom JS/TS kernel, register built-in modules during `initialize`: ```typescript @ts-nocheck import { defineKernel } from '@taucad/runtime'; export default defineKernel({ name: 'MyKernel', version: '1.0.0', async initialize(options, runtime) { const wasmCode = await loadMyLibraryWasm(); runtime.bundler.registerModule('my-library', { code: wasmCode, version: '1.0.0', globalName: 'myLibrary', }); return { /* context */ }; }, // ... }); ``` See the Replicad and JSCAD kernel source for full examples. 6. Define a Custom Bundler with defineBundler [#6-define-a-custom-bundler-with-definebundler] For non-esbuild bundlers (e.g., custom transpiler, different execution model), use [`defineBundler`](../api/bundler). The definition requires: `name`, `version`, `extensions`, `initialize`, `detectImports`, `bundle`, `execute`, and `registerModule`. Optional: `resolveDependencies`, `cleanup`: ```typescript @ts-nocheck import { defineBundler } from '@taucad/runtime/bundler'; const myBundler = defineBundler({ name: 'MyBundler', version: '1.0.0', extensions: ['ts', 'js'], async initialize({ filesystem, projectPath }) { return { filesystem, projectPath }; }, async detectImports({ entryPath }, _ctx) { return { detectedModules: [], dependencies: [entryPath] }; }, async bundle({ entryPath }, _ctx) { return { code: '...', success: true, issues: [], dependencies: [] }; }, async execute(_code, _ctx) { return { success: true, value: {} }; }, registerModule(_name, _builtinModule, _ctx) { // Store for resolution during bundle() }, }); ``` Register your bundler via a [`BundlerPlugin`](../api/bundler) with `moduleUrl` pointing to the built module. Variations [#variations] * **Multiple bundlers**: Pass multiple bundlers when you have kernels with different extension needs. The framework selects the bundler that handles the file extension. * **Bundler selection**: The worker matches the entry file extension to `bundler.extensions`. The first matching bundler is used. * **Skip bundler in tests**: Use `skipBundler: true` in `createTestWorker` when testing kernel logic that does not need bundling. Related [#related] * [Create a Custom Kernel](./custom-kernel) -- Implement kernels that use the bundler * [Plugin System](../concepts/plugin-system) -- How bundlers are loaded * [API Reference: Bundler](../api/bundler) -- EsbuildOptions, defineBundler, BundlerDefinition * [API Reference: Types](../api/types) -- KernelBundler, BundleResult