Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.photon.codes/docs/llms.txt

Use this file to discover all available pages before exploring further.

spectrum-ts is a unified messaging SDK for TypeScript. Write your logic once, deliver it across every platform — iMessage, WhatsApp Business, your terminal, or a custom platform you build yourself.

Installation

npm install spectrum-ts
Requires TypeScript 5 or later (TypeScript 6 is also supported).

Core concepts

Spectrum is built around four primitives:
PrimitiveWhat it represents
MessageAn incoming piece of content — text, attachments, or structured data — from any platform.
SpaceA conversation context. A DM, a group chat, a terminal session. You send messages into a space.
UserA participant on a platform, identified by a platform-specific ID.
Platform providerA platform adapter (iMessage, terminal, WhatsApp, or your own) that translates platform-specific protocols into Spectrum’s unified interface.
Every message arrives as a [Space, Message] tuple. The space gives you the ability to respond; the message gives you the content and metadata.

Quickstart

Get your credentials

Find your PROJECT_ID and SECRET_KEY in your project Settings on the dashboard.

Run your first app

import { Spectrum } from "spectrum-ts";
import { imessage } from "spectrum-ts/providers/imessage";

const app = await Spectrum({
  projectId: "your-project-id",
  projectSecret: "your-project-secret",
  providers: [
    imessage.config(),
  ],
});

for await (const [space, message] of app.messages) {
  if (message.content.type === "text") {
    console.log(`[${message.platform}] ${message.sender.id}: ${message.content.text}`);
    await space.send("hello world");
  }
}
Projectless providers (like terminal) can be used without credentials:
import { Spectrum } from "spectrum-ts";
import { terminal } from "spectrum-ts/providers/terminal";

const app = await Spectrum({
  providers: [terminal.config()],
});

The app instance

Spectrum() returns a — an object that merges a message stream with platform-specific custom event streams.
app.messages                 // AsyncIterable<[Space, Message]>
await app.send(space, ...)   // send into a space
await app.responding(space, fn)  // run fn with a typing indicator
await app.stop()             // graceful shutdown
Custom events emitted by providers are exposed as flat async iterables on the same object — see Custom events and lifecycle.

Multi-platform in three lines

Combine providers to receive and send across platforms simultaneously:
import { Spectrum } from "spectrum-ts";
import { imessage } from "spectrum-ts/providers/imessage";
import { terminal } from "spectrum-ts/providers/terminal";

const app = await Spectrum({
  projectId: process.env.PROJECT_ID!,
  projectSecret: process.env.PROJECT_SECRET!,
  providers: [
    imessage.config(),
    terminal.config(),
  ],
});

for await (const [space, message] of app.messages) {
  await space.responding(async () => {
    await message.reply("Hello from Spectrum.");
  });
}
Messages from every provider merge into the single app.messages stream. The message.platform field identifies the source.

Telemetry

Spectrum has built-in OpenTelemetry instrumentation. Enable it by passing telemetry: true:
const app = await Spectrum({
  projectId: process.env.PROJECT_ID!,
  projectSecret: process.env.PROJECT_SECRET!,
  providers: [imessage.config()],
  telemetry: true,
});
When enabled, Spectrum traces initialization, provider setup, message send/receive/get flows, space resolution, and custom events. Each span includes attributes like the provider name, space ID, content type, and sender kind. Traces are sent to the Photon OTLP endpoint by default. Standard OTEL_EXPORTER_OTLP_* environment variables override the default endpoint and headers. Calling app.stop() flushes any pending telemetry data before shutting down.