ResendExplainer
Engineering a Vercel Chat Adapter
Summary
Vercel’s Chat SDK supports bots across multiple chat platforms, but those channels can be ephemeral and leave conversations buried in feeds and threads. Email offers a persistent, widely used channel, so Resend built an official adapter that treats email as bidirectional chat. Inbound mail arrives through Resend webhooks and triggers Chat SDK handlers, while outbound messages use the Resend API. The adapter reconstructs threads from In-Reply-To and References headers, tracking message-to-thread mappings in an in-memory Map and generating IDs from the sender address and a SHA-256 prefix of the root Message-ID. It also translates Chat SDK messages, including markdown and CardElement structures, into email HTML and plain-text content through React Email components, trading richer native chat semantics for email’s reach and simpler delivery model.
Context
The adapter connects Vercel’s open-source, TypeScript Chat SDK to email through Resend. It addresses the persistence and reach of email while accommodating email’s less structured threading and content representations.
Approach / What changed
Implement the Chat SDK’s parseMessage and postMessage methods for email. Incoming messages use Resend webhooks and are mapped to SDK events; outgoing strings, markdown, ASTs, and cards are converted into email HTML and plain text. ThreadResolver uses In-Reply-To and References to find existing conversations, or hashes a Message-ID to create a thread ID, storing mappings in an in-memory Map.
Takeaways
Email threading is reconstructed from In-Reply-To and References headers because email provides no central thread ID.
The adapter stores message-to-thread relationships in an in-memory Map, relying on email’s References header for conversation history rather than persistence.
Chat SDK CardElement values map to React Email components such as Text, Button, Img, and Hr for email rendering.
FAQ
How does the adapter determine whether an incoming email belongs to an existing thread?
ThreadResolver extracts message IDs from In-Reply-To and References and checks them against its message-to-thread Map. A match reuses the existing thread; otherwise, the adapter hashes the new Message-ID to create a thread ID.
How are structured Chat SDK cards represented in email?
CardElement types are converted to React Email components. Text becomes Text, link-buttons become Button, images become Img, dividers become Hr, and fields become a bolded label followed by their value.
Source and freshness
- Source
- resend.com
- Published
- Added to Yomu
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.