> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nodi3d.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Modular is a module project designed to import node graphs created in Nodi in JSON format, enabling the extraction of geometric data generated based on the node graph structure.

# Prepare Project

Place .json file exported from [app.nodi3d.com](app.nodi3d.com)

<Frame>
  <img src="https://mintcdn.com/nodi/HoCRFHodyhFyaHzr/images/nodi-modular/modular_export.png?fit=max&auto=format&n=HoCRFHodyhFyaHzr&q=85&s=c8b2a030d4efc9ef19a1b58ee82811ba" style={{ borderRadius: '0.5rem', width:'100%', height:'auto' }} width="485" height="230" data-path="images/nodi-modular/modular_export.png" />
</Frame>

# Install

nodi3d/modular is available via npm:

```mdx theme={null}
npm install @nodi3d/modular
```

Features can now be imported via `"@nodi3d/modular"`

```mdx theme={null}
import init, { Modular } from "@nodi3d/modular";
```

# Usage

<Tabs>
  <Tab title="JS">
    ```JS theme={null}
      
      import init, { Modular } from "@nodi3d/modular";

      // Initialize the WebAssembly module
      await init();

      // Create a new instance of the Modular
      const modular = Modular.new();

      // Load a node graph in JSON format as a string
      modular.loadGraph(JSON.stringify({
        nodes: { ... },
      }));

      // Evaluate the node graph to get the result
      const result = modular.evaluate();

      // Geometry identifiers are the keys of the geometries in the result
      const { geometryIdentifiers } = result;

      geometryIdentifiers.forEach((identifier) => {
        // Get the geometry variant by identifier
        // variants are curve, surface, mesh, and etc.
        const geometry = modular.findGeometryById(identifier);

        // Get the geometry interop by identifier
        // geometry interop has the data that can be rendered as a polygonalized data (polyline or triangle mesh)
        const interop = modular.findGeometryInteropById(identifier);
      });

      // Get the nodes of the node graph
      const nodes = modular.getNodes();

      // Find the node by the variant and label
      const numberOfGrid = nodes.find((n) => n.variant === "Number" && n.label === 'number of grid');

      // Each nodes have the properties that can be changed
      // What properties can be changed depends on the node variant, so you need to check the node variant's properties (numberGrid["properties"])
      modular.changeNodeProperty(numberOfGrid.id, {
        name: "value",
        value: {
          type: "Number",
          content: 30,
        }
      });

      // re-evaluate the node graph to get the result after the property change
      const resultAfterPropertyChange = await modular.evaluate();

    ```
  </Tab>

  <Tab title="React">
    ```JS theme={null}
      import init, { Modular } from "@nodi3d/modular";

      .
      .
      .


      const [modular, setModular] = useState<Modular | null>(null);
      const [nodes, setNodes] = useState<NodeInterop[]>([]);
      const [geometries, setGeometries] = useState<BufferGeometry[]>([]);

      const evaluate = useCallback(
        (m: Modular) => {
          m.evaluate().then((e) => {
            const { geometryIdentifiers } = e;

            const gs = geometryIdentifiers
              .map((id) => {
                const interop = m.findGeometryInteropById(id);
                const { transform } = id;

                switch (interop?.variant) {
                  case "Mesh": {
                    const { data } = interop;
                    const geometry = new BufferGeometry();

                    const { vertices, normals, faces } = data;

                    geometry.setAttribute(
                      "position",
                      new BufferAttribute(new Float32Array(vertices.flat(1)), 3)
                    );
                    geometry.setAttribute(
                      "normal",
                      new BufferAttribute(new Float32Array(normals.flat(1)), 3)
                    );
                    if (faces !== undefined) {
                      geometry.setIndex(
                        new BufferAttribute(new Uint32Array(faces.flat(1)), 1)
                      );
                    }

                    geometry.applyMatrix4(new Matrix4().fromArray(transform));

                    return geometry;
                  }
                  default: {
                    return null;
                  }
                }
              })
              .filter((g): g is BufferGeometry => g !== null);
            setGeometries(gs);
          });
        },
        []
      );

      .
      .
      .

      useEffect(() => {
        (async () => {
          await init();
          setModular(Modular.new());
        })();
      }, []);

      useEffect(() => {
        if (modular !== null) {
          modular.loadGraph(JSON.stringify(shell.graph));
          // modular.loadGraph(JSON.stringify(brickWall.graph));
          const nodes = modular.getNodes();
          const numberNodes = nodes.filter((n) => n.variant === "Number" || n.variant === "NumberSlider");
          setNodes(numberNodes);
          evaluate(modular);
        }
      }, [modular, evaluate]);
    ```
  </Tab>
</Tabs>
