# Where Are Nodeterm's Node Factories Defined? Complete Guide to the Workspace State Module

> Discover where Nodeterm's node factories are defined in src/renderer/workspace.ts. Learn how createTerminalNode, createStickyNode, and createGroupNode instantiate canvas nodes with consistent identifiers and data.

- Repository: [eneskirca/nodeterm](https://github.com/eneskirca/nodeterm)
- Tags: deep-dive
- Published: 2026-08-26

---

**Nodeterm's node factories are centrally defined in [`src/renderer/state/workspace.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.ts), which exports functions like `createTerminalNode`, `createStickyNode`, and `createGroupNode` to instantiate canvas nodes with consistent identifiers, default dimensions, and persistent data payloads.**

Nodeterm is an open-source terminal workspace manager that organizes applications into a canvas-based node system using Electron. The **node factories** serve as the primary mechanism for creating terminal windows, sticky notes, and grouped containers with uniform schemas. Understanding where these factories live—specifically within the renderer state layer—reveals how the application maintains consistency across its Electron main process, server edition, and mobile companion interfaces.

## Primary Location: The Workspace State Module

The definitive location for all node factory definitions is **[`src/renderer/state/workspace.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.ts)**. According to the nodeterm source code, this module acts as the central hub for node instantiation, exporting factory functions that initialize every node type used within the canvas workflow.

Each factory function follows a consistent pattern:
- Generates a stable identifier (e.g., `term-<hash>` for terminals)
- Applies default sizing and positioning parameters
- Constructs the persistent `data` payload that drives the UI across processes

### Factory Functions Available in workspace.ts

The workspace module exports specialized creators for each node variant:

- **`createTerminalNode`** – Instantiates terminal windows with optional SSH remote Tmux bindings
- **`createStickyNode`** – Generates sticky note components with customizable colors and text
- **`createGroupNode`** – Creates container nodes for organizing related elements
- **`createEditorNode`** – Produces code editor nodes
- **`createDiffNode`** – Initializes diff view components
- **`createVideoNode`** – Handles video player nodes
- **`createWebNode`** and **`createBrowserNode`** – Embed web content
- **`createDinoNode`** – Implements the dinosaur game node

## Technical Implementation of Node Creation

### SSH-Aware Terminal Initialization

In [`src/renderer/state/workspace.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.ts), the `createTerminalNode` function implements specific logic for SSH-connected projects. When a terminal belongs to an SSH project, the factory stamps the **`data.sshRemoteTmux`** flag within the node’s data payload. This marker ensures that the application can correctly restore remote tmux sessions when reopening saved workspaces.

### Stable ID Generation for Persistence

The factory functions generate stable identifiers using hash-based formatting. For example, `createTerminalNode` produces IDs following the `term-<hash>` pattern. This approach guarantees that nodes maintain consistent identities across application restarts and workspace serialization cycles.

```typescript
// Creating a new terminal node with default sizing
import { createTerminalNode } from '@/renderer/state/workspace';

const newTerminal = createTerminalNode(
  0,                          // index
  '/home/user/project',       // working directory
  undefined,                  // size (defaults applied)
  undefined,                  // position (defaults applied)
  undefined                   // non-SSH project
);

```

```typescript
// Creating a sticky note with custom properties
import { createStickyNode } from '@/renderer/state/workspace';

const sticky = createStickyNode(
  1,                                    // index
  { x: 200, y: 150 },                   // position
  { width: 300, height: 150 },          // size
  '#ffeb3b',                            // color
  'Remember to run tests!'              // text
);

```

## Real-World Usage Across the Codebase

### Reopening Persisted Terminals via reopenNode.ts

The file **[`src/renderer/lib/reopenNode.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/lib/reopenNode.ts)** demonstrates factory usage by re-creating nodes from saved workspace data. When restoring a terminal session, it invokes `createTerminalNode` with the stored working directory and SSH binding:

```typescript
import { createTerminalNode } from '@/renderer/state/workspace';

function reopenTerminal(savedData) {
  return createTerminalNode(
    0,                          // index
    savedData.cwd,              // working directory
    undefined,                  // size (defaults applied)
    undefined,                  // position (defaults applied)
    savedData.project?.ssh      // preserves SSH connection flag
  );
}

```

### Unit Testing ID Formats

The test file **[`src/renderer/state/workspace.node-ids.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.node-ids.test.ts)** validates that factory functions produce correctly formatted identifiers. These tests verify the `term-<hash>` pattern and ensure uniqueness constraints required for the canvas rendering engine.

## Summary

- **All node factories reside in [`src/renderer/state/workspace.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.ts)**, centralizing creation logic for terminal, sticky, group, editor, diff, video, web, browser, and dino nodes.
- **The `createTerminalNode` factory handles SSH contexts** by setting `data.sshRemoteTmux` for remote projects and generating stable `term-<hash>` identifiers.
- **[`src/renderer/lib/reopenNode.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/lib/reopenNode.ts) consumes factories** to restore saved workspaces, passing persisted working directories and connection flags.
- **Tests in [`workspace.node-ids.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/workspace.node-ids.test.ts)** validate factory output, ensuring ID uniqueness and format compliance.
- **Centralized factory architecture** guarantees uniform node schemas across the Electron main process, server edition, and mobile companion platforms.

## Frequently Asked Questions

### Where exactly are nodeterm's node factories defined?

The factories are defined in the **[`src/renderer/state/workspace.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.ts)** module within the renderer state layer. This file exports all creation functions including `createTerminalNode` and `createStickyNode`, serving as the single source of truth for node instantiation.

### How does createTerminalNode handle SSH connections?

When the terminal belongs to an SSH project, the factory sets the **`data.sshRemoteTmux`** flag in the node's data payload. This ensures the application can restore the remote tmux session when reopening the workspace.

### What file tests the node factory ID generation?

Unit tests validating factory-generated identifiers are located in **[`src/renderer/state/workspace.node-ids.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/state/workspace.node-ids.test.ts)**. These tests verify that functions like `createTerminalNode` produce correctly formatted IDs.

### How does nodeterm restore saved terminal nodes?

The **[`src/renderer/lib/reopenNode.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/renderer/lib/reopenNode.ts)** module imports factory functions to reconstruct nodes from saved state. It calls `createTerminalNode` with persisted working directories and SSH flags to restore the previous session.