Skip to main content

My First Component

Let's create your first component to get started with DynaMaker!

In this tutorial, you will learn how to create a project with a component from the default template, and then how to modify its geometry so that it follows its configurable size. It also covers the basics of presets, refactoring & debugging. As a product example, we will use a configurable flat metal bracket with some holes.

For this we will follow 5 simple steps:

  1. Create new project
  2. Modify model
  3. Presets
  4. Refactoring
  5. Debugging

This tutorial takes approximately 20 minutes to complete. Good luck!

1. Create New Project

In your team dashboard you can add as many projects as you want. Try the following:

  • Add one and name it for example BracketApp.
  • Select the Toolbar position you want to give to your app.

Now you should see your project in your team like the following:


By clicking on the thumbnail or name of your project, you will go to the project dashboard, as follows:


Great, let's identify the component and see where to modify its geometry. Understanding how the component is structured is the key to create your app in the best way possible.

  • Under the section Components, open the component Component1 (by clicking the thumbnail or name).
  • Here we find two sections: the Preview (left side) and the Code editor (right side).


  • On the right side of the Code editor, you will find the file menu including:
    • PRESETS: for specifying how the preview should look, including tests (we skip this for this tutorial).
    • COMPONENT: for defining your component, including Component (to create its properties and more).
    • PARAMETERS: here you can find the 3 parameters used for the UI and modifying the model.
    • GEOM: for defining the geometry of the component, separated in GEOM2D (for 2D representation) and GEOM3D (for 3D representation).
    • CONSTANTS: to store all your constants.
    • API: intended for advanced features (we skip this as well for now).

2. Modify Model

We will modify the model in 4 different steps:

A. Flat sheet

