Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"guides/example-projects/mastra-agents-with-memory",
"guides/example-projects/meme-generator-human-in-the-loop",
"guides/example-projects/openai-agents-sdk-typescript-playground",
"guides/example-projects/product-image-generator",
"guides/example-projects/realtime-csv-importer",
"guides/example-projects/realtime-fal-ai",
"guides/example-projects/turborepo-monorepo-prisma",
Expand Down Expand Up @@ -376,6 +377,7 @@
"guides/examples/puppeteer",
"guides/examples/react-pdf",
"guides/examples/react-email",
"guides/examples/replicate-image-generation",
"guides/examples/resend-email-sequence",
"guides/examples/satori",
"guides/examples/scrape-hacker-news",
Expand Down
61 changes: 61 additions & 0 deletions docs/guides/example-projects/product-image-generator.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: "Product image generator using Replicate and Trigger.dev"
sidebarTitle: "Product image generator"
description: "AI-powered product image generator that transforms basic product photos into professional marketing shots using Replicate's image generation models"
---

## Overview

This project demonstrates how to build an AI-powered product image generator that transforms basic product photos into professional marketing shots. Users upload a product image and receive three professionally styled variations: clean product shots, lifestyle scenes, and hero shots with dramatic lighting.

## Video

<video
controls
className="w-full aspect-video"
src="https://content.trigger.dev/product-image-generator-example.mp4"
/>

## GitHub repo

Clone this repo and follow the instructions in the `README.md` file to get started.

<Card
title="View the product image generator repo"
icon="GitHub"
href="https://github.com/triggerdotdev/examples/tree/main/product-image-generator"
>
Click here to view the full code in our examples repository on GitHub. You can fork it and use it
as a starting point for your project.
</Card>

## Tech stack

