Spectrum exposes a family of content builders —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.
text, attachment, voice, contact, richlink, poll, group, custom, reaction, reply, edit, and typing — plus a string shortcut that’s equivalent to text(). Any API that takes a accepts a plain string or a .
Text
Attachments
Pass a file path or aBuffer. MIME types are detected from the file extension; override with options.mimeType when you already have the bytes.
options.mimeType, attachment() throws when the content is built.
Voice
Send a voice note. Same input shape asattachment — a path or a Buffer plus optional metadata.
options.mimeType is omitted, the builder throws at send time.
Voice
Resolved voice content delivered alongside the message.
Voice
Resolved voice content delivered alongside the message.
| Field | Type | Description |
|---|---|---|
mimeType | string | The audio MIME type (e.g. audio/mp4). |
name | string (optional) | Filename for the underlying clip. |
duration | number (optional) | Length in seconds. |
size | number (optional) | Byte length, when known up front. |
read() | () => Promise<Buffer> | Materialize the bytes. |
stream() | () => Promise<ReadableStream> | Stream the bytes — preferred for large clips. |
Contacts
Share contact cards. Thecontact() builder takes either a structured ContactInput, a vCard string, a vcf instance, or a known User paired with optional ContactDetails.
- Structured
- From a User
- From vCard
fromVCard(vcf) parses a vCard string into a ContactInput; toVCard(contact) serializes a resolved Contact back to vCard.
ContactInput
The fields you can populate on a contact card. All fields are optional except where the receiving platform requires at least one identifying field.
ContactInput
The fields you can populate on a contact card. All fields are optional except where the receiving platform requires at least one identifying field.
| Field | Type | Description |
|---|---|---|
name | { formatted?, first?, last?, middle?, prefix?, suffix? } | Structured display name. |
phones | Array<{ value, type? }> | Phone numbers. type is "mobile" | "home" | "work" | "other". |
emails | Array<{ value, type? }> | Email addresses. type is "home" | "work" | "other". |
addresses | Array<{ street?, city?, region?, postalCode?, country?, type? }> | Postal addresses. |
org | { name?, title?, department? } | Employer / org info. |
urls | string[] | Associated URLs. |
birthday | string | ISO date. |
note | string | Free-form note. |
photo | { mimeType, read() } | Profile photo bytes. |
raw | unknown | Provider-specific extras passed through untouched. |
Rich links
Render a URL as a rich preview card with title, summary, and cover image. Spectrum scrapes Open Graph metadata at send time; pass just the URL and the builder fills in the rest.title(), summary(), and cover() are lazy async accessors — the metadata fetch happens only if the receiving platform needs it. Platforms without rich-link support fall back to the URL as plain text.
Richlink
Resolved rich-link content with lazy metadata accessors.
Richlink
Resolved rich-link content with lazy metadata accessors.
| Field | Type | Description |
|---|---|---|
url | string | The original URL. |
title() | () => Promise<string | undefined> | OG title. |
summary() | () => Promise<string | undefined> | OG description. |
cover() | () => Promise<{ mimeType?, read(), stream() } | undefined> | OG image. |
Polls
Send a poll with a title and a list of choices. Each choice can be a plain string or a object — useoption() when you want the explicit form.
poll_option content — see Messages for narrowing on incoming votes.
Groups
Agroup bundles multiple messages into one logical unit (an album of images, a multi-attachment reply). Each item is delivered as its own Message, but they ship together so the receiving platform can render them as a single visual group when supported.
Custom
Send structured, platform-specific payloads. Use this when the receiving platform supports rich content types that don’t fit into the built-in builders.send action — it’s up to the provider to interpret it.
Replies
Send a threaded reply by wrapping content with the message being replied to. See Reactions and replies for the full details and sugar methods.reply() cannot wrap reply, edit, reaction, group, or typing content.
Edits
Rewrite the content of a previously-sent outbound message. Edits are fire-and-forget —space.send(edit(...)) resolves to undefined.
edit() cannot wrap edit, reply, reaction, group, or typing content.
Typing indicators
Send a typing indicator signal through the content pipeline. Defaults to"start".
space.startTyping(), space.stopTyping(), and space.responding(fn) are sugar over space.send(typing(...)). Platforms without a typing-indicator API silently no-op.
Composing multiple items
All send methods take a variadic list. Items are sent sequentially as separate messages:send() per item on the underlying provider — not a single compound message. Reach for group(...) instead when you specifically want them rendered as one bundled unit.
Replies (sugar)
message.reply(...) has the same variadic signature and delegates to space.send(reply(...)) internally:
reply() resolves as a no-op. If you need guaranteed delivery, use space.send(...) instead. See Reactions and replies for the canonical form and more details.