To change the height of the cube, we need to update its default property value and make sure the parameter Height (z) has reasonable options.

  • In COMPONENT, notice that in the constructor we have the properties depth, height & width.

  • Change the default value of height from 100 to 2, as:

    constructor() {
    super() = {
    depth: 100,
    height: 2,
    width: 100,
  • Save & Update at the bottom (Ctrl+S) to see the change in the _Preview_.

Great! However, the parameter Height (z) has options with too high values. Let's fix it:

  • In PARAMETER, identify heightParameter and update the values to reasonable ones, like:
    const heightParameter = SKYPARAM.generateDropdown('height', 'Height (z)', [
    new SKYPARAM.DropdownItem('0.7', 0.7),
    new SKYPARAM.DropdownItem('2', 2),
    new SKYPARAM.DropdownItem('5', 5),
    ], { unit: 'mm' })
  • Save & Update and you will see that the second option (`2 mm`) is the default one because it matches the default property value we chose previously.


B. Holes

Let's add some holes that dynamically dis/appear depending on the size of the sheet. For now, let's start adding a hole in the middle.

  • In COMPONENT, notice that generateGeometry() is using generateModel() that comes fromGEOM3D.
  • In GEOM3D, go to the function generateModel().
  • Create a circle sketch for a hole in the center and name it holeSketch.
    const holeSketch = SKYCAD.generateCircleSketch(width / 2, depth / 2, 7) // position = (width / 2, depth / 2); diameter = 7
  • Create a plane on top of the sheet and name it topPlane.
    const topPlane = new SKYCAD.Plane(0, 0, 1, height)
  • Use the existing model to add the extrude cut and give as arguments:
    • holeSketch as the sketch to define the shape of the cut.
    • topPlane as the plane from where the cut is done.
    • -height for the length of the cut (negative since the normal of the plane is pointing outwards).
    model.addExtrudeCut(holeSketch, topPlane, -height)
  • Save & Update to save the changes and update the model.

Perfect! We will repeat this process for more holes in the rest of the corners, but we will add some rules so the holes don't collide with each other for example. As an example you can have the following:

const topPlane = new SKYCAD.Plane(0, 0, 1, height)
const MARGIN = 15

if (width <= 50 && depth <= 50) {
const holeSketch = SKYCAD.generateCircleSketch(width / 2, depth / 2, HOLE_DIAMETER)
model.addExtrudeCut(holeSketch, topPlane, -height)
} else if (width > 50 && depth <= 50) {
const leftHoleSketch = SKYCAD.generateCircleSketch(MARGIN, depth / 2, HOLE_DIAMETER)
const rightHoleSketch = SKYCAD.generateCircleSketch(width - MARGIN, depth / 2, HOLE_DIAMETER)
model.addExtrudeCut(leftHoleSketch, topPlane, -height)
model.addExtrudeCut(rightHoleSketch, topPlane, -height)
} else if (width <= 50 && depth > 50) {
const bottomHoleSketch = SKYCAD.generateCircleSketch(width / 2, MARGIN, HOLE_DIAMETER)
const topHoleSketch = SKYCAD.generateCircleSketch(width / 2, depth - MARGIN, HOLE_DIAMETER)
model.addExtrudeCut(bottomHoleSketch, topPlane, -height)
model.addExtrudeCut(topHoleSketch, topPlane, -height)
} else {
const bottomLeftHoleSketch = SKYCAD.generateCircleSketch(MARGIN, MARGIN, HOLE_DIAMETER)
const bottomRightHoleSketch = SKYCAD.generateCircleSketch(width - MARGIN, MARGIN, HOLE_DIAMETER)
const topLeftHoleSketch = SKYCAD.generateCircleSketch(MARGIN, depth - MARGIN, HOLE_DIAMETER)
const topRightHoleSketch = SKYCAD.generateCircleSketch(width - MARGIN, depth - MARGIN, HOLE_DIAMETER)
model.addExtrudeCut(bottomLeftHoleSketch, topPlane, -height)
model.addExtrudeCut(bottomRightHoleSketch, topPlane, -height)
model.addExtrudeCut(topLeftHoleSketch, topPlane, -height)
model.addExtrudeCut(topRightHoleSketch, topPlane, -height)


Try different values for the parameters Width (x) and Depth (y) and see how the holes behave when having values lower and higher than 50 in this case.

C. Fillet

As a third step, we can also round the corners. For that we can simply add fillets for each node of baseSketch.

const CORNER_RADIUS = 10
const baseSketch = SKYCAD.generateRectangleSketch(0, 0, width, depth)
baseSketch.getNodes().forEach((node, nodeId) => {
baseSketch.addFillet(CORNER_RADIUS, nodeId)


D. Color

Changing the color of the component is very easy and has to be changed when adding the model to a geometry group, which contains information about the position, rotation and materials.

  • In COMPONENT, go to generateGeometry().
  • See that the model is added to the geometry group with materials, which contains the color, whose value comes from CONSTANTS.
  • Go to CONSTANTS and set it to gray as MATERIAL_COLOR = 0xCCCCCC, so that:


3. Presets

Notice that we only have been working with the component so far. We can try different values of the parameters (Width (x), Depth (y) & Height (z)) within the component without going to the app. The advantage of this is that you can immediately see how the parameters affect your new features, e.g. the distribution of holes in this case. However, sometimes you want to save some specific edge cases to keep track of their behavior for later. In DynaMaker, we use presets with specific properties for this. Let's add a couple of presets:

  • Under mainComponentPreset add the edge cases you want to see. For example, try these to see the distribution of holes at width = 50 with the code we wrote before in section B. Holes:
mainComponentPreset.addCase([], {
postProcessor: (component: COMPONENT.Component) => {
width: 50,
depth: 150,
height: 0.7,
label: '50 x 150 x 0.7',

mainComponentPreset.addCase([], {
postProcessor: (component: COMPONENT.Component) => {
width: 51,
depth: 150,
height: 0.7,
label: '51 x 150 x 0.7'
  • Switch between components presets in the dropdown at the top-right corner of the Preview.
  • Keep adding more presets until you covered all the edge cases, e.g. in this case:


4. Refactoring

Cleaning the code or refactoring is quite important to make clear what you do in your components. Remember that you might not be the only one working on the project, so whatever you write has to be clear for anyone jumping into your project at any stage.

Imagine that someone wrote a function that does a lot of complex calculations. It works perfectly until 1 month later that a new feature is requested. Then the calculations must be changed and some things are wrong or simply not useful anymore. And add the extra difficulty when the developer that has to fix it is you and not the person that wrote it initially.

So as a first recommendation, keep things where they should be. In this case, the hole sketches are in

GEOM3D, but ideally we should have done it in GEOM2D and have it something like:
// GEOM 2D
export function generateHoleSketch (posX: number, posY: number) {
const holeSketch = SKYCAD.generateCircleSketch(posX, posY, HOLE_DIAMETER)
return holeSketch
// GEOM 3D
// [...]
if (width <= 50 && depth <= 50) {
const holeSketch = GEOM2D.generateHoleSketch(width / 2, depth / 2)
model.addExtrudeCut(holeSketch, topPlane, -height)
} else if (width > 50 && depth <= 50) {
// [...]

Remember to export the function in GEOM2D if you want to use it anywhere else, or you won't be able to use it in e.g. GEOM3D. Also, the code completion should help you notice that.

And as a second recommendation, keep things with a proper name, so when you read it you know what it does. In this case in GEOM3D, having 50 everywhere is bad because you might wonder later what does this 50 mean?. For that, you should keep these numbers in variables or const. And also, if you use these variables somewhere else you should move them to CONSTANTS. For example:

export const HOLE_DIAMETER = 7
export const SIZE_LIMIT_FOR_HOLES = 50
// GEOM 2D
export function generateHoleSketch (posX: number, posY: number) {
const holeSketch = SKYCAD.generateCircleSketch(posX, posY, CONSTANTS.HOLE_DIAMETER)
return holeSketch
// GEOM 3D
// [...]
const holeSketch = GEOM2D.generateHoleSketch(width / 2, depth / 2)
model.addExtrudeCut(holeSketch, topPlane, -height)
// [...]

5. Debugging

When something is wrong in your component and you don't know exactly where the problem comes from, it's time for stepping into the code and check what's happening at specific points, also known as debugging.

Let's show a typical problem that can be fixed in 1 line of code. Taking the component we have made as an example, we have introduced an intentioned bug. Knowing that the UI has been modified to make it easier, are you able to find the width and depth that causes a bug with one of the holes in this app?

Show solution:

Exactly, when width < 50 and depth < 50 the hole gets misplaced. tutorial-my-first-component-bug

Since it's related to geometry, what you would do is:

  • Go to your component (Component1 in this case).
  • Create a new preset with the values you found the bug with (e.g. width = 20 and depth = 30).
  • Save & Update and make sure to use that preset.

Now you would see the problem clearly with those values. Let's start debugging:

  • Still in your component, go to GEOM3D.
  • Open the browser console (F12)
  • Type debugger right before you want to start debugging.
  • Save & Update to apply the change, Notice that it stops exactly at the line you typed `debugger`.


By pressing F10 you can go on with the debugging line by line.

In this case, we find that we have swapped depth & width in line 16, so the correct code should have been:

const holeSketch = GEOM2D.generateHoleSketch(width / 2, depth / 2)

Read more about debugging here.

Congratulations! You have finished the first tutorial. Having the component in an app would look like this:

Now that we know how to create components, let's create an assembly with multiple components in the next tutorial My First Assembly.