API Reference@liveblocks/emails

@liveblocks/emails provides a set of functions that simplifies sending styled emails with Notifications and webhooks. This library is only intended for use in your Node.js back end.

Setup

This package exposes functions that enable easy creation of styled emails with React and HTML. Each method is designed to be used with our webhooks which means you must set them up first. Webhooks require an API endpoint in your application, and this is typically what they will look like.

Next.js route handler for webhooks
import { isThreadNotificationEvent, WebhookHandler } from "@liveblocks/node";import { Liveblocks } from "@liveblocks/node";import { prepareThreadNotificationEmailAsReact } from "@liveblocks/emails";
const liveblocks = new Liveblocks({ secret: "",});
const webhookHandler = new WebhookHandler( process.env.LIVEBLOCKS_WEBHOOK_SECRET_KEY as string);
export async function POST(request: Request) { const body = await request.json(); const headers = request.headers;
// Verify if this is a real webhook request let event; try { event = webhookHandler.verifyRequest({ headers: headers, rawBody: JSON.stringify(body), }); } catch (err) { console.error(err); return new Response("Could not verify webhook call", { status: 400 }); }
// Using `@liveblocks/emails` to create an email if (isThreadNotificationEvent(event)) { const emailData = await prepareThreadNotificationEmailAsReact( liveblocks, event );
if (emailData.type === "unreadMention") { const email = ( <div> <div> @{emailData.comment.author.id} at {emailData.comment.createdAt} </div> <div>{emailData.comment.reactBody}</div> </div> );
// Send unread mention email // ... } }
return new Response(null, { status: 200 });}

We’ll only show the highlighted part below, as it’s assumed you’ve set this already, and your file contains liveblocks and event.

Thread notification emails

These functions help you create emails to notify users of unread comments in threads. They fetch each relevant comment, filtering out any that have already been read, and help you style each comment’s body with either React or HTML.

An email showing 7 new comments, with comment bodies and links to each comment

The function also helps you distinguish between unread mentions and unread replies.

A thread has unread replies if a comment was created after the readAt date on the notification, and created before or at the same time as the notifiedAt date. All unread replies are returned in an array.

{  type: "unreadReplies",  roomId: "my-room-id",  comments: [    {/* Comment data */},    // ...  ],}

A thread has an unread mention if it has unread replies, and one of the replies mentions the user. A single comment with the latest mention is returned.

{  type: "unreadMentions",  roomId: "my-room-id",  comment: {/* Comment data */},}

prepareThreadNotificationEmailAsReact

Takes a thread notification webhook event and returns unread comment body(s) related to the notification, as React nodes. It can return one of three formats, an unreadMention type containing one comment, an unreadReplies type returning multiple comments, or null if there are no unread mentions/replies. You can also resolve user & room data and customize the components.

import { prepareThreadNotificationEmailAsReact } from "@liveblocks/emails";import { isThreadNotificationEvent } from "@liveblocks/node";
// Get `liveblocks` and `event` (see "Setup" section)// ...
if (isThreadNotificationEvent(event)) { const emailData = await prepareThreadNotificationEmailAsReact( liveblocks, event ); let email;
switch (emailData.type) { case "unreadMention": { email = ( <div> <div> @{emailData.comment.author.id} at {emailData.comment.createdAt} </div> <div>{emailData.comment.reactBody}</div> </div> ); break; }
case "unreadReplies": { email = ( <div> {emailData.comments.map((comment) => ( <div key={comment.id}> <div> @{comment.author.id} at {comment.createdAt} </div> <div>{comment.reactBody}</div> </div> ))} </div> ); break; } }}
// Send your email// ...

It’s designed to be used in a webhook event, which requires a Liveblocks Node.js client and a WebhookHandler. Check for the correct webhook event using isThreadNotificationEvent before running the function, such as in this Next.js route handler.

Returns
  • valueThreadNotificationEmailDataAsReact | null

    Returns comment information, and a formatted React body, ready for use in emails. Returns null if there are no unread mentions or replies. The result has two formats depending on whether this notification is for a single unread mention, or for multiple unread replies:

Arguments
  • clientLiveblocksRequired

    A Liveblocks Node.js client.

  • eventThreadNotificationEventRequired

    An object passed from a webhook event, specifically the ThreadNotificationEvent. Learn more about setting this up.

  • optionsobject

    A number of options to customize the format of the comments, adding user info, room info, and styles.

  • options.resolveUsers

    A function that resolves user information in Comments. Return an array of UserMeta["info"] objects in the same order they arrived. Works similarly to the resolver on the client. Learn more.

  • options.resolveRoomInfo

    A function that resolves room information. Return a RoomInfo object, as matching your types. Works similarly to the resolver on the client but for one room. Learn more.

  • options.componentsobject

    Pass different React components to customize the elements in the comment bodies. Five components can be passed to the object: Container, Paragraph, Text, Link, Mention. Learn more.

  • options.components.Container({ children: ReactNode }) => ReactNode

    The comment body container.

  • options.components.Paragraph({ children: ReactNode }) => ReactNode

    The paragraph block.

  • options.components.Text({ children: ReactNode }) => ReactNode

    The text element.

  • options.components.Link

    The link element.

  • options.components.Mention

    The mention element.

Resolving data

Similarly to on the client, you can resolve users and room info, making it easier to render your emails. For example, you can resolve a user’s ID into their name, and show their name in the email.

const emailData = await prepareThreadNotificationEmailAsReact(  liveblocks,  webhookEvent,  {    resolveUsers: async ({ userIds }) => {      const usersData = await (userIds);
return usersData.map((userData) => ({ name: userData.name, // "Nimesh" avatar: userData.avatar.src, // "https://..." })); }, resolveRoomInfo({ roomId }) { return { name: roomId, // "my-room-name" url: `https://example.com/${roomId}`, }; }, });
// { type: "unreadMention", comment: { ... }, ... }console.log(emailData);
// { name: "Nimesh", avatar: "https://..." }console.log(emailData.comment.author.info);
// { name: "my-room-name", url: "https://example.com/my-room-name" }console.log(emailData.roomInfo);

Customizing components

Each React component in the comment body can be replaced with a custom React component, if you wish to apply different styles. Five components are available: Container, Paragraph, Text, Link, Mention.

const emailData = await prepareThreadNotificationEmailAsReact(  liveblocks,  webhookEvent,  {    components: {      Paragraph: ({ children }) => <p>{children}</p>,
// `react-email` components are supported Text: ({ children }) => ( <Text className="text-sm text-black m-0 mb-4">{children}</Text> ),
// `user` is the optional data returned from `resolveUsers` Mention: ({ element, user }) => ( <span style={{ color: "red" }}>@{user?.name ?? element.id}</span> ),
// If the link is rich-text render it, otherwise use the URL Link: ({ element, href }) => <a href={href}>{element?.text ?? href}</a>, }, });
// { type: "unreadMention", comment: { ... }, ... }console.log(emailData);
// The components are now used in this React bodyconsole.log(emailData.comment.reactBody);

prepareThreadNotificationEmailAsHtml

Takes a thread notification webhook event and returns unread comment body(s) related to the notification, as an HTML-safe string. It can return one of three formats, an unreadMention type containing one comment, an unreadReplies type returning multiple comments, or null if there are no unread mentions/replies. You can also resolve user & room data and customize the styles.

import { prepareThreadNotificationEmailAsHtml } from "@liveblocks/emails";import { isThreadNotificationEvent } from "@liveblocks/node";
// Get `liveblocks` and `event` (see "Setup" section)// ...
if (isThreadNotificationEvent(event)) { const emailData = await prepareThreadNotificationEmailAsHtml( liveblocks, event ); let email;
switch (emailData.type) { case "unreadMention": { email = ` <div> <div> @${emailData.comment.author.id} at ${emailData.comment.createdAt} </div> <div>${emailData.comment.htmlBody}</div> </div> `; break; }
case "unreadReplies": { email = ` <div> ${emailData.comments .map( (comment) => ` <div> <div> @${comment.author.id} at ${comment.createdAt} </div> <div>${comment.htmlBody}</div> </div> ` ) .join("")} </div> `; break; } }}
// Send your email// ...

It’s designed to be used in a webhook event, which requires a Liveblocks Node.js client, a WebhookHandler. Check for the correct webhook event using isThreadNotificationEvent before running the function, such as in this Next.js route handler.

Returns
  • valueThreadNotificationEmailDataAsHtml | null

    Returns comment information, and a formatted HTML body, ready for use in emails. Returns null if there are no unread mentions or comments. The result has two formats depending on whether this notification is for a single unread mention, or for multiple unread replies:

Arguments
  • clientLiveblocksRequired

    A Liveblocks Node.js client.

  • eventThreadNotificationEventRequired

    An object passed from a webhook event, specifically the ThreadNotificationEvent. Learn more about setting this up.

  • optionsobject

    A number of options to customize the format of the comments, adding user info, room info, and styles.

  • options.resolveUsers

    A function that resolves user information in Comments. Return an array of UserMeta["info"] objects in the same order they arrived. Works similarly to the resolver on the client. Learn more.

  • options.resolveRoomInfo

    A function that resolves room information. Return a RoomInfo object, as matching your types. Works similarly to the resolver on the client but for one room. Learn more.

  • options.stylesobject

    Pass CSS properties to style the different HTML elements in the comment bodies. Five elements can be styled: container, paragraph, text, link, mention. Learn more.

  • options.styles.containerCSSProperties

    Inline styles to apply to the comment body container.

  • options.styles.paragraphCSSProperties

    Inline styles to apply to the paragraph block.

  • options.styles.textCSSProperties

    Inline styles to apply to the text element.

  • options.styles.linkCSSProperties

    Inline styles to apply to the link element.

  • options.styles.mentionCSSProperties

    Inline styles to apply to the mention element.

Resolving data

Similarly to on the client, you can resolve users and room info, making it easier to render your emails. For example, you can resolve a user’s ID into their name, and show their name in the email.

const emailData = await prepareThreadNotificationEmailAsHtml(  liveblocks,  webhookEvent,  {    resolveUsers: async ({ userIds }) => {      const usersData = await (userIds);
return usersData.map((userData) => ({ name: userData.name, // "Nimesh" avatar: userData.avatar.src, // "https://..." })); }, resolveRoomInfo({ roomId }) { return { name: roomId, // "my-room-name" url: `https://example.com/${roomId}`, }; }, });
// { type: "unreadMention", comment: { ... }, ... }console.log(emailData);
// { name: "Nimesh", avatar: "https://..." }console.log(emailData.comment.author.info);
// { name: "my-room-name", url: "https://example.com/my-room-name" }console.log(emailData.roomInfo);

Styling elements

Each element in the comment body can be styled with custom CSS properties, if you would like to change the appearance. Five elements are available: container, paragraph, text, link, mention.

const emailData = await prepareThreadNotificationEmailAsHtml(  liveblocks,  webhookEvent,  {    styles: {      paragraph: { margin: "12px 0" },
mention: { fontWeight: "bold", color: "red", },
link: { textDecoration: "underline", }, }, });
// { type: "unreadMention", comment: { ... }, ... }console.log(emailData);
// The elements in the comment body are now styledconsole.log(emailData.comment.htmlBody);

We use cookies to collect data to improve your experience on our site. Read our Privacy Policy to learn more.