Skip to content

Commit a1271fa

Browse files
committed
Squashed commit of the following:
commit 1f5874d Author: D-K-P <[email protected]> Date: Tue Apr 15 15:28:59 2025 +0100 Updated readme commit 0921b5d Author: D-K-P <[email protected]> Date: Tue Apr 15 14:56:07 2025 +0100 Updated readme and renamed project commit 72df27b Author: D-K-P <[email protected]> Date: Mon Apr 14 16:47:20 2025 +0100 Loop now working commit be79607 Author: D-K-P <[email protected]> Date: Mon Apr 14 11:34:30 2025 +0100 improved the meme gen commit fc6d745 Author: D-K-P <[email protected]> Date: Fri Apr 11 17:01:13 2025 +0100 wip
1 parent f321652 commit a1271fa

22 files changed

+9125
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Generate an API key at https://platform.openai.com/api-keys
2+
OPENAI_API_KEY="<your-openai-api-key>"
3+
# Find this in your Trigger.dev dashboard
4+
TRIGGER_SECRET_KEY="<your-trigger-secret-key>"
5+
# Create a Slack app and get the webhook URL from the app's settings. https://api.slack.com/quickstart
6+
SLACK_WEBHOOK_URL="<your-slack-incoming-webhook-url>" # Required for Slack notifications
7+
# This is the URL of your Next.js app. For local development, it's http://localhost:3000, for production, it's your app's public URL
8+
NEXT_PUBLIC_APP_URL="<your-app-url>" # Required for the approval endpoint
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
.env
34+
35+
# vercel
36+
.vercel
37+
38+
# typescript
39+
*.tsbuildinfo
40+
next-env.d.ts
41+
42+
.trigger
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Meme generator with human-in-the-loop approval
2+
3+
> **ℹ️ Note:** This is a v4 project. If you are using v3 and want to upgrade, please refer to our [v4 upgrade guide](https://trigger.dev/docs/v4-upgrade-guide).
4+
5+
This example reference project demonstrates using a human-in-the-loop workflow to approve memes generated using OpenAI's DALL-E 3.
6+
7+
![Meme Generator with Human-in-the-Loop Approval](/public/meme-image.png)
8+
9+
## Features
10+
11+
- A [Next.js](https://nextjs.org/) app, with an [endpoint](src/app/endpoints/[slug]/page.tsx) for approving the generated memes
12+
- [Trigger.dev](https://trigger.dev) tasks to generate the images and orchestrate the waitpoint workflow
13+
- [OpenAI DALL-E 3](https://platform.openai.com/docs/guides/images) for generating the images
14+
- A [Slack app](https://api.slack.com/quickstart) for the human-in-the-loop step, with the approval buttons linked to the endpoint
15+
16+
## Getting started
17+
18+
1. After cloning the repo, run `npm install` to install the dependencies.
19+
2. Copy the `.env.example` file to `.env` and fill in the required environment variables:
20+
- You'll need an OpenAI API key for DALL-E 3. Create a free account at [OpenAI](https://platform.openai.com/signup).
21+
- Sign up for a free Trigger.dev account [here](https://cloud.trigger.dev/login) and create a new project.
22+
- Create a Slack incoming webhook URL for notifications. You will need to create and install your own [Slack app](https://api.slack.com/quickstart) to a specific channel in your workspace. Make sure the app has the relevant permissions to send messages to the channel, the incoming webhook URL details can be found in the Slack app settings.
23+
- Set your app's public URL for approval callbacks.
24+
3. Copy the project ref from the Trigger.dev dashboard and add it to the `trigger.config.ts` file.
25+
4. Run the Next.js server with `npm run dev`.
26+
5. In a separate terminal, run the Trigger.dev dev CLI command with `npx trigger@v4-beta dev` (it may ask you to authorize the CLI if you haven't already).
27+
6. To test your workflow, go to the [Trigger.dev dashboard](https://cloud.trigger.dev/dashboard) test page and trigger the workflow.
28+
29+
Example payload:
30+
31+
```json
32+
{
33+
"prompt": "A meme with a cat and a dog"
34+
}
35+
```
36+
37+
## Relevant code
38+
39+
- **Meme generator task**: View the Trigger.dev task code in the [src/trigger/memegenerator.ts](src/trigger/memegenerator.ts) file, which:
40+
41+
- Generates two meme variants using DALL-E 3
42+
- Uses [batchTriggerAndWait](https://trigger.dev/docs/triggering#yourtask-batchtriggerandwait) to generate multiple meme variants simultaneously (this is because you can only generate 1 image at a time with DALL-E 3)
43+
- Creates a [waitpoint](https://trigger.dev/docs/upgrade-to-v4) token for human approval
44+
- Sends the generated images with approval buttons to Slack for review
45+
- Handles the approval workflow
46+
47+
- **Approval Endpoint**: The waitpoint approval handling is in [src/app/endpoints/[slug]/page.tsx](src/app/endpoints/[slug]/page.tsx), which processes:
48+
- User selections from Slack buttons
49+
- Waitpoint completion with the chosen meme variant
50+
- Success/failure feedback to the approver
51+
52+
## Learn More
53+
54+
To learn more about the technologies used in this project, check out the following resources:
55+
56+
- [Trigger.dev Documentation](https://trigger.dev/docs) - learn about Trigger.dev and its features
57+
- [Trigger.dev wait tokens](https://trigger.dev/docs/upgrade-to-v4) - learn about using wait points in workflows
58+
- [OpenAI DALL-E API](https://platform.openai.com/docs/guides/images) - learn about the DALL-E image generation API
59+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API
60+
- [Slack Incoming Webhooks](https://api.slack.com/messaging/webhooks) - learn about integrating with Slack
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { dirname } from "path";
2+
import { fileURLToPath } from "url";
3+
import { FlatCompat } from "@eslint/eslintrc";
4+
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = dirname(__filename);
7+
8+
const compat = new FlatCompat({
9+
baseDirectory: __dirname,
10+
});
11+
12+
const eslintConfig = [
13+
...compat.extends("next/core-web-vitals", "next/typescript"),
14+
];
15+
16+
export default eslintConfig;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { NextConfig } from "next";
2+
3+
const nextConfig: NextConfig = {
4+
/* config options here */
5+
};
6+
7+
export default nextConfig;

0 commit comments

Comments
 (0)