diff --git a/docs/docs.json b/docs/docs.json
new file mode 100644
index 0000000000..8649b22cb2
--- /dev/null
+++ b/docs/docs.json
@@ -0,0 +1,484 @@
+{
+ "$schema": "https://mintlify.com/docs.json",
+ "theme": "maple",
+ "name": "Trigger.dev",
+ "description": "Trigger.dev is an open source background jobs framework that lets you write reliable workflows in plain async code. Run long-running AI tasks, handle complex background jobs, and build AI agents with built-in queuing, automatic retries, and real-time monitoring. No timeouts, elastic scaling, and zero infrastructure management required.",
+ "colors": {
+ "primary": "#A8FF53",
+ "light": "#A8FF53",
+ "dark": "#A8FF53"
+ },
+ "favicon": "/images/favicon.png",
+ "navigation": {
+ "dropdowns": [
+ {
+ "dropdown": "Documentation",
+ "description": "Resources for Trigger.dev",
+ "icon": "book-open",
+ "groups": [
+ {
+ "group": "Getting started",
+ "pages": ["introduction", "quick-start", "video-walkthrough", "how-it-works", "limits"]
+ },
+ {
+ "group": "Fundamentals",
+ "pages": [
+ {
+ "group": "Tasks",
+ "pages": ["tasks/overview", "tasks/schemaTask", "tasks/scheduled"]
+ },
+ "triggering",
+ "runs",
+ "apikeys",
+ {
+ "group": "Configuration",
+ "pages": ["config/config-file", "config/extensions/overview"]
+ }
+ ]
+ },
+ {
+ "group": "Development",
+ "pages": ["cli-dev", "run-tests"]
+ },
+ {
+ "group": "Deployment",
+ "pages": [
+ "cli-deploy",
+ "deploy-environment-variables",
+ "github-actions",
+ {
+ "group": "Deployment integrations",
+ "pages": ["vercel-integration"]
+ }
+ ]
+ },
+ {
+ "group": "Writing tasks",
+ "pages": [
+ "writing-tasks-introduction",
+ "logging",
+ "errors-retrying",
+ {
+ "group": "Wait",
+ "pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"]
+ },
+ "queue-concurrency",
+ "versioning",
+ "machines",
+ "idempotency",
+ "replaying",
+ "runs/max-duration",
+ "tags",
+ "runs/metadata",
+ "run-usage",
+ "context",
+ "bulk-actions",
+ "examples"
+ ]
+ },
+ {
+ "group": "Frontend usage",
+ "pages": [
+ "frontend/overview",
+ {
+ "group": "React hooks",
+ "pages": [
+ "frontend/react-hooks/overview",
+ "frontend/react-hooks/realtime",
+ "frontend/react-hooks/triggering"
+ ]
+ }
+ ]
+ },
+ {
+ "group": "Realtime API",
+ "pages": [
+ "realtime/overview",
+ "realtime/streams",
+ "realtime/react-hooks",
+ "realtime/subscribe-to-run",
+ "realtime/subscribe-to-runs-with-tag",
+ "realtime/subscribe-to-batch"
+ ]
+ },
+ {
+ "group": "API reference",
+ "pages": [
+ "management/overview",
+ {
+ "group": "Tasks API",
+ "pages": ["management/tasks/trigger", "management/tasks/batch-trigger"]
+ },
+ {
+ "group": "Runs API",
+ "pages": [
+ "management/runs/list",
+ "management/runs/retrieve",
+ "management/runs/replay",
+ "management/runs/cancel",
+ "management/runs/reschedule",
+ "management/runs/update-metadata"
+ ]
+ },
+ {
+ "group": "Schedules API",
+ "pages": [
+ "management/schedules/list",
+ "management/schedules/create",
+ "management/schedules/retrieve",
+ "management/schedules/update",
+ "management/schedules/delete",
+ "management/schedules/deactivate",
+ "management/schedules/activate",
+ "management/schedules/timezones"
+ ]
+ },
+ {
+ "group": "Env Vars API",
+ "pages": [
+ "management/envvars/list",
+ "management/envvars/import",
+ "management/envvars/create",
+ "management/envvars/retrieve",
+ "management/envvars/update",
+ "management/envvars/delete"
+ ]
+ },
+ {
+ "group": "Projects API",
+ "pages": ["management/projects/runs"]
+ }
+ ]
+ },
+ {
+ "group": "CLI",
+ "pages": [
+ "cli-introduction",
+ {
+ "group": "Commands",
+ "pages": [
+ "cli-login-commands",
+ "cli-init-commands",
+ "cli-dev-commands",
+ "cli-deploy-commands",
+ "cli-whoami-commands",
+ "cli-logout-commands",
+ "cli-list-profiles-commands",
+ "cli-update-commands"
+ ]
+ }
+ ]
+ },
+ {
+ "group": "Open source",
+ "pages": [
+ "open-source-self-hosting",
+ "open-source-contributing",
+ "github-repo",
+ "changelog",
+ "roadmap"
+ ]
+ },
+ {
+ "group": "Troubleshooting",
+ "pages": [
+ "troubleshooting",
+ "upgrading-packages",
+ "upgrading-beta",
+ "troubleshooting-alerts",
+ "troubleshooting-uptime-status",
+ "troubleshooting-github-issues",
+ "request-feature"
+ ]
+ },
+ {
+ "group": "Help",
+ "pages": ["community", "help-slack", "help-email"]
+ }
+ ]
+ },
+ {
+ "dropdown": "Guides & examples",
+ "description": "A great way to get started",
+ "icon": "book",
+ "groups": [
+ {
+ "group": "Introduction",
+ "pages": ["guides/introduction"]
+ },
+ {
+ "group": "Frameworks",
+ "pages": [
+ "guides/frameworks/bun",
+ "guides/frameworks/nextjs",
+ "guides/frameworks/nodejs",
+ "guides/frameworks/remix"
+ ]
+ },
+ {
+ "group": "Guides",
+ "pages": [
+ {
+ "group": "AI Agents",
+ "icon": {
+ "name": "microchip-ai",
+ "style": "regular"
+ },
+ "pages": [
+ "guides/ai-agents/overview",
+ "guides/ai-agents/generate-translate-copy",
+ "guides/ai-agents/route-question",
+ "guides/ai-agents/respond-and-check-content",
+ "guides/ai-agents/verify-news-article",
+ "guides/ai-agents/translate-and-refine"
+ ]
+ },
+ "guides/frameworks/drizzle",
+ "guides/frameworks/prisma",
+ "guides/frameworks/sequin",
+ {
+ "group": "Supabase",
+ "icon": {
+ "name": "bolt",
+ "style": "solid"
+ },
+ "pages": [
+ "guides/frameworks/supabase-guides-overview",
+ "guides/frameworks/supabase-edge-functions-basic",
+ "guides/frameworks/supabase-edge-functions-database-webhooks"
+ ]
+ },
+ {
+ "group": "Webhooks",
+ "icon": {
+ "name": "webhook",
+ "style": "solid"
+ },
+ "pages": [
+ "guides/frameworks/webhooks-guides-overview",
+ "guides/frameworks/nextjs-webhooks",
+ "guides/frameworks/remix-webhooks",
+ "guides/examples/stripe-webhook"
+ ]
+ }
+ ]
+ },
+ {
+ "group": "Example projects",
+ "pages": [
+ "guides/example-projects/realtime-fal-ai",
+ "guides/example-projects/batch-llm-evaluator",
+ "guides/example-projects/realtime-csv-importer",
+ "guides/example-projects/vercel-ai-sdk-image-generator"
+ ]
+ },
+ {
+ "group": "Example tasks",
+ "pages": [
+ "guides/examples/dall-e3-generate-image",
+ "guides/examples/deepgram-transcribe-audio",
+ "guides/examples/fal-ai-image-to-cartoon",
+ "guides/examples/fal-ai-realtime",
+ "guides/examples/ffmpeg-video-processing",
+ "guides/examples/firecrawl-url-crawl",
+ "guides/examples/libreoffice-pdf-conversion",
+ "guides/examples/open-ai-with-retrying",
+ "guides/examples/pdf-to-image",
+ "guides/examples/puppeteer",
+ "guides/examples/scrape-hacker-news",
+ "guides/examples/sentry-error-tracking",
+ "guides/examples/sharp-image-processing",
+ "guides/examples/supabase-database-operations",
+ "guides/examples/supabase-storage-upload",
+ "guides/examples/react-pdf",
+ "guides/examples/resend-email-sequence",
+ "guides/examples/vercel-ai-sdk",
+ "guides/examples/vercel-sync-env-vars"
+ ]
+ },
+ {
+ "group": "Migrations",
+ "pages": ["guides/use-cases/upgrading-from-v2"]
+ }
+ ]
+ }
+ ]
+ },
+ "logo": {
+ "light": "/logo/light.png",
+ "dark": "/logo/dark.png",
+ "href": "https://trigger.dev"
+ },
+ "api": {
+ "openapi": ["openapi.yml", "v3-openapi.yaml"],
+ "playground": {
+ "display": "simple"
+ }
+ },
+ "appearance": {
+ "default": "dark",
+ "strict": true
+ },
+ "background": {
+ "color": {
+ "light": "#fff",
+ "dark": "#121317"
+ }
+ },
+ "navbar": {
+ "primary": {
+ "type": "github",
+ "href": "https://github.com/triggerdotdev/trigger.dev"
+ }
+ },
+ "footer": {
+ "socials": {
+ "x": "https://twitter.com/triggerdotdev",
+ "github": "https://github.com/triggerdotdev",
+ "linkedin": "https://www.linkedin.com/company/triggerdotdev"
+ },
+ "links": [
+ {
+ "header": "Developers",
+ "items": [
+ {
+ "label": "Changelog",
+ "href": "https://trigger.dev/changelog"
+ },
+ {
+ "label": "Contributing",
+ "href": "https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md"
+ },
+ {
+ "label": "Open source",
+ "href": "https://github.com/triggerdotdev/trigger.dev?tab=Apache-2.0-1-ov-file#readme"
+ },
+ {
+ "label": "GitHub",
+ "href": "https://github.com/triggerdotdev/trigger.dev"
+ },
+ {
+ "label": "OSS Friends",
+ "href": "https://trigger.dev/oss-friends"
+ }
+ ]
+ },
+ {
+ "header": "Product",
+ "items": [
+ {
+ "label": "Pricing",
+ "href": "https://trigger.dev/pricing"
+ },
+ {
+ "label": "How it works",
+ "href": "https://trigger.dev/#how-it-works"
+ },
+ {
+ "label": "Features",
+ "href": "https://trigger.dev/product"
+ },
+ {
+ "label": "Roadmap",
+ "href": "https://feedback.trigger.dev/roadmap"
+ },
+ {
+ "label": "FAQs",
+ "href": "https://trigger.dev/pricing#faqs"
+ },
+ {
+ "label": "Uptime status",
+ "href": "https://status.trigger.dev/"
+ }
+ ]
+ },
+ {
+ "header": "Company",
+ "items": [
+ {
+ "label": "Blog",
+ "href": "https://trigger.dev/blog"
+ },
+ {
+ "label": "Contact",
+ "href": "https://trigger.dev/contact"
+ },
+ {
+ "label": "Careers",
+ "href": "https://trigger.dev/jobs"
+ },
+ {
+ "label": "Privacy",
+ "href": "https://trigger.dev/legal/privacy"
+ },
+ {
+ "label": "Terms of service",
+ "href": "https://trigger.dev/legal"
+ }
+ ]
+ }
+ ]
+ },
+ "redirects": [
+ {
+ "source": "/v3/feature-matrix",
+ "destination": "https://feedback.trigger.dev/roadmap"
+ },
+ {
+ "source": "/v3/upgrading-from-v2",
+ "destination": "/guides/use-cases/upgrading-from-v2"
+ },
+ {
+ "source": "/v3/open-source-self-hosting",
+ "destination": "/open-source-self-hosting"
+ },
+ {
+ "source": "/v3/:slug*",
+ "destination": "/:slug*"
+ },
+ {
+ "source": "/reattempting-replaying",
+ "destination": "/replaying"
+ },
+ {
+ "source": "/tasks-overview",
+ "destination": "/tasks/overview"
+ },
+ {
+ "source": "/tasks-scheduled",
+ "destination": "/tasks/scheduled"
+ },
+ {
+ "source": "/trigger-folder",
+ "destination": "/config/config-file"
+ },
+ {
+ "source": "/trigger-config",
+ "destination": "/config/config-file"
+ },
+ {
+ "source": "/guides/frameworks/introduction",
+ "destination": "/guides/introduction"
+ },
+ {
+ "source": "/guides/examples/intro",
+ "destination": "/guides/introduction"
+ },
+ {
+ "source": "/examples/:slug*",
+ "destination": "/guides/examples/:slug*"
+ },
+ {
+ "source": "/realtime",
+ "destination": "/realtime/overview"
+ },
+ {
+ "source": "/runs-and-attempts",
+ "destination": "/runs"
+ },
+ {
+ "source": "/frontend/react-hooks",
+ "destination": "/frontend/react-hooks/overview"
+ }
+ ]
+}
diff --git a/docs/guides/ai-agents/evaluator-optimizer.png b/docs/guides/ai-agents/evaluator-optimizer.png
new file mode 100644
index 0000000000..4ec95643cf
Binary files /dev/null and b/docs/guides/ai-agents/evaluator-optimizer.png differ
diff --git a/docs/guides/ai-agents/generate-translate-copy.mdx b/docs/guides/ai-agents/generate-translate-copy.mdx
new file mode 100644
index 0000000000..127cb028ea
--- /dev/null
+++ b/docs/guides/ai-agents/generate-translate-copy.mdx
@@ -0,0 +1,120 @@
+---
+title: "Generate and translate copy"
+sidebarTitle: "Generate & translate copy"
+description: "Create an AI agent workflow that generates and translates copy"
+---
+
+## Overview
+
+**Prompt chaining** is an AI workflow pattern that decomposes a complex task into a sequence of steps, where each LLM call processes the output of the previous one. This approach trades off latency for higher accuracy by making each LLM call an easier, more focused task, with the ability to add programmatic checks between steps to ensure the process remains on track.
+
+
+
+## Example task
+
+In this example, we'll create a workflow that generates and translates copy. This approach is particularly effective when tasks require different models or approaches for different inputs.
+
+**This task:**
+
+- Uses `generateText` from [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to interact with OpenAI models
+- Uses `experimental_telemetry` to provide LLM logs
+- Generates marketing copy based on subject and target word count
+- Validates the generated copy meets word count requirements (±10 words)
+- Translates the validated copy to the target language while preserving tone
+
+```typescript
+import { openai } from "@ai-sdk/openai";
+import { task } from "@trigger.dev/sdk/v3";
+import { generateText } from "ai";
+
+export interface TranslatePayload {
+ marketingSubject: string;
+ targetLanguage: string;
+ targetWordCount: number;
+}
+
+export const generateAndTranslateTask = task({
+ id: "generate-and-translate-copy",
+ maxDuration: 300, // Stop executing after 5 mins of compute
+ run: async (payload: TranslatePayload) => {
+ // Step 1: Generate marketing copy
+ const generatedCopy = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content: "You are an expert copywriter.",
+ },
+ {
+ role: "user",
+ content: `Generate as close as possible to ${payload.targetWordCount} words of compelling marketing copy for ${payload.marketingSubject}`,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "generate-and-translate-copy",
+ },
+ });
+
+ // Gate: Validate the generated copy meets the word count target
+ const wordCount = generatedCopy.text.split(/\s+/).length;
+
+ if (
+ wordCount < payload.targetWordCount - 10 ||
+ wordCount > payload.targetWordCount + 10
+ ) {
+ throw new Error(
+ `Generated copy length (${wordCount} words) is outside acceptable range of ${
+ payload.targetWordCount - 10
+ }-${payload.targetWordCount + 10} words`
+ );
+ }
+
+ // Step 2: Translate to target language
+ const translatedCopy = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content: `You are an expert translator specializing in marketing content translation into ${payload.targetLanguage}.`,
+ },
+ {
+ role: "user",
+ content: `Translate the following marketing copy to ${payload.targetLanguage}, maintaining the same tone and marketing impact:\n\n${generatedCopy}`,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "generate-and-translate-copy",
+ },
+ });
+
+ return {
+ englishCopy: generatedCopy,
+ translatedCopy,
+ };
+ },
+});
+```
+
+## Run a test
+
+On the Test page in the dashboard, select the `generate-and-translate-copy` task and include a payload like the following:
+
+```json
+{
+ marketingSubject: "The controversial new Jaguar electric concept car",
+ targetLanguage: "Spanish",
+ targetWordCount: 100,
+}
+```
+
+This example payload generates copy and then translates it using sequential LLM calls. The translation only begins after the generated copy has been validated against the word count requirements.
+
+
diff --git a/docs/guides/ai-agents/orchestrator-workers.png b/docs/guides/ai-agents/orchestrator-workers.png
new file mode 100644
index 0000000000..79f037ded8
Binary files /dev/null and b/docs/guides/ai-agents/orchestrator-workers.png differ
diff --git a/docs/guides/ai-agents/overview.mdx b/docs/guides/ai-agents/overview.mdx
new file mode 100644
index 0000000000..de734ccf59
--- /dev/null
+++ b/docs/guides/ai-agents/overview.mdx
@@ -0,0 +1,17 @@
+---
+title: "AI agents overview"
+sidebarTitle: "Overview"
+description: "Real world AI agent example tasks using Trigger.dev"
+---
+
+## Overview
+
+This guide will show you how to set up different types of AI agent workflows with Trigger.dev. The examples take inspiration from Athropic's blog post on [building effective agents](https://www.anthropic.com/research/building-effective-agents).
+
+
+ Chain prompts together to generate and translate marketing copy automatically
+ Send questions to different AI models based on complexity analysis
+ Simultaneously check for inappropriate content while responding to customer inquiries
+ Coordinate multiple AI workers to verify news article accuracy
+ Translate text and automatically improve quality through feedback loops
+
diff --git a/docs/guides/ai-agents/parallelization.png b/docs/guides/ai-agents/parallelization.png
new file mode 100644
index 0000000000..1c4f0bb5ac
Binary files /dev/null and b/docs/guides/ai-agents/parallelization.png differ
diff --git a/docs/guides/ai-agents/prompt-chaining.png b/docs/guides/ai-agents/prompt-chaining.png
new file mode 100644
index 0000000000..95c4cbf623
Binary files /dev/null and b/docs/guides/ai-agents/prompt-chaining.png differ
diff --git a/docs/guides/ai-agents/respond-and-check-content.mdx b/docs/guides/ai-agents/respond-and-check-content.mdx
new file mode 100644
index 0000000000..ca487fa3dd
--- /dev/null
+++ b/docs/guides/ai-agents/respond-and-check-content.mdx
@@ -0,0 +1,134 @@
+---
+title: "Respond to customer inquiry and check for inappropriate content"
+sidebarTitle: "Respond & check content"
+description: "Create an AI agent workflow that responds to customer inquiries while checking if their text is inappropriate"
+---
+
+## Overview
+
+**Parallelization** is a workflow pattern where multiple tasks or processes run simultaneously instead of sequentially, allowing for more efficient use of resources and faster overall execution. It's particularly valuable when different parts of a task can be handled independently, such as running content analysis and response generation at the same time.
+
+
+## Example task
+
+In this example, we'll create a workflow that simultaneously checks content for issues while responding to customer inquiries. This approach is particularly effective when tasks require multiple perspectives or parallel processing streams, with the orchestrator synthesizing the results into a cohesive output.
+
+**This task:**
+
+- Uses `generateText` from [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to interact with OpenAI models
+- Uses `experimental_telemetry` to provide LLM logs
+- Uses [`batch.triggerByTaskAndWait`](/triggering#batch-triggerbytaskandwait) to run customer response and content moderation tasks in parallel
+- Generates customer service responses using an AI model
+- Simultaneously checks for inappropriate content while generating responses
+
+```typescript
+import { openai } from "@ai-sdk/openai";
+import { batch, task } from "@trigger.dev/sdk/v3";
+import { generateText } from "ai";
+
+// Task to generate customer response
+export const generateCustomerResponse = task({
+ id: "generate-customer-response",
+ run: async (payload: { question: string }) => {
+ const response = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content: "You are a helpful customer service representative.",
+ },
+ { role: "user", content: payload.question },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "generate-customer-response",
+ },
+ });
+
+ return response.text;
+ },
+});
+
+// Task to check for inappropriate content
+export const checkInappropriateContent = task({
+ id: "check-inappropriate-content",
+ run: async (payload: { text: string }) => {
+ const response = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content:
+ "You are a content moderator. Respond with 'true' if the content is inappropriate or contains harmful, threatening, offensive, or explicit content, 'false' otherwise.",
+ },
+ { role: "user", content: payload.text },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "check-inappropriate-content",
+ },
+ });
+
+ return response.text.toLowerCase().includes("true");
+ },
+});
+
+// Main task that coordinates the parallel execution
+export const handleCustomerQuestion = task({
+ id: "handle-customer-question",
+ run: async (payload: { question: string }) => {
+ const {
+ runs: [responseRun, moderationRun],
+ } = await batch.triggerByTaskAndWait([
+ {
+ task: generateCustomerResponse,
+ payload: { question: payload.question },
+ },
+ {
+ task: checkInappropriateContent,
+ payload: { text: payload.question },
+ },
+ ]);
+
+ // Check moderation result first
+ if (moderationRun.ok && moderationRun.output === true) {
+ return {
+ response:
+ "I apologize, but I cannot process this request as it contains inappropriate content.",
+ wasInappropriate: true,
+ };
+ }
+
+ // Return the generated response if everything is ok
+ if (responseRun.ok) {
+ return {
+ response: responseRun.output,
+ wasInappropriate: false,
+ };
+ }
+
+ // Handle any errors
+ throw new Error("Failed to process customer question");
+ },
+});
+```
+
+## Run a test
+
+On the Test page in the dashboard, select the `handle-customer-question` task and include a payload like the following:
+
+``` json
+{
+ "question": "Can you explain 2FA?"
+}
+```
+
+When triggered with a question, the task simultaneously generates a response while checking for inappropriate content using two parallel LLM calls. The main task waits for both operations to complete before delivering the final response.
+
+
diff --git a/docs/guides/ai-agents/route-question.mdx b/docs/guides/ai-agents/route-question.mdx
new file mode 100644
index 0000000000..69eb705314
--- /dev/null
+++ b/docs/guides/ai-agents/route-question.mdx
@@ -0,0 +1,114 @@
+---
+title: "Route a question to a different AI model"
+sidebarTitle: "Route a question"
+description: "Create an AI agent workflow that routes a question to a different AI model depending on its complexity"
+---
+
+## Overview
+
+**Routing** is a workflow pattern that classifies an input and directs it to a specialized followup task. This pattern allows for separation of concerns and building more specialized prompts, which is particularly effective when there are distinct categories that are better handled separately. Without routing, optimizing for one kind of input can hurt performance on other inputs.
+
+
+
+## Example task
+
+In this example, we'll create a workflow that routes a question to a different AI model depending on its complexity. This approach is particularly effective when tasks require different models or approaches for different inputs.
+
+**This task:**
+
+- Uses `generateText` from [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to interact with OpenAI models
+- Uses `experimental_telemetry` in the source verification and historical analysis tasks to provide LLM logs
+- Routes questions using a lightweight model (`o1-mini`) to classify complexity
+- Directs simple questions to `gpt-4o` and complex ones to `gpt-o3-mini`
+- Returns both the answer and metadata about the routing decision
+
+```typescript
+import { openai } from "@ai-sdk/openai";
+import { task } from "@trigger.dev/sdk/v3";
+import { generateText } from "ai";
+import { z } from "zod";
+
+// Schema for router response
+const routingSchema = z.object({
+ model: z.enum(["gpt-4o", "gpt-o3-mini"]),
+ reason: z.string(),
+});
+
+// Router prompt template
+const ROUTER_PROMPT = `You are a routing assistant that determines the complexity of questions.
+Analyze the following question and route it to the appropriate model:
+
+- Use "gpt-4o" for simple, common, or straightforward questions
+- Use "gpt-o3-mini" for complex, unusual, or questions requiring deep reasoning
+
+Respond with a JSON object in this exact format:
+{"model": "gpt-4o" or "gpt-o3-mini", "reason": "your reasoning here"}
+
+Question: `;
+
+export const routeAndAnswerQuestion = task({
+ id: "route-and-answer-question",
+ run: async (payload: { question: string }) => {
+ // Step 1: Route the question
+ const routingResponse = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content:
+ "You must respond with a valid JSON object containing only 'model' and 'reason' fields. No markdown, no backticks, no explanation.",
+ },
+ {
+ role: "user",
+ content: ROUTER_PROMPT + payload.question,
+ },
+ ],
+ temperature: 0.1,
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "route-and-answer-question",
+ },
+ });
+
+ // Add error handling and cleanup
+ let jsonText = routingResponse.text.trim();
+ if (jsonText.startsWith("```")) {
+ jsonText = jsonText.replace(/```json\n|\n```/g, "");
+ }
+
+ const routingResult = routingSchema.parse(JSON.parse(jsonText));
+
+ // Step 2: Get the answer using the selected model
+ const answerResult = await generateText({
+ model: openai(routingResult.model),
+ messages: [{ role: "user", content: payload.question }],
+ });
+
+ return {
+ answer: answerResult.text,
+ selectedModel: routingResult.model,
+ routingReason: routingResult.reason,
+ };
+ },
+});
+```
+
+
+
+## Run a test
+
+Triggering our task with a simple question shows it routing to the gpt-4o model and returning the answer with reasoning:
+
+```json
+{
+ "question": "How many planets are there in the solar system?"
+}
+```
+
+
\ No newline at end of file
diff --git a/docs/guides/ai-agents/routing.png b/docs/guides/ai-agents/routing.png
new file mode 100644
index 0000000000..332ac2c462
Binary files /dev/null and b/docs/guides/ai-agents/routing.png differ
diff --git a/docs/guides/ai-agents/translate-and-refine.mdx b/docs/guides/ai-agents/translate-and-refine.mdx
new file mode 100644
index 0000000000..fd3d1b5a9d
--- /dev/null
+++ b/docs/guides/ai-agents/translate-and-refine.mdx
@@ -0,0 +1,170 @@
+---
+title: "Translate text and refine it based on feedback"
+sidebarTitle: "Translate and refine"
+description: "This guide will show you how to create a task that translates text and refines it based on feedback."
+---
+
+## Overview
+
+This example is based on the **evaluator-optimizer** pattern, where one LLM generates a response while another provides evaluation and feedback in a loop. This is particularly effective for tasks with clear evaluation criteria where iterative refinement provides better results.
+
+
+
+## Example task
+
+This example task translates text into a target language and refines the translation over a number of iterations based on feedback provided by the LLM.
+
+**This task:**
+
+- Uses `generateText` from [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to generate the translation
+- Uses `experimental_telemetry` to provide LLM logs on the Run page in the dashboard
+- Runs for a maximum of 10 iterations
+- Uses `generateText` again to evaluate the translation
+- Recursively calls itself to refine the translation based on the feedback
+
+```typescript
+import { task } from "@trigger.dev/sdk/v3";
+import { generateText } from "ai";
+import { openai } from "@ai-sdk/openai";
+
+interface TranslationPayload {
+ text: string;
+ targetLanguage: string;
+ previousTranslation?: string;
+ feedback?: string;
+ rejectionCount?: number;
+}
+
+export const translateAndRefine = task({
+ id: "translate-and-refine",
+ run: async (payload: TranslationPayload) => {
+ const rejectionCount = payload.rejectionCount || 0;
+
+ // Bail out if we've hit the maximum attempts
+ if (rejectionCount >= 10) {
+ return {
+ finalTranslation: payload.previousTranslation,
+ iterations: rejectionCount,
+ status: "MAX_ITERATIONS_REACHED",
+ };
+ }
+
+ // Generate translation (or refinement if we have previous feedback)
+ const translationPrompt = payload.feedback
+ ? `Previous translation: "${payload.previousTranslation}"\n\nFeedback received: "${payload.feedback}"\n\nPlease provide an improved translation addressing this feedback.`
+ : `Translate this text into ${payload.targetLanguage}, preserving style and meaning: "${payload.text}"`;
+
+ const translation = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content: `You are an expert literary translator into ${payload.targetLanguage}.
+ Focus on accuracy first, then style and natural flow.`,
+ },
+ {
+ role: "user",
+ content: translationPrompt,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "translate-and-refine",
+ },
+ });
+
+ // Evaluate the translation
+ const evaluation = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content: `You are an expert literary critic and translator focused on practical, high-quality translations.
+ Your goal is to ensure translations are accurate and natural, but not necessarily perfect.
+ This is iteration ${
+ rejectionCount + 1
+ } of a maximum 5 iterations.
+
+ RESPONSE FORMAT:
+ - If the translation meets 90%+ quality: Respond with exactly "APPROVED" (nothing else)
+ - If improvements are needed: Provide only the specific issues that must be fixed
+
+ Evaluation criteria:
+ - Accuracy of meaning (primary importance)
+ - Natural flow in the target language
+ - Preservation of key style elements
+
+ DO NOT provide detailed analysis, suggestions, or compliments.
+ DO NOT include the translation in your response.
+
+ IMPORTANT RULES:
+ - First iteration MUST receive feedback for improvement
+ - Be very strict on accuracy in early iterations
+ - After 3 iterations, lower quality threshold to 85%`,
+ },
+ {
+ role: "user",
+ content: `Original: "${payload.text}"
+ Translation: "${translation.text}"
+ Target Language: ${payload.targetLanguage}
+ Iteration: ${rejectionCount + 1}
+ Previous Feedback: ${
+ payload.feedback ? `"${payload.feedback}"` : "None"
+ }
+
+ ${
+ rejectionCount === 0
+ ? "This is the first attempt. Find aspects to improve."
+ : 'Either respond with exactly "APPROVED" or provide only critical issues that must be fixed.'
+ }`,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "translate-and-refine",
+ },
+ });
+
+ // If approved, return the final result
+ if (evaluation.text.trim() === "APPROVED") {
+ return {
+ finalTranslation: translation.text,
+ iterations: rejectionCount,
+ status: "APPROVED",
+ };
+ }
+
+ // If not approved, recursively call the task with feedback
+ await translateAndRefine
+ .triggerAndWait({
+ text: payload.text,
+ targetLanguage: payload.targetLanguage,
+ previousTranslation: translation.text,
+ feedback: evaluation.text,
+ rejectionCount: rejectionCount + 1,
+ })
+ .unwrap();
+ },
+});
+```
+
+## Run a test
+
+On the Test page in the dashboard, select the `translate-and-refine` task and include a payload like the following:
+
+```json
+{
+ "text": "In the twilight of his years, the old clockmaker's hands, once steady as the timepieces he crafted, now trembled like autumn leaves in the wind.",
+ "targetLanguage": "French"
+}
+```
+
+This example payload translates the text into French and should be suitably difficult to require a few iterations, depending on the model used and the prompt criteria you set.
+
+
\ No newline at end of file
diff --git a/docs/guides/ai-agents/verify-news-article.mdx b/docs/guides/ai-agents/verify-news-article.mdx
new file mode 100644
index 0000000000..2d912c7415
--- /dev/null
+++ b/docs/guides/ai-agents/verify-news-article.mdx
@@ -0,0 +1,220 @@
+---
+title: "Verify a news article"
+sidebarTitle: "Verify news article"
+description: "Create an AI agent workflow that verifies the facts in a news article"
+---
+
+## Overview
+
+This example demonstrates the **orchestrator-workers** pattern, where a central AI agent dynamically breaks down complex tasks and delegates them to specialized worker agents. This pattern is particularly effective when tasks require multiple perspectives or parallel processing streams, with the orchestrator synthesizing the results into a cohesive output.
+
+
+
+## Example task
+
+Our example task uses multiple LLM calls to extract claims from a news article and analyze them in parallel, combining source verification and historical context to assess their credibility.
+
+**This task:**
+
+- Uses `generateText` from [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to interact with OpenAI models
+- Uses `experimental_telemetry` to provide LLM logs
+- Uses [`batch.triggerByTaskAndWait`](/triggering#batch-triggerbytaskandwait) to orchestrate parallel processing of claims
+- Extracts factual claims from news articles using the `o1-mini` model
+- Evaluates claims against recent sources and analyzes historical context in parallel
+- Combines results into a structured analysis report
+
+
+```typescript
+import { openai } from "@ai-sdk/openai";
+import { batch, logger, task } from "@trigger.dev/sdk/v3";
+import { CoreMessage, generateText } from "ai";
+
+// Define types for our workers' outputs
+interface Claim {
+ id: number;
+ text: string;
+}
+
+interface SourceVerification {
+ claimId: number;
+ isVerified: boolean;
+ confidence: number;
+ explanation: string;
+}
+
+interface HistoricalAnalysis {
+ claimId: number;
+ feasibility: number;
+ historicalContext: string;
+}
+
+// Worker 1: Claim Extractor
+export const extractClaims = task({
+ id: "extract-claims",
+ run: async ({ article }: { article: string }) => {
+ try {
+ const messages: CoreMessage[] = [
+ {
+ role: "system",
+ content:
+ "Extract distinct factual claims from the news article. Format as numbered claims.",
+ },
+ {
+ role: "user",
+ content: article,
+ },
+ ];
+
+ const response = await generateText({
+ model: openai("o1-mini"),
+ messages,
+ });
+
+ const claims = response.text
+ .split("\n")
+ .filter((line: string) => line.trim())
+ .map((claim: string, index: number) => ({
+ id: index + 1,
+ text: claim.replace(/^\d+\.\s*/, ""),
+ }));
+
+ logger.info("Extracted claims", { claimCount: claims.length });
+ return claims;
+ } catch (error) {
+ logger.error("Error in claim extraction", {
+ error: error instanceof Error ? error.message : "Unknown error",
+ });
+ throw error;
+ }
+ },
+});
+
+// Worker 2: Source Verifier
+export const verifySource = task({
+ id: "verify-source",
+ run: async (claim: Claim) => {
+ const response = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content:
+ "Verify this claim by considering recent news sources and official statements. Assess reliability.",
+ },
+ {
+ role: "user",
+ content: claim.text,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "verify-source",
+ },
+ });
+
+ return {
+ claimId: claim.id,
+ isVerified: false,
+ confidence: 0.7,
+ explanation: response.text,
+ };
+ },
+});
+
+// Worker 3: Historical Context Analyzer
+export const analyzeHistory = task({
+ id: "analyze-history",
+ run: async (claim: Claim) => {
+ const response = await generateText({
+ model: openai("o1-mini"),
+ messages: [
+ {
+ role: "system",
+ content:
+ "Analyze this claim in historical context, considering past announcements and technological feasibility.",
+ },
+ {
+ role: "user",
+ content: claim.text,
+ },
+ ],
+ experimental_telemetry: {
+ isEnabled: true,
+ functionId: "analyze-history",
+ },
+ });
+
+ return {
+ claimId: claim.id,
+ feasibility: 0.8,
+ historicalContext: response.text,
+ };
+ },
+});
+
+// Orchestrator
+export const newsFactChecker = task({
+ id: "news-fact-checker",
+ run: async ({ article }: { article: string }) => {
+ // Step 1: Extract claims
+ const claimsResult = await batch.triggerByTaskAndWait([
+ { task: extractClaims, payload: { article } },
+ ]);
+
+ if (!claimsResult.runs[0].ok) {
+ logger.error("Failed to extract claims", {
+ error: claimsResult.runs[0].error,
+ runId: claimsResult.runs[0].id,
+ });
+ throw new Error(
+ `Failed to extract claims: ${claimsResult.runs[0].error}`
+ );
+ }
+
+ const claims = claimsResult.runs[0].output;
+
+ // Step 2: Process claims in parallel
+ const parallelResults = await batch.triggerByTaskAndWait([
+ ...claims.map((claim) => ({ task: verifySource, payload: claim })),
+ ...claims.map((claim) => ({ task: analyzeHistory, payload: claim })),
+ ]);
+
+ // Split and process results
+ const verifications = parallelResults.runs
+ .filter(
+ (run): run is typeof run & { ok: true } =>
+ run.ok && run.taskIdentifier === "verify-source"
+ )
+ .map((run) => run.output as SourceVerification);
+
+ const historicalAnalyses = parallelResults.runs
+ .filter(
+ (run): run is typeof run & { ok: true } =>
+ run.ok && run.taskIdentifier === "analyze-history"
+ )
+ .map((run) => run.output as HistoricalAnalysis);
+
+ return { claims, verifications, historicalAnalyses };
+ },
+});
+```
+
+## Run a test
+
+On the Test page in the dashboard, select the `news-fact-checker` task and include a payload like the following:
+
+```json
+{
+ "article": "Tesla announced a new breakthrough in battery technology today. The company claims their new batteries will have 50% more capacity and cost 30% less to produce. Elon Musk stated this development will enable electric vehicles to achieve price parity with gasoline cars by 2024. The new batteries are scheduled to enter production next quarter at the Texas Gigafactory."
+}
+```
+
+This example payload verifies the claims in the news article and provides a report on the results.
+
+
\ No newline at end of file
diff --git a/docs/guides/dashboard/creating-a-project.mdx b/docs/guides/dashboard/creating-a-project.mdx
deleted file mode 100644
index 2854ccbd32..0000000000
--- a/docs/guides/dashboard/creating-a-project.mdx
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "Creating a project"
-description: "This guide will show you how to create a new Trigger.dev project."
----
-
-## Prerequisites
-
-- [Create a Trigger.dev account](https://cloud.trigger.dev)
-- Login to the Trigger.dev [dashboard](https://cloud.trigger.dev)
-
-## Create a new Trigger.dev project
-
-
-
- Click on "Projects" in the left hand side menu then click on "Create a new Project" button in the top right corner .
- 
-
-
- 
-
-
- Once you have created your project you can find your Project ref to add to your `trigger.config` file and rename your project by clicking "Project settings" in the left hand side menubar.
- 
-
-
-
-## Useful next steps
-
-
-
- Setup Trigger.dev in 3 minutes
-
-
- Learn what tasks are and how to write them
-
-
diff --git a/docs/guides/example-projects/realtime-fal-ai.mdx b/docs/guides/example-projects/realtime-fal-ai.mdx
index e0dc0f6f3e..e61499c2b8 100644
--- a/docs/guides/example-projects/realtime-fal-ai.mdx
+++ b/docs/guides/example-projects/realtime-fal-ai.mdx
@@ -30,16 +30,14 @@ This full stack Next.js project showcases the following:
This video walks through the process of creating this task in a Next.js project.
-
-
-
+
diff --git a/docs/guides/examples/fal-ai-image-to-cartoon.mdx b/docs/guides/examples/fal-ai-image-to-cartoon.mdx
index 9275d09cb9..1deb56b095 100644
--- a/docs/guides/examples/fal-ai-image-to-cartoon.mdx
+++ b/docs/guides/examples/fal-ai-image-to-cartoon.mdx
@@ -8,9 +8,15 @@ description: "This example task generates an image from a URL using Fal.ai and u
This video walks through the process of creating this task in a Next.js project.
-
-
-
+
## Prerequisites
diff --git a/docs/guides/examples/fal-ai-realtime.mdx b/docs/guides/examples/fal-ai-realtime.mdx
index 52f5ede9fd..38f28c44f5 100644
--- a/docs/guides/examples/fal-ai-realtime.mdx
+++ b/docs/guides/examples/fal-ai-realtime.mdx
@@ -19,17 +19,15 @@ description: "This example task generates an image from a prompt using Fal.ai an
This video walks through the process of creating this task in a Next.js project.
-
-
-
+/>
## Prerequisites
diff --git a/docs/guides/examples/scrape-hacker-news.mdx b/docs/guides/examples/scrape-hacker-news.mdx
index 7b869757ea..dc17bc4808 100644
--- a/docs/guides/examples/scrape-hacker-news.mdx
+++ b/docs/guides/examples/scrape-hacker-news.mdx
@@ -7,17 +7,15 @@ description: "This example demonstrates how to scrape the top 3 articles from Ha
import LocalDevelopment from "/snippets/local-development-extensions.mdx";
import ScrapingWarning from "/snippets/web-scraping-warning.mdx";
-
-
-
+/>
## Overview
diff --git a/docs/guides/frameworks/supabase-edge-functions-basic.mdx b/docs/guides/frameworks/supabase-edge-functions-basic.mdx
index 5fd9f5eb46..7b00f176bb 100644
--- a/docs/guides/frameworks/supabase-edge-functions-basic.mdx
+++ b/docs/guides/frameworks/supabase-edge-functions-basic.mdx
@@ -29,7 +29,7 @@ This guide shows you how to set up and deploy a simple Supabase edge function ex
- Since Supabase CLI version 1.123.4, you must have [Docker Desktop installed](https://supabase.com/docs/guides/functions/deploy#deploy-your-edge-functions) to deploy Edge Functions
- Ensure TypeScript is installed
- [Create a Trigger.dev account](https://cloud.trigger.dev)
-- [Create a new Trigger.dev project](/guides/dashboard/creating-a-project)
+- Create a new Trigger.dev project
## GitHub repo
diff --git a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx
index 223ae23aa5..e018277cec 100644
--- a/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx
+++ b/docs/guides/frameworks/supabase-edge-functions-database-webhooks.mdx
@@ -31,7 +31,7 @@ Supabase and Trigger.dev can be used together to create powerful workflows trigg
- Since Supabase CLI version 1.123.4, you must have [Docker Desktop installed](https://supabase.com/docs/guides/functions/deploy#deploy-your-edge-functions) to deploy Edge Functions
- Ensure TypeScript is installed
- [Create a Trigger.dev account](https://cloud.trigger.dev)
-- [Create a new Trigger.dev project](/guides/dashboard/creating-a-project)
+- Create a new Trigger.dev project
- [Create a new Deepgram account](https://deepgram.com/) and get your API key from the dashboard
## GitHub repo
diff --git a/docs/guides/introduction.mdx b/docs/guides/introduction.mdx
index 12f11de627..cf4bd34c6f 100644
--- a/docs/guides/introduction.mdx
+++ b/docs/guides/introduction.mdx
@@ -1,30 +1,30 @@
---
title: "Frameworks, guides and examples overview"
-sidebarTitle: "Introduction"
+sidebarTitle: "Overview"
description: "An ever growing list of guides and examples to help you get setup with Trigger.dev."
---
-import CardBun from "/snippets/card-bun.mdx";
-import CardNodejs from "/snippets/card-nodejs.mdx";
-import CardNextjs from "/snippets/card-nextjs.mdx";
-import CardRemix from "/snippets/card-remix.mdx";
-import CardSupabase from "/snippets/card-supabase.mdx";
-
## Frameworks
-
-
-
-
-
+
+
+
+
+
+
## Guides
Get set up fast using our detailed walk-through guides.
| Guide | Description |
| :----------------------------------------------------------------------------------------- | :------------------------------------------------ |
+| [AI Agent: Generate and translate copy](/guides/ai-agents/generate-translate-copy) | Chain prompts to generate and translate content |
+| [AI Agent: Route questions](/guides/ai-agents/route-question) | Route questions to different models based on complexity |
+| [AI Agent: Content moderation](/guides/ai-agents/respond-and-check-content) | Parallel check content while responding to customers |
+| [AI Agent: News verification](/guides/ai-agents/verify-news-article) | Orchestrate fact checking of news articles |
+| [AI Agent: Translation refinement](/guides/ai-agents/translate-and-refine) | Evaluate and refine translations with feedback |
| [Prisma](/guides/frameworks/prisma) | How to setup Prisma with Trigger.dev |
| [Sequin database triggers](/guides/frameworks/sequin) | Trigger tasks from database changes using Sequin |
| [Supabase edge function hello world](/guides/frameworks/supabase-edge-functions-basic) | Trigger tasks from Supabase edge function |
diff --git a/docs/images/creating-a-project/creating-a-project-1.png b/docs/images/creating-a-project/creating-a-project-1.png
deleted file mode 100644
index 28e99d8d29..0000000000
Binary files a/docs/images/creating-a-project/creating-a-project-1.png and /dev/null differ
diff --git a/docs/images/creating-a-project/creating-a-project-2.png b/docs/images/creating-a-project/creating-a-project-2.png
deleted file mode 100644
index 393da25617..0000000000
Binary files a/docs/images/creating-a-project/creating-a-project-2.png and /dev/null differ
diff --git a/docs/images/creating-a-project/creating-a-project-3.png b/docs/images/creating-a-project/creating-a-project-3.png
deleted file mode 100644
index 68d74ca886..0000000000
Binary files a/docs/images/creating-a-project/creating-a-project-3.png and /dev/null differ
diff --git a/docs/images/intro-browserbase.jpg b/docs/images/intro-browserbase.jpg
new file mode 100644
index 0000000000..0be974da4d
Binary files /dev/null and b/docs/images/intro-browserbase.jpg differ
diff --git a/docs/images/intro-deepgram.jpg b/docs/images/intro-deepgram.jpg
new file mode 100644
index 0000000000..bafe9f21d2
Binary files /dev/null and b/docs/images/intro-deepgram.jpg differ
diff --git a/docs/images/intro-examples.jpg b/docs/images/intro-examples.jpg
new file mode 100644
index 0000000000..03e20df350
Binary files /dev/null and b/docs/images/intro-examples.jpg differ
diff --git a/docs/images/intro-fal.jpg b/docs/images/intro-fal.jpg
new file mode 100644
index 0000000000..5379eb185f
Binary files /dev/null and b/docs/images/intro-fal.jpg differ
diff --git a/docs/images/intro-ffmpeg.jpg b/docs/images/intro-ffmpeg.jpg
new file mode 100644
index 0000000000..ffd5830b3f
Binary files /dev/null and b/docs/images/intro-ffmpeg.jpg differ
diff --git a/docs/images/intro-firecrawl.jpg b/docs/images/intro-firecrawl.jpg
new file mode 100644
index 0000000000..3dcdd7ab3a
Binary files /dev/null and b/docs/images/intro-firecrawl.jpg differ
diff --git a/docs/images/intro-frameworks.jpg b/docs/images/intro-frameworks.jpg
new file mode 100644
index 0000000000..00715e21fb
Binary files /dev/null and b/docs/images/intro-frameworks.jpg differ
diff --git a/docs/images/intro-libreoffice.jpg b/docs/images/intro-libreoffice.jpg
new file mode 100644
index 0000000000..894d0d9f75
Binary files /dev/null and b/docs/images/intro-libreoffice.jpg differ
diff --git a/docs/images/intro-openai.jpg b/docs/images/intro-openai.jpg
new file mode 100644
index 0000000000..096bdcd508
Binary files /dev/null and b/docs/images/intro-openai.jpg differ
diff --git a/docs/images/intro-puppeteer.jpg b/docs/images/intro-puppeteer.jpg
new file mode 100644
index 0000000000..183ea7d55c
Binary files /dev/null and b/docs/images/intro-puppeteer.jpg differ
diff --git a/docs/images/intro-quickstart.jpg b/docs/images/intro-quickstart.jpg
new file mode 100644
index 0000000000..f01e9c2ce5
Binary files /dev/null and b/docs/images/intro-quickstart.jpg differ
diff --git a/docs/images/intro-resend.jpg b/docs/images/intro-resend.jpg
new file mode 100644
index 0000000000..995fbac0a7
Binary files /dev/null and b/docs/images/intro-resend.jpg differ
diff --git a/docs/images/intro-sentry.jpg b/docs/images/intro-sentry.jpg
new file mode 100644
index 0000000000..6aef9127c5
Binary files /dev/null and b/docs/images/intro-sentry.jpg differ
diff --git a/docs/images/intro-sharp.jpg b/docs/images/intro-sharp.jpg
new file mode 100644
index 0000000000..f462793709
Binary files /dev/null and b/docs/images/intro-sharp.jpg differ
diff --git a/docs/images/intro-supabase.jpg b/docs/images/intro-supabase.jpg
new file mode 100644
index 0000000000..aeffb69485
Binary files /dev/null and b/docs/images/intro-supabase.jpg differ
diff --git a/docs/images/intro-vercel.jpg b/docs/images/intro-vercel.jpg
new file mode 100644
index 0000000000..3aa6426dfe
Binary files /dev/null and b/docs/images/intro-vercel.jpg differ
diff --git a/docs/images/intro-video.jpg b/docs/images/intro-video.jpg
new file mode 100644
index 0000000000..11b68b562d
Binary files /dev/null and b/docs/images/intro-video.jpg differ
diff --git a/docs/images/logo-bun.png b/docs/images/logo-bun.png
new file mode 100644
index 0000000000..fd17a59062
Binary files /dev/null and b/docs/images/logo-bun.png differ
diff --git a/docs/images/logo-nextjs.png b/docs/images/logo-nextjs.png
new file mode 100644
index 0000000000..9007cb4217
Binary files /dev/null and b/docs/images/logo-nextjs.png differ
diff --git a/docs/images/logo-nodejs-1.png b/docs/images/logo-nodejs-1.png
new file mode 100644
index 0000000000..22985b15cc
Binary files /dev/null and b/docs/images/logo-nodejs-1.png differ
diff --git a/docs/images/logo-nodejs.png b/docs/images/logo-nodejs.png
new file mode 100644
index 0000000000..4a95ab5530
Binary files /dev/null and b/docs/images/logo-nodejs.png differ
diff --git a/docs/images/logo-remix.png b/docs/images/logo-remix.png
new file mode 100644
index 0000000000..9f7ca11c48
Binary files /dev/null and b/docs/images/logo-remix.png differ
diff --git a/docs/introduction.mdx b/docs/introduction.mdx
index 16df1bba43..fd17e8b911 100644
--- a/docs/introduction.mdx
+++ b/docs/introduction.mdx
@@ -1,59 +1,94 @@
---
-title: "Introduction"
-description: "Welcome to the Trigger.dev v3 documentation."
+title: "Welcome to the Trigger.dev docs"
+sidebarTitle: "Introduction"
+description: "Find all the resources and guides you need to get started"
+mode: "center"
---
-## What is Trigger.dev (v3)?
-
-Trigger.dev v3 makes it easy to write reliable long-running tasks without timeouts.
+
+
+ Get started with Trigger.dev in 3 minutes
+
+
+ Explore dozens of examples tasks to use in your own projects
+
+
+ Learn how to use Trigger.dev with your favorite frameworks
+
+
+ Watch an end-to-end demo of Trigger.dev in 10 minutes
+
+
-- We run your tasks with no timeouts. You don't have to manage any infrastructure (unless you [self-host](/open-source-self-hosting)). Workers are automatically scaled and managed for you.
-- We provide a multi-tenant queue that is used when triggering tasks.
-- We provide an SDK and CLI for writing tasks in your existing codebase, inside [/trigger folders](/config/config-file).
-- We provide different types of tasks: [regular](/tasks-regular) and [scheduled](/tasks/scheduled).
-- We provide a dashboard for monitoring, debugging, and managing your tasks.
-- We provide a [Realtime API](/realtime) for monitoring tasks in real-time, along with [React hooks](/frontend/react-hooks#realtime-hooks) for building custom dashboards.
+## What is Trigger.dev?
-We're [open source](https://github.com/triggerdotdev/trigger.dev) and you can choose to use the [Trigger.dev Cloud](https://cloud.trigger.dev) or [Self-host Trigger.dev](/open-source-self-hosting) on your own infrastructure.
+Trigger.dev is an open source background jobs framework that lets you write reliable workflows in plain async code. Run long-running AI tasks, handle complex background jobs, and build AI agents with built-in queuing, automatic retries, and real-time monitoring. No timeouts, elastic scaling, and zero infrastructure management required.
-## Getting started
+We provide everything you need to build and manage background tasks: a [CLI and SDK](/config/config-file) for writing tasks in your existing codebase, support for both [regular](/tasks-regular) and [scheduled](/tasks/scheduled) tasks, full observability through our dashboard, and a [Realtime API](/realtime) with [React hooks](/frontend/react-hooks#realtime-hooks) for showing task status in your frontend. You can use [Trigger.dev Cloud](https://cloud.trigger.dev) or [self-host](/open-source-self-hosting) on your own infrastructure.
-### Video walkthrough
+## Learn the concepts
-
-
-
+
+
+ Tasks are the core of Trigger.dev. Learn what they are and how to write them.
+
+
+ Learn how to trigger tasks from your codebase.
+
+
+ Runs are the instances of tasks that are executed. Learn how they work.
+
+
+ API keys are used to authenticate requests to the Trigger.dev API. Learn how to create and use them.
+
+
-### Quick start, writing tasks and guides
+## Explore by feature
-
- Go from zero to running your first task in 3 minutes.
+
+ Scheduled tasks are a type of task that is scheduled to run at a specific time.
-
- Tasks are the core of Trigger.dev. Learn what they are and how to write them.
+
+ The Realtime API allows you to trigger tasks and get the status of runs.
+
+
+ React hooks are a way to show task status in your frontend.
+
+
+ Waits are a way to wait for a task to finish before continuing.
-
- Detailed guides for setting up Trigger.dev with popular frameworks and services, including
- Next.js, Remix, Supabase and more.
+
+ Learn how to handle errors and retries.
-
- Code you can use in your own projects, including OpenAI, Deepgram, FFmpeg, Puppeteer, Stripe,
- Supabase and many more.
+
+ Configure what you want to happen when there is more than one run at a time.
+## Explore by example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
## Getting help
-We'd love to hear from you or give you a hand getting started. Here are some ways to get in touch with us. We'd also ❤️ your support.
+We'd love to hear from you or give you a hand getting started. Here are some ways to get in touch with us.
- The help forum is a great place to get help with any questions about Trigger.dev.
+ Our Discord is the best place to get help with any questions about Trigger.dev.
- Follow us on X (Twitter) to get the latest updates and news.
+ Follow us to get the latest updates and news.
- Arrange a call with one of the founders. We can help answer questions and give 1-on-1 help
- building your first task.
+ Arrange a call with one of the founders to get help with any questions.
- Check us out at triggerdotdev/trigger.dev
+ Check us out our GitHub repo and give us a star if you like what we're doing.
diff --git a/docs/mint.json b/docs/mint.json
deleted file mode 100644
index 551d8a5f50..0000000000
--- a/docs/mint.json
+++ /dev/null
@@ -1,392 +0,0 @@
-{
- "$schema": "https://mintlify.com/schema.json",
- "name": "Trigger.dev",
- "openapi": ["/openapi.yml", "/v3-openapi.yaml"],
- "api": {
- "playground": {
- "mode": "simple"
- },
- "maintainOrder": true
- },
- "logo": {
- "dark": "/logo/dark.png",
- "light": "/logo/light.png",
- "href": "https://trigger.dev"
- },
- "favicon": "/images/favicon.png",
- "colors": {
- "primary": "#A8FF53",
- "light": "#A8FF53",
- "dark": "#A8FF53",
- "anchors": {
- "from": "#252630",
- "to": "#252630"
- },
- "background": {
- "light": "#fff",
- "dark": "#121317"
- }
- },
- "theme": "quill",
- "modeToggle": {
- "default": "dark",
- "isHidden": true
- },
- "feedback": {
- "suggestEdit": true,
- "raiseIssue": true,
- "thumbsRating": true
- },
- "topbarCtaButton": {
- "type": "github",
- "url": "https://github.com/triggerdotdev/trigger.dev"
- },
- "topbarLinks": [
- {
- "name": "Switch to v2 docs",
- "url": "https://v2docs.trigger.dev/documentation/introduction"
- },
- {
- "name": "Discord",
- "url": "https://trigger.dev/discord"
- }
- ],
- "redirects": [
- {
- "source": "/v3/feature-matrix",
- "destination": "https://feedback.trigger.dev/roadmap"
- },
- {
- "source": "/v3/upgrading-from-v2",
- "destination": "/guides/use-cases/upgrading-from-v2"
- },
- {
- "source": "/v3/open-source-self-hosting",
- "destination": "/open-source-self-hosting"
- },
- {
- "source": "/v3/:slug*",
- "destination": "/:slug*"
- },
- {
- "source": "/reattempting-replaying",
- "destination": "/replaying"
- },
- {
- "source": "/tasks-overview",
- "destination": "/tasks/overview"
- },
- {
- "source": "/tasks-scheduled",
- "destination": "/tasks/scheduled"
- },
- {
- "source": "/trigger-folder",
- "destination": "/config/config-file"
- },
- {
- "source": "/trigger-config",
- "destination": "/config/config-file"
- },
- {
- "source": "/guides/frameworks/introduction",
- "destination": "/guides/introduction"
- },
- {
- "source": "/guides/examples/intro",
- "destination": "/guides/introduction"
- },
- {
- "source": "/examples/:slug*",
- "destination": "/guides/examples/:slug*"
- },
- {
- "source": "/realtime",
- "destination": "/realtime/overview"
- },
- {
- "source": "/runs-and-attempts",
- "destination": "/runs"
- },
- {
- "source": "/frontend/react-hooks",
- "destination": "/frontend/react-hooks/overview"
- }
- ],
- "anchors": [
- {
- "name": "Guides & examples",
- "icon": "book",
- "url": "guides"
- }
- ],
- "navigation": [
- {
- "group": "Getting Started",
- "pages": ["introduction", "quick-start", "video-walkthrough", "how-it-works", "limits"]
- },
- {
- "group": "Fundamentals",
- "pages": [
- {
- "group": "Tasks",
- "pages": ["tasks/overview", "tasks/schemaTask", "tasks/scheduled"]
- },
- "triggering",
- "runs",
- "apikeys",
- {
- "group": "Configuration",
- "pages": ["config/config-file", "config/extensions/overview"]
- }
- ]
- },
- {
- "group": "Development",
- "pages": ["cli-dev", "run-tests"]
- },
- {
- "group": "Deployment",
- "pages": [
- "cli-deploy",
- "deploy-environment-variables",
- "github-actions",
- {
- "group": "Deployment integrations",
- "pages": ["vercel-integration"]
- }
- ]
- },
- {
- "group": "Writing tasks",
- "pages": [
- "writing-tasks-introduction",
- "logging",
- "errors-retrying",
- {
- "group": "Wait",
- "pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"]
- },
- "queue-concurrency",
- "versioning",
- "machines",
- "idempotency",
- "replaying",
- "runs/max-duration",
- "tags",
- "runs/metadata",
- "run-usage",
- "context",
- "bulk-actions",
- "examples"
- ]
- },
- {
- "group": "Frontend usage",
- "pages": [
- "frontend/overview",
- {
- "group": "React hooks",
- "pages": [
- "frontend/react-hooks/overview",
- "frontend/react-hooks/realtime",
- "frontend/react-hooks/triggering"
- ]
- }
- ]
- },
- {
- "group": "Realtime API",
- "pages": [
- "realtime/overview",
- "realtime/streams",
- "realtime/react-hooks",
- "realtime/subscribe-to-run",
- "realtime/subscribe-to-runs-with-tag",
- "realtime/subscribe-to-batch"
- ]
- },
- {
- "group": "API reference",
- "pages": [
- "management/overview",
- {
- "group": "Tasks API",
- "pages": ["management/tasks/trigger", "management/tasks/batch-trigger"]
- },
- {
- "group": "Runs API",
- "pages": [
- "management/runs/list",
- "management/runs/retrieve",
- "management/runs/replay",
- "management/runs/cancel",
- "management/runs/reschedule",
- "management/runs/update-metadata"
- ]
- },
- {
- "group": "Schedules API",
- "pages": [
- "management/schedules/list",
- "management/schedules/create",
- "management/schedules/retrieve",
- "management/schedules/update",
- "management/schedules/delete",
- "management/schedules/deactivate",
- "management/schedules/activate",
- "management/schedules/timezones"
- ]
- },
- {
- "group": "Env Vars API",
- "pages": [
- "management/envvars/list",
- "management/envvars/import",
- "management/envvars/create",
- "management/envvars/retrieve",
- "management/envvars/update",
- "management/envvars/delete"
- ]
- },
- {
- "group": "Projects API",
- "pages": ["management/projects/runs"]
- }
- ]
- },
- {
- "group": "CLI",
- "pages": [
- "cli-introduction",
- {
- "group": "Commands",
- "pages": [
- "cli-login-commands",
- "cli-init-commands",
- "cli-dev-commands",
- "cli-deploy-commands",
- "cli-whoami-commands",
- "cli-logout-commands",
- "cli-list-profiles-commands",
- "cli-update-commands"
- ]
- }
- ]
- },
- {
- "group": "Open source",
- "pages": [
- "open-source-self-hosting",
- "open-source-contributing",
- "github-repo",
- "changelog",
- "roadmap"
- ]
- },
- {
- "group": "Troubleshooting",
- "pages": [
- "troubleshooting",
- "upgrading-packages",
- "upgrading-beta",
- "troubleshooting-alerts",
- "troubleshooting-uptime-status",
- "troubleshooting-github-issues",
- "request-feature"
- ]
- },
- {
- "group": "Help",
- "pages": ["community", "help-slack", "help-email"]
- },
- {
- "group": "",
- "pages": ["guides/introduction"]
- },
- {
- "group": "Frameworks",
- "pages": [
- "guides/frameworks/bun",
- "guides/frameworks/nextjs",
- "guides/frameworks/nodejs",
- "guides/frameworks/remix"
- ]
- },
- {
- "group": "Guides",
- "pages": [
- "guides/frameworks/prisma",
- "guides/frameworks/drizzle",
- "guides/frameworks/sequin",
- {
- "group": "Supabase",
- "icon": "bolt",
- "iconType": "solid",
- "pages": [
- "guides/frameworks/supabase-guides-overview",
- "guides/frameworks/supabase-edge-functions-basic",
- "guides/frameworks/supabase-edge-functions-database-webhooks"
- ]
- },
- {
- "group": "Webhooks",
- "icon": "webhook",
- "iconType": "solid",
- "pages": [
- "guides/frameworks/webhooks-guides-overview",
- "guides/frameworks/nextjs-webhooks",
- "guides/frameworks/remix-webhooks",
- "guides/examples/stripe-webhook"
- ]
- }
- ]
- },
- {
- "group": "Example projects",
- "pages": [
- "guides/example-projects/realtime-fal-ai",
- "guides/example-projects/batch-llm-evaluator",
- "guides/example-projects/realtime-csv-importer",
- "guides/example-projects/vercel-ai-sdk-image-generator"
- ]
- },
- {
- "group": "Example tasks",
- "pages": [
- "guides/examples/dall-e3-generate-image",
- "guides/examples/deepgram-transcribe-audio",
- "guides/examples/fal-ai-image-to-cartoon",
- "guides/examples/fal-ai-realtime",
- "guides/examples/ffmpeg-video-processing",
- "guides/examples/firecrawl-url-crawl",
- "guides/examples/libreoffice-pdf-conversion",
- "guides/examples/open-ai-with-retrying",
- "guides/examples/pdf-to-image",
- "guides/examples/puppeteer",
- "guides/examples/scrape-hacker-news",
- "guides/examples/sentry-error-tracking",
- "guides/examples/sharp-image-processing",
- "guides/examples/supabase-database-operations",
- "guides/examples/supabase-storage-upload",
- "guides/examples/react-pdf",
- "guides/examples/resend-email-sequence",
- "guides/examples/vercel-ai-sdk",
- "guides/examples/vercel-sync-env-vars"
- ]
- },
- {
- "group": "Dashboard",
- "pages": ["guides/dashboard/creating-a-project"]
- },
- {
- "group": "Migrations",
- "pages": ["guides/use-cases/upgrading-from-v2"]
- }
- ],
- "footerSocials": {
- "twitter": "https://twitter.com/triggerdotdev",
- "github": "https://github.com/triggerdotdev",
- "linkedin": "https://www.linkedin.com/company/triggerdotdev"
- }
-}
diff --git a/docs/realtime/overview.mdx b/docs/realtime/overview.mdx
index 4a102d7767..b4193f1366 100644
--- a/docs/realtime/overview.mdx
+++ b/docs/realtime/overview.mdx
@@ -12,17 +12,15 @@ The Realtime API is built on top of [Electric SQL](https://electric-sql.com/), a
## Walkthrough
-