- [**Next.js**](https://nextjs.org/) – frontend React framework
- [**Replicate**](https://replicate.com/docs) – AI image generation using the `google/nano-banana` image-to-image model
- [**UploadThing**](https://uploadthing.com/) – file upload management and server callbacks
- [**Cloudflare R2**](https://developers.cloudflare.com/r2/) – scalable image storage with public URLs

## How it works

The application orchestrates image generation through two main tasks: [`generateImages`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/trigger/generate-images.ts) coordinates batch processing, while [`generateImage`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/trigger/generate-images.ts) handles individual style generation.

Each generation task enhances prompts with style-specific instructions, calls Replicate's `google/nano-banana` image-to-image model, creates waitpoint tokens for async webhook handling, and uploads results to Cloudflare R2. The frontend displays real-time progress updates via React hooks as tasks complete.

Style presets include clean product shots (white background), lifestyle scenes (person holding product), and hero shots (dramatic lighting).

## Relevant code

- **Image generation tasks** – batch processing with waitpoints for Replicate webhook callbacks ([`app/trigger/generate-images.ts`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/trigger/generate-images.ts))
- **Upload handler** – UploadThing integration that triggers batch generation ([`app/api/uploadthing/core.ts`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/api/uploadthing/core.ts))
- **Real-time progress UI** – live task updates using React hooks ([`app/components/GeneratedCard.tsx`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/components/GeneratedCard.tsx))
- **Custom prompt interface** – user-defined style generation ([`app/components/CustomPromptCard.tsx`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/components/CustomPromptCard.tsx))
- **Main app component** – layout and state management ([`app/ProductImageGenerator.tsx`](https://github.com/triggerdotdev/examples/blob/main/product-image-generator/app/ProductImageGenerator.tsx))

## Learn more

- [**Waitpoints**](/wait-for-token) – pause tasks for async webhook callbacks
- [**React hooks**](/realtime/react-hooks/overview) – real-time task updates and frontend integration
- [**Batch operations**](/triggering#tasks-batchtrigger) – parallel task execution patterns
- [**Replicate API**](https://replicate.com/docs/get-started/nextjs) – AI model integration
- [**UploadThing**](https://docs.uploadthing.com/) – file upload handling and server callbacks
124 changes: 124 additions & 0 deletions docs/guides/examples/replicate-image-generation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
title: "Image-to-image generation using Replicate and nano-banana"
sidebarTitle: "Replicate image generation"
description: "Learn how to generate images from source image URLs using Replicate and Trigger.dev."
---

## Overview

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.

## Task code

```tsx trigger/generateImage.tsx
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { task, wait } from "@trigger.dev/sdk";
import Replicate, { Prediction } from "replicate";

// Initialize clients
const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN,
});

const s3Client = new S3Client({
region: "auto",
endpoint: process.env.R2_ENDPOINT,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
},
});

const model = "google/nano-banana";

export const generateImageAndUploadToR2 = task({
id: "generate-image-and-upload-to-r2",
run: async (payload: { prompt: string; imageUrl: string }) => {
const { prompt, imageUrl } = payload;

const token = await wait.createToken({
timeout: "10m",
});

// Use Flux with structured prompt
const output = await replicate.predictions.create({
model: model,
input: { prompt, image_input: [imageUrl] },
// pass the provided URL to Replicate's webhook, so they can "callback"
webhook: token.url,
webhook_events_filter: ["completed"],
});

const result = await wait.forToken<Prediction>(token);
// unwrap() throws a timeout error or returns the result 👆

if (!result.ok) {
throw new Error("Failed to create prediction");
}

const generatedImageUrl = result.output.output;

const image = await fetch(generatedImageUrl);
const imageBuffer = Buffer.from(await image.arrayBuffer());

const base64Image = Buffer.from(imageBuffer).toString("base64");

const timestamp = Date.now();
const filename = `generated-${timestamp}.png`;

// Generate unique key for R2
const sanitizedFileName = filename.replace(/[^a-zA-Z0-9.-]/g, "_");
const r2Key = `uploaded-images/${timestamp}-${sanitizedFileName}`;

const uploadParams = {
Bucket: process.env.R2_BUCKET,
Key: r2Key,
Body: imageBuffer,
ContentType: "image/png",
// Add cache control for better performance
CacheControl: "public, max-age=31536000", // 1 year
};

const uploadResult = await s3Client.send(new PutObjectCommand(uploadParams));

// Construct the public URL using the R2_PUBLIC_URL env var
const publicUrl = `${process.env.R2_PUBLIC_URL}/${r2Key}`;

return {
success: true,
publicUrl,
originalPrompt: prompt,
sourceImageUrl: imageUrl,
};
},
});
```

## Environment variables

You will need to set the following environment variables:

```
TRIGGER_SECRET_KEY=<your-trigger-secret-key>
REPLICATE_API_TOKEN=<your-replicate-api-token>
R2_ENDPOINT=<your-r2-endpoint>
R2_ACCESS_KEY_ID=<your-r2-access-key-id>
R2_SECRET_ACCESS_KEY=<your-r2-secret-access-key>
R2_BUCKET=<your-r2-bucket>
R2_PUBLIC_URL=<your-r2-public-url>
```

## 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>
2 changes: 2 additions & 0 deletions docs/guides/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Example projects are full projects with example repos you can fork and use. Thes
| [Mastra agents with memory](/guides/example-projects/mastra-agents-with-memory) | Use Mastra to create a weather agent that can collect live weather data and generate clothing recommendations. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/mastra-agents) |
| [OpenAI Agents SDK for Python guardrails](/guides/example-projects/openai-agent-sdk-guardrails) | Use the OpenAI Agents SDK for Python to create a guardrails system for your AI agents. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/openai-agent-sdk-guardrails-examples) |
| [OpenAI Agents SDK for TypeScript playground](/guides/example-projects/openai-agents-sdk-typescript-playground) | A playground containing 7 AI agents using the OpenAI Agents SDK for TypeScript with Trigger.dev. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/openai-agents-sdk-with-trigger-playground) |
| [Product image generator](/guides/example-projects/product-image-generator) | Transform basic product photos into professional marketing shots using Replicate's image generation models. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/product-image-generator) |
| [Python web crawler](/guides/python/python-crawl4ai) | Use Python, Crawl4AI and Playwright to create a headless web crawler with Trigger.dev. | — | [View the repo](https://github.com/triggerdotdev/examples/tree/main/python-crawl4ai) |
| [Realtime CSV Importer](/guides/example-projects/realtime-csv-importer) | Upload a CSV file and see the progress of the task streamed to the frontend. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/realtime-csv-importer) |
| [Realtime Fal.ai image generation](/guides/example-projects/realtime-fal-ai) | Generate an image from a prompt using Fal.ai and show the progress of the task on the frontend using Realtime. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/realtime-fal-ai-image-generation) |
Expand Down Expand Up @@ -79,6 +80,7 @@ Task code you can copy and paste to use in your project. They can all be extende
| [React email](/guides/examples/react-email) | Send an email using React Email. |
| [React to PDF](/guides/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. |
| [Resend email sequence](/guides/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. |
| [Replicate image generation](/guides/examples/replicate-image-generation) | Learn how to generate images from source image URLs using Replicate and Trigger.dev. |
| [Satori](/guides/examples/satori) | Generate OG images using React Satori. |
| [Scrape Hacker News](/guides/examples/scrape-hacker-news) | Scrape Hacker News using BrowserBase and Puppeteer, summarize the articles with ChatGPT and send an email of the summary every weekday using Resend. |
| [Sentry error tracking](/guides/examples/sentry-error-tracking) | Automatically send errors to Sentry from your tasks. |
Expand Down