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
Requires TypeScript 5 or later (TypeScript 6 is also supported).
Core concepts
Spectrum is built around four primitives:
| Primitive | What it represents |
|---|
| Message | An incoming piece of content — text, attachments, or structured data — from any platform. |
| Space | A conversation context. A DM, a group chat, a terminal session. You send messages into a space. |
| User | A participant on a platform, identified by a platform-specific ID. |
| Platform provider | A 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.
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.