Skip to content

Multi-File Imports ​

Open the editor to try multi-file projects live.

Split simulation logic across files with named ES import syntax. The bundler resolves dependencies at compile time.

Creating Files ​

Use + in the file explorer. One file is the entry (main.js by default — shown with an entry badge). New files are modules (isEntry: false). There is no UI to change which file is entry; keep your return in main.js.

Critical Limitation ​

Module files do not receive time, dt, state, w, or h. They run once at compile time. Export pure helpers and pass frame data from the entry:

javascript
// physics.js
function step(body, dt, g) {
  body.vy += g * dt;
  body.x += body.vx * dt;
  body.y += body.vy * dt;
}
module.exports = { step };

// main.js
import { step } from './physics';
step(state.ball, dt, 200);

Import Syntax ​

javascript
import { gravity, drag } from './physics';
import { Particle } from './particle';
FeatureSupportedExample
Named importsYesimport { foo, bar } from './mod'
Default importsNoimport foo from './mod'
Namespace importsNoimport * as foo from './mod'
Dynamic importsNoimport('mod')
export keyword in modulesNoUse module.exports
Relative ./Yes'./physics', './physics.js'
Parent ../NoFlat project namespace only
Multiline import statementsNoKeep imports on one line

Builtin ai module

ai is the one built-in module — no file needs to exist. It supports default, namespace, and named imports: import ai from 'ai', import * as ai from 'ai', or import { seek, flock } from 'ai'. It is not a global, so each file that uses it must import it. See the AI cookbook.

How Modules Work ​

Non-entry files compile like CommonJS:

javascript
new Function('exports', 'module', /* optional __modules */, code)

They run once per compile; module.exports is cached. They are not re-executed every frame.

javascript
// physics.js
function gravity(body, dt, g) {
  body.vy += g * dt;
}

function drag(body, dt, coeff) {
  body.vx *= (1 - coeff * dt);
  body.vy *= (1 - coeff * dt);
}

module.exports = { gravity, drag };

module and exports are injected — do not use ES export in module files.

Example: Particle Spawner ​

main.js (entry):

javascript
import { createParticle, updateParticles } from './physics';

if (!state.init) {
  state.particles = [];
  state.init = true;
}

if (state.clickX !== undefined) {
  for (let i = 0; i < 8; i++) {
    state.particles.push(createParticle(state.clickX, state.clickY));
  }
  state.clickX = undefined;
  state.clickY = undefined;
}

state.particles = updateParticles(state.particles, dt, w, h);

return {
  particles: state.particles.map((p) => ({
    x: p.x, y: p.y, r: 5, color: p.color,
  })),
  text: { count: state.particles.length },
};

physics.js:

javascript
import { COLORS } from './constants';

function createParticle(x, y) {
  return {
    x, y,
    vx: (Math.random() - 0.5) * 250,
    vy: -150 - Math.random() * 100,
    life: 1,
    decay: 0.2 + Math.random() * 0.5,
    color: COLORS[Math.floor(Math.random() * COLORS.length)],
  };
}

function updateParticles(particles, dt, w, h) {
  return particles.filter((p) => {
    p.vy += 200 * dt;
    p.x += p.vx * dt;
    p.y += p.vy * dt;
    p.life -= p.decay * dt;
    if (p.y > h - 20) { p.y = h - 20; p.vy *= -0.5; p.vx *= 0.8; }
    if (p.x > w - 10 || p.x < 10) p.vx *= -1;
    return p.life > 0;
  });
}

module.exports = { createParticle, updateParticles };

constants.js:

javascript
const COLORS = ['#8B5CF6', '#F59E0B', '#EF4444', '#22C55E', '#3B82F6'];
module.exports = { COLORS };

The bundler topo-sorts the graph and compiles modules before rewriting entry imports.

Circular Dependencies ​

Cycles throw at compile time. Move shared pieces into a third leaf module.

Import Resolution ​

SpecifierResolution
'./utils'File named utils or utils.js
'./utils.js'File named utils.js
'../utils'Not supported

Specifier must match the explorer file name (with or without .js).

Troubleshooting ​

ErrorCause
Module not foundSpecifier ≠ file name
Circular import detectedCycle in the graph
Error in module 'X'Syntax/runtime error while compiling that file
dt is not defined in a modulePass dt as an argument from the entry