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

The Core Platform seam in nodeterm is a strict architectural boundary defined by the CorePlatform interface in 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 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, 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, 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:

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:

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, 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:

// 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:

// 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:

// 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 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 and src/server/main.ts, establishing a singleton accessible through platform().
  • Strict enforcement via 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, 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →