Example tasks
Process images using Sharp
This example demonstrates how to process images using the Sharp library with Trigger.dev.
Overview
This task optimizes and watermarks an image using the Sharp library, and then uploads the processed image to R2 storage.
Adding build configurations
To use this example, you’ll first need to add these build settings to your trigger.config.ts
file:
trigger.config.ts
import { defineConfig } from "@trigger.dev/sdk/v3";
export default defineConfig({
project: "<project ref>",
// Your other config settings...
build: {
// This is required to use the Sharp library
external: ["sharp"],
},
});
Any packages that install or build a native binary should be added to external, as native binaries cannot be bundled.
Key features
- Resizes and rotates an image
- Adds a watermark to the image
- Uploads the processed image to R2 storage
Task code
trigger/sharp-image-processing.ts
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { logger, task } from "@trigger.dev/sdk/v3";
import fs from "fs/promises";
import fetch from "node-fetch";
import os from "os";
import path from "path";
import sharp from "sharp";
// Initialize R2 client
const r2Client = new S3Client({
region: "auto",
endpoint: process.env.R2_ENDPOINT,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
},
});
export const sharpProcessImage = task({
id: "sharp-process-image",
run: async (payload: { imageUrl: string; watermarkUrl: string }) => {
const { imageUrl, watermarkUrl } = payload;
// Generate temporary and output file names
const tempDirectory = os.tmpdir();
const outputPath = path.join(tempDirectory, `output_${Date.now()}.jpg`);
// Fetch the image and watermark
const [imageResponse, watermarkResponse] = await Promise.all([
fetch(imageUrl),
fetch(watermarkUrl),
]);
const imageBuffer = await imageResponse.arrayBuffer();
const watermarkBuffer = await watermarkResponse.arrayBuffer();
// Optimize the image using Sharp
await sharp(Buffer.from(imageBuffer))
.rotate(90) // Rotate the image by 90 degrees
.resize(800, 600) // Resize the image to 800x600
.composite([
{
input: Buffer.from(watermarkBuffer),
gravity: "southeast", // Position the watermark in the bottom-right corner
},
])
.toFormat("jpeg")
.toFile(outputPath);
// Log the output file path
logger.log(`Optimized image saved at: ${outputPath}`);
// Read the optimized image file
const optimizedImageBuffer = await fs.readFile(outputPath);
// Upload the optimized image to R2, replacing slashes with underscores
const r2Key = `processed-images/${path.basename(outputPath)}`;
const uploadParams = {
Bucket: process.env.R2_BUCKET,
Key: r2Key,
Body: optimizedImageBuffer,
};
// Upload the image to R2 and get the URL
await r2Client.send(new PutObjectCommand(uploadParams));
const r2Url = `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${process.env.R2_BUCKET}/${r2Key}`;
logger.log("Optimized image uploaded to R2", { url: r2Url });
// Delete the temporary file
await fs.unlink(outputPath);
// Return the optimized image buffer, file path, and R2 URL
return {
optimizedImageBuffer,
optimizedImagePath: outputPath,
r2Url,
};
},
});
Testing your task
To test this task in the dashboard, you can use the following payload:
{
"imageUrl": "<an-image-url.jpg>", // Replace with a URL to a JPEG image
"watermarkUrl": "<an-image-url.png>" // Replace with a URL to a PNG watermark image
}
Local development
To test this example task locally, be sure to install any packages from the build extensions you added to your trigger.config.ts
file to your local machine. In this case, you need to install .
Was this page helpful?