Skip to content

Commit ddcd171

Browse files
committed
Added nano banana task
1 parent 3188dc9 commit ddcd171

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
title: "Image-to-image generation using Replicate and nano-banana"
3+
sidebarTitle: "Nano banana image-to-image"
4+
description: "Learn how to generate images from source image URLs using Replicate and Trigger.dev."
5+
---
6+
7+
## Overview
8+
9+
This example demonstrates how to use Trigger.dev to generate images from source image URLs using [Replicate](https://replicate.com/), the [nano-banana-image-to-image](https://replicate.com/meta/nano-banana-image-to-image) model.
10+
11+
## Task code
12+
13+
```tsx trigger/generateImage.tsx
14+
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
15+
import { task, wait } from "@trigger.dev/sdk";
16+
import Replicate, { Prediction } from "replicate";
17+
18+
// Initialize clients
19+
const replicate = new Replicate({
20+
auth: process.env.REPLICATE_API_TOKEN,
21+
});
22+
23+
const s3Client = new S3Client({
24+
region: "auto",
25+
endpoint: process.env.R2_ENDPOINT,
26+
credentials: {
27+
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
28+
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
29+
},
30+
});
31+
32+
const model = "google/nano-banana";
33+
34+
export const generateImageAndUploadToR2 = task({
35+
id: "generate-image-and-upload-to-r2",
36+
run: async (payload: { prompt: string; imageUrl: string }) => {
37+
const { prompt, imageUrl } = payload;
38+
39+
const token = await wait.createToken({
40+
timeout: "10m",
41+
});
42+
43+
// Use Flux with structured prompt
44+
const output = await replicate.predictions.create({
45+
model: model,
46+
input: { prompt, image_input: [imageUrl] },
47+
// pass the provided URL to Replicate's webhook, so they can "callback"
48+
webhook: token.url,
49+
webhook_events_filter: ["completed"],
50+
});
51+
52+
const result = await wait.forToken<Prediction>(token);
53+
// unwrap() throws a timeout error or returns the result 👆
54+
55+
if (!result.ok) {
56+
throw new Error("Failed to create prediction");
57+
}
58+
59+
const generatedImageUrl = result.output.output;
60+
61+
const image = await fetch(generatedImageUrl);
62+
const imageBuffer = Buffer.from(await image.arrayBuffer());
63+
64+
const base64Image = Buffer.from(imageBuffer).toString("base64");
65+
66+
const timestamp = Date.now();
67+
const filename = `generated-${timestamp}.png`;
68+
69+
// Generate unique key for R2
70+
const sanitizedFileName = filename.replace(/[^a-zA-Z0-9.-]/g, "_");
71+
const r2Key = `uploaded-images/${timestamp}-${sanitizedFileName}`;
72+
73+
const uploadParams = {
74+
Bucket: process.env.R2_BUCKET,
75+
Key: r2Key,
76+
Body: imageBuffer,
77+
ContentType: "image/png",
78+
// Add cache control for better performance
79+
CacheControl: "public, max-age=31536000", // 1 year
80+
};
81+
82+
const uploadResult = await s3Client.send(new PutObjectCommand(uploadParams));
83+
84+
// Construct the public URL using the R2_PUBLIC_URL env var
85+
const publicUrl = `${process.env.R2_PUBLIC_URL}/${r2Key}`;
86+
87+
return {
88+
success: true,
89+
publicUrl,
90+
originalPrompt: prompt,
91+
sourceImageUrl: imageUrl,
92+
};
93+
},
94+
});
95+
```
96+
97+
## Environment variables
98+
99+
You will need to set the following environment variables:
100+
101+
```
102+
TRIGGER_SECRET_KEY=<your-trigger-secret-key>
103+
REPLICATE_API_TOKEN=<your-replicate-api-token>
104+
R2_ENDPOINT=<your-r2-endpoint>
105+
R2_ACCESS_KEY_ID=<your-r2-access-key-id>
106+
R2_SECRET_ACCESS_KEY=<your-r2-secret-access-key>
107+
R2_BUCKET=<your-r2-bucket>
108+
R2_PUBLIC_URL=<your-r2-public-url>
109+
```
110+
111+
## Learn more
112+
113+
### React Email docs
114+
115+
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.
116+
117+
<CardGroup cols={2}>
118+
<Card title="Components" icon="puzzle-piece" href="https://react.email/components">
119+
Pre-built components you can copy and paste into your emails.
120+
</Card>
121+
<Card title="Templates" icon="rectangle-list" href="https://react.email/templates">
122+
Extensive pre-built templates ready to use.
123+
</Card>
124+
</CardGroup>

0 commit comments

Comments
 (0)