Multi-file projects in Code Mode
Organize your Code Mode scripts across multiple files using imports, exports, and package.json configuration.
Multi-file projects in Code Mode
As your scripts grow, you can organize code across multiple files. This makes complex projects more manageable and allows you to reuse utility functions across different scripts.
Adding files
To add a new file to your project:
- Click the + button in the file tab bar above the editor
- Enter a filename with a
.tsor.jsextension (for example,utils.tsorlib/helpers.ts) - Click Add File
The new file opens in the editor and appears as a tab in the file bar.
File naming
- Use relative paths like
utils.tsorlib/helpers.ts - Files must have
.tsor.jsextensions - Filenames can contain letters, numbers, underscores, hyphens, and forward slashes
Closing files
To close a file, click the X on its tab. You cannot close the main file (main.ts) or package.json.
Closing a file removes it from the project. If you need the file again, you must re-add it.
Importing between files
Use standard ES module syntax to import and export between files.
Exporting from a file
Export functions, constants, or types from a file:
// utils.ts
export function createRoundedCube(size: number, radius: number) {
// implementation
}
export const DEFAULT_SEGMENTS = 32;
Importing into another file
Import using relative paths with ./:
// main.ts
import { createRoundedCube, DEFAULT_SEGMENTS } from './utils';
import { Manifold } from 'manifold-3d/manifoldCAD';
const cube = createRoundedCube(20, 2);
export const result = cube;
Nested directories
For files in subdirectories, use the full relative path:
// main.ts
import { helperFunction } from './lib/helpers';
import { constants } from './config/settings';
The package.json file
Every project includes a package.json file that CADit manages automatically. This file tracks your project's dependencies and configuration.
Automatic updates
When you import npm packages in your code, CADit detects them and updates package.json automatically. For example, if you add:
import _ from 'lodash';
CADit adds lodash to the dependencies in package.json.
Manual editing
You can edit package.json directly to:
- Pin specific package versions
- Add packages before using them in code
- Set the project name
Example package.json:
{
"name": "@cadit-app/my-project",
"version": "1.0.0",
"type": "module",
"dependencies": {
"lodash": "^4.17.21"
}
}
The main entry point
The main.ts file (or whatever file appears first in the tab bar) is the entry point. This file must export a result variable or use defineParams with a main function.
If you rename the main file or want to use a different entry point, update the main file name in your project settings.
Example: Organizing a parametric design
Here is how you might structure a multi-file parametric design:
geometry.ts - Reusable geometry functions:
import { Manifold } from 'manifold-3d/manifoldCAD';
export function createFilletedBox(
width: number,
height: number,
depth: number,
radius: number
) {
// Create box with filleted edges
const box = Manifold.cube([width, height, depth], true);
// ... filleting logic
return box;
}
export function createMountingHole(diameter: number, depth: number) {
return Manifold.cylinder(depth, diameter / 2);
}
constants.ts - Shared constants:
export const WALL_THICKNESS = 2;
export const MOUNTING_HOLE_DIAMETER = 4;
export const DEFAULT_FILLET_RADIUS = 1;
main.ts - Main entry point with parameters:
import { defineParams } from '@cadit-app/script-params';
import { Manifold } from '@cadit-app/manifold-3d/manifoldCAD';
import { createFilletedBox, createMountingHole } from './geometry';
import { WALL_THICKNESS, MOUNTING_HOLE_DIAMETER } from './constants';
export default defineParams({
params: {
width: { type: 'slider', default: 50, min: 20, max: 100 },
height: { type: 'slider', default: 30, min: 10, max: 60 },
depth: { type: 'slider', default: 50, min: 20, max: 100 },
addHoles: { type: 'switch', default: true, label: 'Add mounting holes' },
},
main: (params) => {
const box = createFilletedBox(
params.width,
params.height,
params.depth,
2
);
if (!params.addHoles) {
return box;
}
const hole = createMountingHole(MOUNTING_HOLE_DIAMETER, WALL_THICKNESS + 1);
const holePositions = [
[params.width / 4, 0, params.depth / 4],
[-params.width / 4, 0, params.depth / 4],
[params.width / 4, 0, -params.depth / 4],
[-params.width / 4, 0, -params.depth / 4],
];
let result = box;
for (const [x, y, z] of holePositions) {
result = result.subtract(
hole.translate([x, -params.height / 2, z])
);
}
return result;
},
});
Tips
- Keep utility functions in separate files for reusability
- Use a
constants.tsfile for values used in multiple places - Keep
main.tsfocused on the high-level structure - Name files descriptively to communicate their purpose
- Use subdirectories like
lib/for helper modules if your project grows large
Next steps
- Code Mode basics - Review the fundamentals of creating geometry
- Code Mode parameters - Add parameters to create customizable designs