Added satori and improved react email (#1877)

* Improved the react email docs and added a video

* Copy

* Added a link to the cursor rules

* Added satori example

* Copy updates

* Added react pdf link
This commit is contained in:
Dan
2025-04-03 16:42:54 +01:00
committed by GitHub
parent 18ad897171
commit 179a9c95c7
7 changed files with 326 additions and 7 deletions
+4 -3
View File
@@ -332,14 +332,15 @@
"guides/examples/open-ai-with-retrying",
"guides/examples/pdf-to-image",
"guides/examples/puppeteer",
"guides/examples/react-pdf",
"guides/examples/react-email",
"guides/examples/resend-email-sequence",
"guides/examples/satori",
"guides/examples/scrape-hacker-news",
"guides/examples/sentry-error-tracking",
"guides/examples/sharp-image-processing",
"guides/examples/supabase-database-operations",
"guides/examples/supabase-storage-upload",
"guides/examples/react-pdf",
"guides/examples/react-email",
"guides/examples/resend-email-sequence",
"guides/examples/vercel-ai-sdk",
"guides/examples/vercel-sync-env-vars"
]
+184 -3
View File
@@ -6,11 +6,11 @@ description: "Learn how to send beautiful emails using React Email and Trigger.d
## Overview
This example demonstrates how to use Trigger.dev to send emails using React Email.
This example demonstrates how to use Trigger.dev to send emails using [React Email](https://react.email/).
<Note>
This example uses [Resend](https://resend.com) as the email provider. You can use other email
providers like [SendGrid](https://sendgrid.com) or [Loops](https://loops.so) as well. Full list of
providers like [Loops](https://loops.so) or [SendGrid](https://sendgrid.com) etc. Full list of
their integrations can be found [here](https://react.email/docs/introduction#integrations).
</Note>
@@ -98,7 +98,7 @@ export const sendEmail = task({
});
```
## How the email should look
## The email
This example email should look like this:
![React Email](/images/react-email.png)
@@ -121,3 +121,184 @@ To test this task in the [dashboard](https://cloud.trigger.dev), you can use the
## Deploying your task
Deploy the task to production using the Trigger.dev CLI `deploy` command.
## Using Cursor / AI to build your emails
In this video you can see how we use Cursor to build a welcome email.
We recommend using our [Cursor rules](https://trigger.dev/changelog/cursor-rules-writing-tasks/) to help you build your tasks and emails.
#### Video: creating a new email template using Cursor
<video
src="https://content.trigger.dev/trigger-welcome-email-cursor.mp4"
controls
muted
autoPlay
loop
/>
#### The generated email template
![Cursor](/images/react-email-welcome.png)
#### The generated code
```tsx trigger/welcome.tsx
import {
Body,
Button,reac
Container,
Head,
Hr,
Html,
Img,
Link,
Preview,
Section,
Text,
} from "@react-email/components";
const baseUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "";
export const TriggerDevWelcomeEmail = () => (
<Html>
<Head />
<Preview>Welcome to Trigger.dev - Your background jobs platform!</Preview>
<Body style={main}>
<Container style={container}>
<Section style={box}>
<Img
src="https://trigger.dev/assets/triggerdev-lockup--light.svg"
width="150"
height="40"
alt="Trigger.dev"
/>
<Hr style={hr} />
<Text style={paragraph}>
Thanks for signing up for Trigger.dev! You're now ready to start
creating powerful background jobs and workflows.
</Text>
<Text style={paragraph}>
You can monitor your jobs, view runs, and manage your projects right
from your dashboard.
</Text>
<Button style={button} href="https://cloud.trigger.dev/dashboard">
View your Trigger.dev Dashboard
</Button>
<Hr style={hr} />
<Text style={paragraph}>
To help you get started, check out our{" "}
<Link style={anchor} href="https://trigger.dev/docs">
documentation
</Link>{" "}
and{" "}
<Link style={anchor} href="https://trigger.dev/docs/quickstart">
quickstart guide
</Link>
.
</Text>
<Text style={paragraph}>
You can create your first job using our SDK, set up integrations,
and configure triggers to automate your workflows. Take a look at
our{" "}
<Link style={anchor} href="https://trigger.dev/docs/examples">
examples
</Link>{" "}
for inspiration.
</Text>
<Text style={paragraph}>
Join our{" "}
<Link style={anchor} href="https://discord.gg/kA47vcd8Qr">
Discord community
</Link>{" "}
to connect with other developers and get help when you need it.
</Text>
<Text style={paragraph}>
We're here to help you build amazing things. If you have any
questions, check out our{" "}
<Link style={anchor} href="https://trigger.dev/docs">
documentation
</Link>{" "}
or reach out to us on Discord.
</Text>
<Text style={paragraph}>— The Trigger.dev team</Text>
<Hr style={hr} />
<Text style={footer}>Trigger.dev Inc.</Text>
</Section>
</Container>
</Body>
</Html>
);
export default TriggerDevWelcomeEmail;
const main = {
backgroundColor: "#0E0C15",
fontFamily:
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
};
const container = {
backgroundColor: "#1D1B27",
margin: "0 auto",
padding: "20px 0 48px",
marginBottom: "64px",
};
const box = {
padding: "0 48px",
};
const hr = {
borderColor: "#2D2B3B",
margin: "20px 0",
};
const paragraph = {
color: "#E1E1E3",
fontSize: "16px",
lineHeight: "24px",
textAlign: "left" as const,
};
const anchor = {
color: "#A78BFA",
};
const button = {
backgroundColor: "#7C3AED",
borderRadius: "6px",
color: "#fff",
fontSize: "16px",
fontWeight: "bold",
textDecoration: "none",
textAlign: "center" as const,
display: "block",
width: "100%",
padding: "12px",
};
const footer = {
color: "#9CA3AF",
fontSize: "12px",
lineHeight: "16px",
};
```
## Learn more
### React Email docs
Check out the [React Email docs](https://react.email/docs) and learn how to set up and use React Email, including how to preview your emails locally.
<CardGroup cols={2}>
<Card title="Components" icon="puzzle-piece" href="https://react.email/components">
Pre-built components you can copy and paste into your emails.
</Card>
<Card title="Templates" icon="rectangle-list" href="https://react.email/templates">
Extensive pre-built templates ready to use.
</Card>
</CardGroup>
+1 -1
View File
@@ -6,7 +6,7 @@ description: "This example will show you how to generate a PDF using Trigger.dev
## Overview
This example demonstrates how to use Trigger.dev to generate a PDF using `react-pdf` and save it to Cloudflare R2.
This example demonstrates how to use Trigger.dev to generate a PDF using [react-pdf](https://react-pdf.org/) and save it to Cloudflare R2.
## Task code
+133
View File
@@ -0,0 +1,133 @@
---
title: "Generate OG Images using Satori"
sidebarTitle: "Satori OG Images"
description: "Learn how to generate dynamic Open Graph images using Satori and Trigger.dev."
---
## Overview
This example demonstrates how to use Trigger.dev to generate dynamic Open Graph (OG) images using Vercel's [Satori](https://github.com/vercel/satori). The task takes a title and image URL as input and generates a beautiful OG image with text overlay.
This can be customized and extended however you like, full list of options can be found [here](https://github.com/vercel/satori).
## Task code
```tsx trigger/generateOgImage.ts
import { schemaTask } from "@trigger.dev/sdk/v3";
import { z } from "zod";
import satori from "satori";
import sharp from "sharp";
import { join } from "path";
import fs from "fs/promises";
export const generateOgImage = schemaTask({
id: "generate-og-image",
schema: z.object({
width: z.number().optional(),
height: z.number().optional(),
title: z.string(),
imageUrl: z.string().url(),
}),
run: async (payload) => {
// Load font
const fontResponse = await fetch(
"https://github.com/googlefonts/roboto/raw/main/src/hinted/Roboto-Regular.ttf"
).then((res) => res.arrayBuffer());
// Fetch and convert image to base64
const imageResponse = await fetch(payload.imageUrl);
const imageBuffer = await imageResponse.arrayBuffer();
const imageBase64 = `data:${
imageResponse.headers.get("content-type") || "image/jpeg"
};base64,${Buffer.from(imageBuffer).toString("base64")}`;
const markup = (
<div
style={{
width: payload.width ?? 1200,
height: payload.height ?? 630,
display: "flex",
backgroundColor: "#121317",
position: "relative",
fontFamily: "Roboto",
}}
>
<img
src={imageBase64}
width={payload.width ?? 1200}
height={payload.height ?? 630}
style={{
objectFit: "cover",
}}
/>
<h1
style={{
fontSize: "60px",
fontWeight: "bold",
color: "#fff",
margin: 0,
position: "absolute",
top: "50%",
transform: "translateY(-50%)",
left: "48px",
maxWidth: "60%",
textShadow: "0 2px 4px rgba(0,0,0,0.5)",
}}
>
{payload.title}
</h1>
</div>
);
const svg = await satori(markup, {
width: payload.width ?? 1200,
height: payload.height ?? 630,
fonts: [
{
name: "Roboto",
data: fontResponse,
weight: 400,
style: "normal",
},
],
});
const fileName = `og-${Date.now()}.jpg`;
const tempDir = join(process.cwd(), "tmp");
await fs.mkdir(tempDir, { recursive: true });
const outputPath = join(tempDir, fileName);
await sharp(Buffer.from(svg))
.jpeg({
quality: 90,
mozjpeg: true,
})
.toFile(outputPath);
return {
filePath: outputPath,
width: payload.width,
height: payload.height,
};
},
});
```
## Image example
This image was generated using the above task.
![OG Image](/images/react-satori-og.jpg)
## Testing your task
To test this task in the [dashboard](https://cloud.trigger.dev), you can use the following payload:
```json
{
"title": "My Awesome OG image",
"imageUrl": "<your-image-url>",
"width": 1200, // optional, defaults to 1200
"height": 630 // optional, defaults to 630
}
```
+4
View File
@@ -77,6 +77,10 @@ Task code you can copy and paste to use in your project. They can all be extende
| [Vercel AI SDK](/guides/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. |
| [Vercel sync environment variables](/guides/examples/vercel-sync-env-vars) | Automatically sync environment variables from your Vercel projects to Trigger.dev. |
## Cursor rules
If you use Cursor, we have a set of Cursor rules which will help you build your tasks. You can find our installation guide [here](https://trigger.dev/changelog/cursor-rules-writing-tasks/).
<Note>
If you would like to see a guide for your framework, or an example task for your use case, please
request it in our [Discord server](https://trigger.dev/discord) and we'll add it to the list.
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB