Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs-src/spectrum-ts/content.mdx.vel
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Use this section when you need to choose the right outbound content shape or und
Share contact cards from structured data, users, or vCards.
</Card>
<Card title="Rich links" icon="link" href="/spectrum-ts/content/rich-links">
Render URLs as rich previews with lazy Open Graph metadata.
Send URLs as rich preview cards rendered by the receiving platform.
</Card>
<Card title="App link cards" icon="panel-top" href="/spectrum-ts/content/app-link-cards">
Present URLs as tappable app-style cards where providers support them.
Expand Down
16 changes: 8 additions & 8 deletions docs-src/spectrum-ts/content/rich-links.mdx.vel
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
title: "Rich links"
description: "Render URLs as rich previews with lazy Open Graph metadata."
description: "Send URLs as rich preview cards rendered by the receiving platform."
---

Use `richlink()` to 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.
Use `richlink()` to send a URL as a rich preview card. Each platform's native client renders the preview — iMessage enables `enableLinkPreview`, Telegram auto-unfurls the bare URL. Spectrum carries only the URL; metadata fetching is left to the platform.

```ts
import { richlink } from "spectrum-ts";

await space.send(richlink("https://example.com/article"));
```

`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.
Platforms without rich-link support fall back to the URL as plain text.

<Accordion title="Richlink" description="Resolved rich-link content with lazy metadata accessors.">
`richlink` is **outbound-only**. Inbound URLs always arrive as `text` content — a URL received from any platform is normalized to its URL string and deserialized as plain `text`, never as a `richlink` payload.

<Accordion title="Richlink" description="A URL the platform should render as a rich link preview.">
| 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. |
| `type` | `"richlink"` | Content discriminator. |
| `url` | `string` | The URL to preview. |
</Accordion>
2 changes: 1 addition & 1 deletion docs-src/spectrum-ts/introduction.mdx.vel
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ You do not have to manage Spectrum only from the dashboard. Use the dashboard fo
Install `spectrum-ts` and send your first message.
</Card>
<Card title="Webhooks" icon="webhook" href="/spectrum-ts/webhooks">
Receive messages via HTTP with native and Fusor webhook support, plus Hono, Express, and Elysia adapters.
Receive messages via HTTP with native and Fusor webhook support, plus Hono, Express, Elysia, and Fastify adapters.
</Card>
<Card title="Build a custom platform" icon="blocks" href="/spectrum-ts/custom-platforms">
Add a new interface with Spectrum's provider model.
Expand Down
32 changes: 31 additions & 1 deletion docs-src/spectrum-ts/webhooks.mdx.vel
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,39 @@ First-party adapters mount the endpoint for you and handle raw-body parsing corr
.listen(3000);
```
</Tab>
<Tab title="Fastify">
```ts
import Fastify from "fastify";
import { Spectrum } from "spectrum-ts";
import { imessage } from "spectrum-ts/providers/imessage";
import { spectrum } from "@spectrum-ts/fastify";

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

const server = Fastify();

server.register(spectrum, {
app,
onMessage: async (space, message) => {
if (message.content.type === "text") {
await space.send(`echo: ${message.content.text}`);
}
},
});

await server.listen({ port: 3000 });
```

Fastify auto-parses known content types before your route handler runs, which breaks HMAC verification. The `@spectrum-ts/fastify` plugin registers a wildcard raw-body parser in its own encapsulated scope, so the webhook route receives exact wire bytes while your other routes keep their normal JSON parsing.
</Tab>
</Tabs>

All three adapters accept the same options:
All four adapters accept the same options:

| Option | Type | Default | Description |
|---|---|---|---|
Expand Down
12 changes: 6 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading