# What Is the Core Platform Seam in nodeterm? Architecture and Implementation Guide

> Understand nodeterm's Core Platform seam, an architectural boundary isolating platform specifics. Run terminal-sharing logic consistently on desktop and servers.

- Repository: [eneskirca/nodeterm](https://github.com/eneskirca/nodeterm)
- Tags: architecture
- Published: 2026-08-23

---

**The Core Platform seam in nodeterm is a strict architectural boundary defined by the `CorePlatform` interface in [`src/core/platform.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/platform.ts) that isolates platform-specific Electron and server implementations from the platform-agnostic core, enabling the same terminal-sharing logic to run unchanged across desktop and headless server environments.**

The nodeterm project by eneskirca implements a sophisticated platform abstraction layer that allows its terminal-sharing engine to operate seamlessly across different deployment targets. At the heart of this architecture lies the Core Platform seam, a contractual interface that prevents the core business logic from directly coupling to Electron APIs or server-specific WebSocket handlers. This design pattern ensures that modules inside `src/core/` remain pure and portable, communicating with the outside world exclusively through a singleton platform instance.

## Defining the CorePlatform Interface Contract

The seam contract is codified in [`src/core/platform.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/platform.ts) as the `CorePlatform` interface. This TypeScript definition establishes the complete vocabulary through which core modules may interact with their host environment, including file system paths, inter-process communication channels, and optional OS-level security features.

### Platform Metadata and Paths

The interface exposes essential environmental properties that every platform must provide:

- **`userDataDir`**: The absolute path where persistent application data lives
- **`appVersion`**: The current semantic version string of the application
- **`isPackaged`**: Boolean flag distinguishing production builds from development mode
- **`resourcesPath`**: Optional string available only on Electron platforms, omitted in server editions

### Communication and IPC Methods

Cross-platform messaging is standardized through a unified RPC interface:

- **`handle(channel, fn)`** and **`on(channel, fn)`**: Register synchronous handlers and event listeners for named channels
- **`handleWithSender(channel, fn)`** and **`onWithSender(channel, fn)`**: Peer-aware variants that include the `senderId` parameter for identifying message origins
- **`sendTo(uiId, channel, ...args)`**: Targeted message delivery to a specific client connection
- **`broadcast(channel, ...args)`**: Fan-out distribution to all connected UI clients
- **`clientIds()`**: Returns an array of active client identifiers for connection management

### Security and External Integration

Platform-specific security capabilities are exposed via optional methods that may be omitted in constrained environments:

- **`sealSecret?(b: Buffer)`** and **`unsealSecret?(b: Buffer)`**: OS keychain integration for credential encryption, implemented only in `ElectronPlatform`
- **`openExternal(url)`**: Async method for delegating URL handling to the host operating system

## Platform Implementations

Two concrete implementations fulfill the `CorePlatform` contract, each optimized for their respective runtime environments according to the nodeterm source code.

### ElectronPlatform for Desktop

Located in [`src/main/platform-electron.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/platform-electron.ts), this implementation bridges the core to the Electron main process. It provides native OS integration including the keychain-backed `sealSecret` and `unsealSecret` methods, access to `resourcesPath` for bundled assets, and peer-aware dispatch mechanisms that route messages through Electron's `webContents` IPC infrastructure.

### ServerPlatform for Headless Deployment

Found in [`src/server/platform-server.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/server/platform-server.ts), this lightweight implementation supports browser-based clients via WebSocket connections. It omits Electron-specific features like `resourcesPath` and secret sealing, instead mapping the communication methods to the WebSocket server (`wsServer`) RPC registry.

## Runtime Initialization and the Singleton Pattern

The platform seam utilizes a singleton pattern established at application startup. The entry point modules construct their respective platform objects and register them via `initPlatform()` before any core modules execute.

**Desktop initialization in [`src/main/index.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/index.ts):**

```typescript
import { initPlatform } from './core/platform';
import { electronPlatform } from './platform-electron';

app.whenReady().then(() => {
  initPlatform(electronPlatform());  // Plug the Electron implementation
  // Window creation and core startup continue...
});

```

**Server initialization in [`src/server/main.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/server/main.ts):**

```typescript
import { initPlatform } from './core/platform';
import { serverPlatform } from './server/platform-server';

initPlatform(serverPlatform());  // Plug the WebSocket-backed implementation

```

Once initialized, core modules retrieve the singleton via the `platform()` accessor function imported from `./core/platform`, ensuring zero direct dependencies on Electron or WebSocket libraries.

## Enforcing the Architectural Boundary

To maintain the integrity of the seam, the repository includes [`src/core/no-electron.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/no-electron.test.ts), which contains static analysis tests that validate core module imports. These tests guarantee that no file within `src/core/` directly references Electron APIs, ensuring that platform abstraction violations are caught during continuous integration rather than at runtime.

## Practical Implementation Examples

### Accessing Platform Services from Core Code

Core modules interact with the filesystem and IPC systems exclusively through the seam:

```typescript
// src/core/pty-manager.ts (excerpt)
import { platform } from './platform';

export async function spawnPty(nodeId: string) {
  const tmuxPath = await findTmux();
  const env = { TMUX: 'node-terminal', ...process.env };
  // Persist socket in platform-agnostic user data directory
  const socket = `${platform().userDataDir}/tmux.sock`;
  // ...
}

```

### Broadcasting Updates Across Platforms

The core remains unaware of whether listeners are Electron webContents or WebSocket peers:

```typescript
// src/core/canvas-sync.ts
import { platform } from './platform';

export function syncCanvasUpdate(update: CanvasUpdate) {
  // Unified broadcast regardless of underlying transport
  platform().broadcast('canvas:update', update);
}

```

### Server-Side WebSocket Mapping

The `ServerPlatform` implementation maps the abstract interface to concrete WebSocket operations:

```typescript
// src/server/platform-server.ts
import { CorePlatform } from '../core/platform';
import { wsServer } from './ws';

export function serverPlatform(): CorePlatform {
  return {
    userDataDir: wsServer.dataDir,
    appVersion: wsServer.version,
    isPackaged: true,
    // No resourcesPath on the server
    handle: (ch, fn) => wsServer.registerHandler(ch, fn),
    on: (ch, fn) => wsServer.registerListener(ch, fn),
    sendTo: (uiId, ch, ...args) => wsServer.sendTo(uiId, ch, ...args),
    broadcast: (ch, ...args) => wsServer.broadcast(ch, ...args),
    clientIds: () => wsServer.clientIds(),
    openExternal: async (url) => { /* remote redirect or no-op */ },
  };
}

```

## Summary

- The **CorePlatform seam** is defined in [`src/core/platform.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/platform.ts) as a TypeScript interface that abstracts all platform-specific capabilities.
- **Two implementations**—`ElectronPlatform` and `ServerPlatform`—provide concrete functionality for desktop and headless environments without modifying core logic.
- **Runtime initialization** occurs via `initPlatform()` in entry points [`src/main/index.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/main/index.ts) and [`src/server/main.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/server/main.ts), establishing a singleton accessible through `platform()`.
- **Strict enforcement** via [`src/core/no-electron.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/no-electron.test.ts) prevents core modules from importing Electron, maintaining architectural purity.
- **Optional interface members** like `sealSecret` allow platforms to expose advanced features while permitting lightweight implementations to omit them.

## Frequently Asked Questions

### What problem does the Core Platform seam solve in nodeterm?

The seam solves the platform coupling problem by preventing terminal-sharing logic from directly importing Electron APIs or server-specific networking code. This allows the same `src/core/` modules to execute identically in a packaged Electron desktop application and a headless browser-accessible server without conditional compilation or runtime forks.

### How does nodeterm prevent core modules from importing Electron directly?

According to the source code, the project maintains [`src/core/no-electron.test.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/no-electron.test.ts), which contains automated tests that statically analyze import statements within the core directory. These tests fail the build if any core module attempts to import Electron, enforcing the architectural boundary at the CI/CD level rather than relying on developer discipline alone.

### Can I implement a custom platform for mobile or embedded targets?

Yes. Any new target can participate in the nodeterm architecture by implementing the `CorePlatform` interface defined in [`src/core/platform.ts`](https://github.com/eneskirca/nodeterm/blob/main/src/core/platform.ts). You must provide the required properties (`userDataDir`, `appVersion`, `isPackaged`) and communication methods (`handle`, `on`, `sendTo`, `broadcast`), then call `initPlatform()` with your implementation at application startup. Optional methods like `sealSecret` may be omitted if the target lacks OS keychain capabilities.

### What happens if a core module calls an optional method that the current platform doesn't implement?

TypeScript's optional chaining and the interface definition using the `?` operator ensure that calls to optional methods like `sealSecret` must be guarded with existence checks. If core code attempts to invoke an unimplemented optional method without verification, it will throw a runtime TypeError. Well-behaved core modules should verify presence using `if (platform().sealSecret)` before invoking platform-specific features.