Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
109 changes: 109 additions & 0 deletions docs/guides/examples/replicate-image-generation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
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();
// 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>
```
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