diff --git a/.cursor/rules/writing-tasks.mdc b/.cursor/rules/writing-tasks.mdc index 5116d083e23..359ed5d4733 100644 --- a/.cursor/rules/writing-tasks.mdc +++ b/.cursor/rules/writing-tasks.mdc @@ -14,7 +14,7 @@ alwaysApply: false ## Essential requirements when generating task code -1. You MUST use `@trigger.dev/sdk/v3` +1. You MUST import from `@trigger.dev/sdk` (NEVER `@trigger.dev/sdk/v3`) 2. You MUST NEVER use `client.defineJob` 3. YOU MUST `export` every task, including subtasks 4. If you are able to generate an example payload for a task, do so. @@ -53,7 +53,7 @@ Instead, you MUST ALWAYS generate ONLY this pattern: ```ts // ✅ ALWAYS GENERATE THIS EXACT PATTERN -import { task } from "@trigger.dev/sdk/v3"; +import { task } from "@trigger.dev/sdk"; //1. You need to export each task, even if it's a subtask export const helloWorld = task({ @@ -71,7 +71,7 @@ export const helloWorld = task({ A task is a function that can run for a long time with resilience to failure: ```ts -import { task } from "@trigger.dev/sdk/v3"; +import { task } from "@trigger.dev/sdk"; export const helloWorld = task({ id: "hello-world", @@ -271,7 +271,7 @@ Global lifecycle hooks can also be defined in `trigger.config.ts` to apply to al ## Correct Schedules task (cron) implementations ```ts -import { schedules } from "@trigger.dev/sdk/v3"; +import { schedules } from "@trigger.dev/sdk"; export const firstScheduledTask = schedules.task({ id: "first-scheduled-task", @@ -312,7 +312,7 @@ export const firstScheduledTask = schedules.task({ ### Attach a Declarative schedule ```ts -import { schedules } from "@trigger.dev/sdk/v3"; +import { schedules } from "@trigger.dev/sdk"; // Sepcify a cron pattern (UTC) export const firstScheduledTask = schedules.task({ @@ -326,7 +326,7 @@ export const firstScheduledTask = schedules.task({ ``` ```ts -import { schedules } from "@trigger.dev/sdk/v3"; +import { schedules } from "@trigger.dev/sdk"; // Specify a specific timezone like this: export const secondScheduledTask = schedules.task({ @@ -375,7 +375,7 @@ const createdSchedule = await schedules.create({ Schema tasks validate payloads against a schema before execution: ```ts -import { schemaTask } from "@trigger.dev/sdk/v3"; +import { schemaTask } from "@trigger.dev/sdk"; import { z } from "zod"; const myTask = schemaTask({ @@ -400,7 +400,7 @@ When you trigger a task from your backend code, you need to set the `TRIGGER_SEC Triggers a single run of a task with specified payload and options without importing the task. Use type-only imports for full type checking. ```ts -import { tasks } from "@trigger.dev/sdk/v3"; +import { tasks } from "@trigger.dev/sdk"; import type { emailSequence } from "~/trigger/emails"; export async function POST(request: Request) { @@ -418,7 +418,7 @@ export async function POST(request: Request) { Triggers multiple runs of a single task with different payloads without importing the task. ```ts -import { tasks } from "@trigger.dev/sdk/v3"; +import { tasks } from "@trigger.dev/sdk"; import type { emailSequence } from "~/trigger/emails"; export async function POST(request: Request) { @@ -436,7 +436,7 @@ export async function POST(request: Request) { Triggers multiple runs of different tasks at once, useful when you need to execute multiple tasks simultaneously. ```ts -import { batch } from "@trigger.dev/sdk/v3"; +import { batch } from "@trigger.dev/sdk"; import type { myTask1, myTask2 } from "~/trigger/myTasks"; export async function POST(request: Request) { @@ -621,7 +621,7 @@ const handle = await myTask.trigger( Access metadata inside a run: ```ts -import { task, metadata } from "@trigger.dev/sdk/v3"; +import { task, metadata } from "@trigger.dev/sdk"; export const myTask = task({ id: "my-task", @@ -713,7 +713,7 @@ Trigger.dev Realtime enables subscribing to runs for real-time updates on run st Subscribe to a run after triggering a task: ```ts -import { runs, tasks } from "@trigger.dev/sdk/v3"; +import { runs, tasks } from "@trigger.dev/sdk"; async function myBackend() { const handle = await tasks.trigger("my-task", { some: "data" }); @@ -735,7 +735,7 @@ async function myBackend() { You can infer types of run's payload and output by passing the task type: ```ts -import { runs } from "@trigger.dev/sdk/v3"; +import { runs } from "@trigger.dev/sdk"; import type { myTask } from "./trigger/my-task"; for await (const run of runs.subscribeToRun(handle.id)) { @@ -752,7 +752,7 @@ for await (const run of runs.subscribeToRun(handle.id)) { Stream data in realtime from inside your tasks using the metadata system: ```ts -import { task, metadata } from "@trigger.dev/sdk/v3"; +import { task, metadata } from "@trigger.dev/sdk"; import OpenAI from "openai"; export type STREAMS = { @@ -947,7 +947,7 @@ For most use cases, Realtime hooks are preferred over SWR hooks with polling due For client-side usage, generate a public access token with appropriate scopes: ```ts -import { auth } from "@trigger.dev/sdk/v3"; +import { auth } from "@trigger.dev/sdk"; const publicToken = await auth.createPublicToken({ scopes: { @@ -967,7 +967,7 @@ Idempotency ensures that an operation produces the same result when called multi Provide an `idempotencyKey` when triggering a task to ensure it runs only once with that key: ```ts -import { idempotencyKeys, task } from "@trigger.dev/sdk/v3"; +import { idempotencyKeys, task } from "@trigger.dev/sdk"; export const myTask = task({ id: "my-task", @@ -1058,7 +1058,7 @@ function hash(payload: any): string { ```ts // onFailure executes after all retries are exhausted; use for notifications, logging, or side effects on final failure: -import { task, logger } from "@trigger.dev/sdk/v3"; +import { task, logger } from "@trigger.dev/sdk"; export const loggingExample = task({ id: "logging-example", @@ -1078,7 +1078,7 @@ export const loggingExample = task({ The `trigger.config.ts` file configures your Trigger.dev project, specifying task locations, retry settings, telemetry, and build options. ```ts -import { defineConfig } from "@trigger.dev/sdk/v3"; +import { defineConfig } from "@trigger.dev/sdk"; export default defineConfig({ project: "", @@ -1226,7 +1226,7 @@ await myTask.trigger({ name: "Alice", age: 30 }); Before generating any code, you MUST verify: -1. Are you importing from `@trigger.dev/sdk/v3`? If not, STOP and FIX. +1. Are you importing from `@trigger.dev/sdk` (NOT `@trigger.dev/sdk/v3`)? If not, STOP and FIX. 2. Have you exported every task? If not, STOP and FIX. 3. Have you generated any DEPRECATED code patterns? If yes, STOP and FIX. diff --git a/docs/docs.json b/docs/docs.json index 14d728e2db1..779b5d53fb5 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -137,7 +137,7 @@ "realtime/run-object", "realtime/auth", { - "group": "React hooks (frontend)", + "group": "React hooks", "pages": [ "realtime/react-hooks/overview", "realtime/react-hooks/triggering", @@ -642,6 +642,10 @@ "source": "/trigger-config", "destination": "/config/config-file" }, + { + "source": "/guides/frameworks", + "destination": "/guides/frameworks/nextjs" + }, { "source": "/guides/frameworks/introduction", "destination": "/guides/introduction" diff --git a/docs/errors-retrying.mdx b/docs/errors-retrying.mdx index 246db2b82af..ae6c4403f4d 100644 --- a/docs/errors-retrying.mdx +++ b/docs/errors-retrying.mdx @@ -12,6 +12,8 @@ You can configure retrying in two ways: 1. In your [trigger.config file](/config/config-file) you can set the default retrying behavior for all tasks. 2. On each task you can set the retrying behavior. +Task-level retry settings override the defaults in your `trigger.config` file. + By default when you create your project using the CLI init command we disabled retrying in the DEV environment. You can enable it in your [trigger.config file](/config/config-file). diff --git a/docs/guides/frameworks/nextjs.mdx b/docs/guides/frameworks/nextjs.mdx index d8b35cbe649..5b91a85bea9 100644 --- a/docs/guides/frameworks/nextjs.mdx +++ b/docs/guides/frameworks/nextjs.mdx @@ -45,7 +45,7 @@ For more information on authenticating with Trigger.dev, see the [API keys page] ## Triggering your task in Next.js -Here are the steps to trigger your task in the Next.js App and Pages router and Server Actions. Alternatively, check out this repo for a [full working example](https://github.com/triggerdotdev/example-projects/tree/main/nextjs/server-actions/my-app) of a Next.js app with a Trigger.dev task triggered using a Server Action. +Here are the steps to trigger your task in the Next.js App and Pages router and Server Actions. @@ -432,5 +432,18 @@ You can test your revalidation task in the Trigger.dev dashboard on the testing +## Realtime updates with React hooks + +The `@trigger.dev/react-hooks` package lets you subscribe to task runs from your React components. Show progress bars, stream AI responses, or display run status in real time. + + + + Hooks for subscribing to runs, streaming data, and triggering tasks from the frontend. + + + Pipe continuous data (like AI completions) from your tasks to the client while they run. + + + diff --git a/docs/guides/frameworks/remix.mdx b/docs/guides/frameworks/remix.mdx index d8fdb3450af..fdab31524c5 100644 --- a/docs/guides/frameworks/remix.mdx +++ b/docs/guides/frameworks/remix.mdx @@ -197,6 +197,19 @@ The `vercel-build` script in `package.json` is specific to Remix projects on Ver The `runtime: "edge"` configuration in the API route allows for better performance on Vercel's Edge Network. +## Realtime updates with React hooks + +The `@trigger.dev/react-hooks` package lets you subscribe to task runs from your React components. Show progress bars, stream AI responses, or display run status in real time. + + + + Hooks for subscribing to runs, streaming data, and triggering tasks from the frontend. + + + Pipe continuous data (like AI completions) from your tasks to the client while they run. + + + ## Additional resources for Remix + +```text +Help me add Trigger.dev to this project. + +## What to do + +1. I need a Trigger.dev account. If I don't have one, point me to https://cloud.trigger.dev to sign up. Wait for me to confirm. +2. Run `npx trigger.dev@latest init` in the project root. + - When it asks about the MCP server, recommend I install it (best DX: gives you direct access to Trigger.dev docs, deploys, and run monitoring). + - Install the "Hello World" example task when prompted. +3. Run `npx trigger.dev@latest dev` to start the dev server. +4. Once the dev server is running, test the example task from the Trigger.dev dashboard. +5. Set TRIGGER_SECRET_KEY in my .env file (or .env.local for Next.js). I can find it on the API Keys page in the dashboard. +6. Ask me what framework I'm using and show me how to trigger the task from my backend code. + +If I've already run init and want the MCP server, run: npx trigger.dev@latest install-mcp + +## Critical rules + +- ALWAYS import from `@trigger.dev/sdk`. NEVER import from `@trigger.dev/sdk/v3`. +- NEVER use `client.defineJob()` — that's the deprecated v2 API. +- Use type-only imports when triggering from backend code to avoid bundling task code: + + import type { myTask } from "./trigger/example"; + import { tasks } from "@trigger.dev/sdk"; + + const handle = await tasks.trigger("hello-world", { message: "Hello from my app!" }); + +## When done, point me to + +- Writing tasks: https://trigger.dev/docs/tasks/overview +- Real-time updates: https://trigger.dev/docs/realtime/overview +- AI tooling: https://trigger.dev/docs/building-with-ai +``` + + + +## Manual setup @@ -26,20 +68,30 @@ Sign up at [Trigger.dev Cloud](https://cloud.trigger.dev) (or [self-host](/open- +## Triggering tasks from your app + +The test page in the dashboard is great for verifying your task works. To trigger tasks from your own code, you'll need to set the `TRIGGER_SECRET_KEY` environment variable. Grab it from the API Keys page in the dashboard and add it to your `.env` file. + +```bash .env +TRIGGER_SECRET_KEY=tr_dev_... +``` + +See [Triggering](/triggering) for the full guide, or jump straight to framework-specific setup for [Next.js](/guides/frameworks/nextjs), [Remix](/guides/frameworks/remix), or [Node.js](/guides/frameworks/nodejs). + ## Next steps - Learn how to build Trigger.dev projects using AI coding assistants + Build Trigger.dev projects using AI coding assistants - Learn how to trigger tasks from your code. + Trigger tasks from your backend code - Tasks are the core of Trigger.dev. Learn what they are and how to write them. + Task options, lifecycle hooks, retries, and queues - Guides and examples for triggering tasks from your code. + Framework guides and working example repos diff --git a/docs/realtime/auth.mdx b/docs/realtime/auth.mdx index 80634b82a8a..025060c688b 100644 --- a/docs/realtime/auth.mdx +++ b/docs/realtime/auth.mdx @@ -141,6 +141,10 @@ By default, auto-generated tokens expire after 15 minutes and have a read scope See our [triggering documentation](/triggering) for detailed examples of how to trigger tasks and get auto-generated tokens. + +**Where should I create tokens?** The standard pattern is to create tokens in your backend code (API route, server action) after triggering a task, then pass the token to your frontend. The `handle.publicAccessToken` returned by `tasks.trigger()` already does this for you. You rarely need to create tokens inside a task itself. + + ### Subscribing to runs with Public Access Tokens Once you have a Public Access Token, you can use it to authenticate requests to the Realtime API in both backend and frontend applications. diff --git a/docs/realtime/backend/overview.mdx b/docs/realtime/backend/overview.mdx index 7adb30bfa0e..6bf81a20aeb 100644 --- a/docs/realtime/backend/overview.mdx +++ b/docs/realtime/backend/overview.mdx @@ -1,23 +1,22 @@ --- -title: Backend overview +title: "Subscribe to tasks from your backend" sidebarTitle: Overview -description: Using the Trigger.dev realtime API from your backend code +description: "Subscribe to run progress, stream AI output, and react to task status changes from your backend code or other tasks." --- import RealtimeExamplesCards from "/snippets/realtime-examples-cards.mdx"; -Use these backend functions to subscribe to runs and streams from your server-side code or other tasks. +**Subscribe to runs from your server-side code or other tasks using async iterators.** Get status updates, metadata changes, and streamed data without polling. -## Overview +## What's available -There are three main categories of functionality: - -- **[Subscribe functions](/realtime/backend/subscribe)** - Subscribe to run updates using async iterators -- **[Metadata](/realtime/backend/subscribe#subscribe-to-metadata-updates-from-your-tasks)** - Update and subscribe to run metadata in real-time -- **[Streams](/realtime/backend/streams)** - Read and consume real-time streaming data from your tasks +| Category | What it does | Guide | +|---|---|---| +| **Run updates** | Subscribe to run status, metadata, and tag changes | [Run updates](/realtime/backend/subscribe) | +| **Streaming** | Read AI output, file chunks, or any continuous data from tasks | [Streaming](/realtime/backend/streams) | - To learn how to emit streams from your tasks, see our [Realtime Streams](/tasks/streams) documentation. + To learn how to emit streams from your tasks, see [Streaming data from tasks](/tasks/streams). ## Authentication diff --git a/docs/realtime/backend/streams.mdx b/docs/realtime/backend/streams.mdx index 11c21bd2f4d..8a273ea5a9f 100644 --- a/docs/realtime/backend/streams.mdx +++ b/docs/realtime/backend/streams.mdx @@ -1,13 +1,13 @@ --- -title: Streams -sidebarTitle: Streams -description: Read and consume real-time streaming data from your tasks in your backend +title: "Stream data to your backend (AI, files)" +sidebarTitle: "Streaming" +description: "Read AI/LLM output, file chunks, and other streaming data from your Trigger.dev tasks in backend code." --- -The Streams API allows you to read streaming data from your Trigger.dev tasks in your backend code. This is particularly useful for consuming AI/LLM outputs, progress updates, or any other real-time data that your tasks emit. +**Read streaming data from your tasks in backend code.** Consume AI completions as they generate, process file chunks, or handle any continuous data your tasks produce. - To learn how to emit streams from your tasks, see our [Realtime Streams](/tasks/streams) documentation. For frontend applications using React, see our [React hooks streams documentation](/realtime/react-hooks/streams). + To emit streams from your tasks, see [Streaming data from tasks](/tasks/streams). For React components, see [Streaming in React](/realtime/react-hooks/streams). ## Reading streams diff --git a/docs/realtime/backend/subscribe.mdx b/docs/realtime/backend/subscribe.mdx index ffa46532bf6..6148ffee6f8 100644 --- a/docs/realtime/backend/subscribe.mdx +++ b/docs/realtime/backend/subscribe.mdx @@ -1,10 +1,10 @@ --- -title: Subscribe functions -sidebarTitle: Subscribe -description: Subscribe to run updates using async iterators +title: "Run updates (backend)" +sidebarTitle: "Run updates" +description: "Subscribe to run status changes, metadata updates, and tag changes from your backend code using async iterators." --- -These functions allow you to subscribe to run updates from your backend code. Each function returns an async iterator that yields run objects as they change. +**Subscribe to runs from your backend and get updates whenever status, metadata, or tags change.** Each function returns an async iterator that yields the run object on every change. ## runs.subscribeToRun diff --git a/docs/realtime/how-it-works.mdx b/docs/realtime/how-it-works.mdx index 04dd13dadad..c26a90f1f82 100644 --- a/docs/realtime/how-it-works.mdx +++ b/docs/realtime/how-it-works.mdx @@ -1,12 +1,14 @@ --- -title: How it works -sidebarTitle: How it works -description: Technical details about how the Trigger.dev Realtime API works +title: "How Realtime works" +sidebarTitle: "How it works" +description: "Technical architecture behind Trigger.dev's real-time run updates, built on Electric SQL and PostgreSQL syncing." --- +This page covers the infrastructure behind **run updates** (status, metadata, tags). [Streaming](/tasks/streams) uses a separate transport. + ## Architecture -The Realtime API is built on top of [Electric SQL](https://electric-sql.com/), an open-source PostgreSQL syncing engine. The Trigger.dev API wraps Electric SQL and provides a simple API to subscribe to [runs](/runs) and get real-time updates. +The run updates system is built on top of [Electric SQL](https://electric-sql.com/), an open-source PostgreSQL syncing engine. The Trigger.dev API wraps Electric SQL and provides a simple API to subscribe to [runs](/runs) and get updates as they happen. ## Run changes diff --git a/docs/realtime/overview.mdx b/docs/realtime/overview.mdx index 8819c4003f8..94cd48c5b82 100644 --- a/docs/realtime/overview.mdx +++ b/docs/realtime/overview.mdx @@ -1,39 +1,63 @@ --- title: Realtime overview sidebarTitle: Overview -description: Using the Trigger.dev Realtime API to trigger and/or subscribe to runs in real-time. +description: "Get live run updates and stream data from background tasks to your frontend or backend. No polling." --- -Trigger.dev Realtime allows you to trigger, subscribe to, and get real-time updates for runs. This is useful for monitoring runs, updating UIs, and building real-time dashboards. +**Realtime is the umbrella for everything live in Trigger.dev.** It covers two things: getting notified when a run's state changes, and streaming continuous data (like AI tokens) from a running task to your app. -You can subscribe to real-time updates for different scopes of runs: +Both use the same `@trigger.dev/react-hooks` package and the same authentication system. The difference is what they give you. -- **Specific runs** - Monitor individual run progress by run ID -- **Runs with specific tags** - Track all runs that have certain [tags](/tags) (e.g., all runs tagged with `user:123`) -- **Batch runs** - All runs within a specific batch -- **Trigger + subscribe combos** - Trigger a task and immediately subscribe to its run (frontend only) +## Run updates vs Streaming -Once subscribed, you'll receive the complete [run object](/realtime/run-object) with automatic real-time updates whenever the [run changes](/realtime/how-it-works#run-changes), including: +| | Run updates | Streaming | +|---|---|---| +| **What you get** | Run state: status, metadata, tags | Continuous data you define (AI tokens, file chunks, progress) | +| **When it fires** | On state changes | While the task runs, as data is produced | +| **Use case** | Progress bars, status badges, dashboards | AI chat output, live logs, file processing | +| **React hook** | [`useRealtimeRun`](/realtime/react-hooks/subscribe) | [`useRealtimeStream`](/realtime/react-hooks/streams) | +| **Setup in task code?** | No, automatic | Yes, using `streams.define()` | +| **Infrastructure** | [Electric SQL](/realtime/how-it-works) (PostgreSQL sync) | Streams transport | -- **Status changes** - queued → executing → completed, etc. -- **Metadata updates** - Custom progress tracking, status updates, user data, etc. ([React hooks](/realtime/react-hooks/subscribe#using-metadata-to-show-progress-in-your-ui) | [backend](/realtime/backend/subscribe#subscribe-to-metadata-updates-from-your-tasks)) -- **Tag changes** - When [tags](/tags) are added or removed from the run -- **Realtime Streams** - Stream real-time data from your tasks, perfect for AI/LLM outputs and progress updates. ([Learn more](/tasks/streams) | [React hooks](/realtime/react-hooks/streams) | [Backend](/realtime/backend/streams)) +You can use both at the same time. Subscribe to a run's status (to show a progress bar) while also streaming AI output (to display tokens as they arrive). -## Using Realtime in your applications +## Run updates -### Authentication +Subscribe to a run and your code gets called whenever its status, [metadata](/runs/metadata), or [tags](/tags) change. No setup needed in your task code. -All Realtime subscriptions require authentication so you can securely trigger and subscribe to runs. See our [authentication guide](/realtime/auth) for more details. +You can subscribe to: -### Frontend implementation +- **Specific runs** by run ID +- **Runs with specific tags** (e.g., all runs tagged with `user:123`) +- **Batch runs** within a specific batch +- **Trigger + subscribe combos** that trigger a task and immediately subscribe (frontend only) -Use our React hooks to build real-time UIs that update as runs execute. Ideal for progress bars, status indicators, and live dashboards. +→ [React hooks](/realtime/react-hooks/subscribe) | [Backend](/realtime/backend/subscribe) -→ **[See our React hooks guide](/realtime/react-hooks/)** +## Streaming -### Backend implementation +Define typed streams in your task, pipe data to them, and read that data from your frontend or backend as it's produced. You need to set up streams in your task code using `streams.define()`. -Use our server-side SDK to subscribe to runs from your backend code, other tasks, or serverless functions. Perfect for triggering workflows, sending notifications, or updating databases based on run status changes. +→ [How to emit streams from tasks](/tasks/streams) | [React hooks](/realtime/react-hooks/streams) | [Backend](/realtime/backend/streams) -→ **[See our Backend guide](/realtime/backend)** +## Authentication + +All Realtime hooks and functions require authentication. See the [authentication guide](/realtime/auth) for setup. + +## Frequently asked questions + +### How do I show a progress bar for a background task? + +Use [run metadata](/runs/metadata) to store progress data (like a percentage), then subscribe to the run with [`useRealtimeRun`](/realtime/react-hooks/subscribe). Your component re-renders on every metadata update. + +### How do I stream AI/LLM responses from a background task? + +Define a stream in your task with `streams.define()`, pipe your AI SDK response to it, then consume it in React with [`useRealtimeStream`](/realtime/react-hooks/streams). See [Streaming data from tasks](/tasks/streams) for the full guide. + +### Do I need WebSockets or polling? + +No. Run updates are powered by [Electric SQL](/realtime/how-it-works) (HTTP-based PostgreSQL syncing). Streams use their own transport. The hooks handle connections automatically. + +### Can I use both run updates and streaming together? + +Yes. A common pattern: subscribe to run status with `useRealtimeRun` (progress indicator) while streaming AI output with `useRealtimeStream` (token-by-token display). diff --git a/docs/realtime/react-hooks/overview.mdx b/docs/realtime/react-hooks/overview.mdx index 7cf84c63f04..6edf74ff46c 100644 --- a/docs/realtime/react-hooks/overview.mdx +++ b/docs/realtime/react-hooks/overview.mdx @@ -1,12 +1,12 @@ --- -title: React hooks overview +title: "React hooks for real-time task updates" sidebarTitle: Overview -description: Using the Trigger.dev Realtime API from your React applications. +description: "Subscribe to background task progress, stream AI responses, and trigger tasks from React components using @trigger.dev/react-hooks." --- import RealtimeExamplesCards from "/snippets/realtime-examples-cards.mdx"; -Our React hooks package provides a set of hooks that make it easy to interact with the Trigger.dev Realtime API from your React applications. You can use these hooks to subscribe to real-time updates, and trigger tasks from your frontend. +**`@trigger.dev/react-hooks` gives your React components live access to background tasks.** Subscribe to run progress, stream AI output as it generates, or trigger tasks directly from the browser. ## Installation @@ -55,19 +55,19 @@ Learn more about [generating and managing tokens in our authentication guide](/r ## Available hooks -We provide several categories of hooks: - -- **[Triggering hooks](/realtime/react-hooks/triggering)** - Trigger tasks from your frontend application -- **[Subscribe hooks](/realtime/react-hooks/subscribe)** - Subscribe to runs, batches, metadata, and more -- **[Streams hooks](/realtime/react-hooks/streams)** - Subscribe to real-time streams from your tasks -- **[SWR hooks](/realtime/react-hooks/swr)** - Fetch data once and cache it using SWR +| Hook category | What it does | Guide | +|---|---|---| +| **Trigger hooks** | Trigger tasks from the browser | [Triggering](/realtime/react-hooks/triggering) | +| **Run updates** | Subscribe to run status, metadata, and tags | [Run updates](/realtime/react-hooks/subscribe) | +| **Streaming** | Consume AI output, file chunks, or any continuous data | [Streaming](/realtime/react-hooks/streams) | +| **SWR hooks** | One-time fetch with caching (not recommended for most cases) | [SWR](/realtime/react-hooks/swr) | ## SWR vs Realtime hooks -We offer two "styles" of hooks: SWR and Realtime. The SWR hooks use the [swr](https://swr.vercel.app/) library to fetch data once and cache it. The Realtime hooks use [Trigger.dev Realtime](/realtime) to subscribe to updates in real-time. +We offer two "styles" of hooks: SWR and Realtime. SWR hooks use the [swr](https://swr.vercel.app/) library to fetch data once and cache it. Realtime hooks use [Trigger.dev Realtime](/realtime) to subscribe to updates as they happen. It can be a little confusing which one to use because [swr](https://swr.vercel.app/) can also be configured to poll for updates. But because of rate-limits and the way the Trigger.dev API works, - we recommend using the Realtime hooks for most use-cases. + we recommend using the Realtime hooks for most use cases. diff --git a/docs/realtime/react-hooks/streams.mdx b/docs/realtime/react-hooks/streams.mdx index f5c1ab0679e..c3c7031d44a 100644 --- a/docs/realtime/react-hooks/streams.mdx +++ b/docs/realtime/react-hooks/streams.mdx @@ -1,14 +1,13 @@ --- -title: Streams hooks -sidebarTitle: Streams -description: Subscribe to real-time streams from your tasks in React components +title: "Stream data to React (AI, files, progress)" +sidebarTitle: "Streaming" +description: "Display AI/LLM output token by token, stream file chunks, or pipe any continuous data from a background task into your React components." --- -These hooks allow you to consume real-time streams from your tasks. Streams are useful for displaying AI/LLM outputs as they're generated, or any other real-time data from your tasks. +**Display AI responses as they generate, stream file processing results, or pipe any continuous data from a running task into your React components.** Unlike [progress and status hooks](/realtime/react-hooks/subscribe) (which track run state), streaming hooks give you the raw data your task produces while it runs. - To learn how to emit streams from your tasks, see our [Realtime Streams](/tasks/streams) - documentation. + To learn how to emit streams from your tasks, see [Streaming data from tasks](/tasks/streams). ## useRealtimeStream (Recommended) @@ -151,7 +150,7 @@ const { parts, error } = useRealtimeStream(runId, { }); ``` -For more information on defining and using streams, see the [Realtime Streams](/tasks/streams) documentation. +For more information on defining and using streams, see the [Streaming data from tasks](/tasks/streams) documentation. ## useInputStreamSend @@ -430,3 +429,21 @@ export function MyComponent({ All other options (accessToken, baseURL, enabled, id) work the same as the other realtime hooks. For the newer `useRealtimeStream` hook, use the `throttleInMs` option instead (see [options above](#options)). + +## Frequently asked questions + +### How do I stream AI/LLM responses from a background task to React? + +Define a typed stream in your task with `streams.define()`, pipe your AI SDK response to it with `.pipe()`, then consume it in your component with `useRealtimeStream`. See [Streaming data from tasks](/tasks/streams) for the task-side setup. + +### What's the difference between streaming and run updates? + +[Run updates](/realtime/react-hooks/subscribe) track **run state** (status, metadata, tags). Streaming (this page) pipes **continuous data** your task produces. Use run updates for progress bars and status badges. Use streaming for AI chat output, live logs, or file processing results. You can use both at the same time. + +### Can I send data back into a running task from React? + +Yes. Use the `useInputStreamSend` hook to send data into a running task's input stream. This is useful for cancel buttons, user approvals, or any interactive flow. See [Input Streams](/tasks/streams#input-streams) for the full guide. + +### Do streams work with the Vercel AI SDK? + +Yes. You can pipe a Vercel AI SDK `streamText` response directly into a Trigger.dev stream using `.pipe()`. The [Streaming data from tasks](/tasks/streams) page has a complete AI streaming example. diff --git a/docs/realtime/react-hooks/subscribe.mdx b/docs/realtime/react-hooks/subscribe.mdx index 41ef2b61f85..84f0e8f6cde 100644 --- a/docs/realtime/react-hooks/subscribe.mdx +++ b/docs/realtime/react-hooks/subscribe.mdx @@ -1,21 +1,21 @@ --- -title: Subscribing to runs -sidebarTitle: Subscribe -description: Get live updates from runs, batches, metadata, and more in your frontend application. +title: "Run updates in React" +sidebarTitle: "Run updates" +description: "Build progress bars, status indicators, and live dashboards by subscribing to background task updates from React components." --- -These hooks allow you to subscribe to runs, batches, and streams using [Trigger.dev Realtime](/realtime). They automatically include real-time updates for run status, metadata, output, and other properties. +**Subscribe to a run and your component re-renders whenever its status, metadata, or tags change.** Build progress bars, deployment monitors, or any UI that needs to reflect what a background task is doing right now. -## Hooks +For streaming continuous data (AI tokens, file chunks), see [Streaming](/realtime/react-hooks/streams) instead. -## Triggering + Realtime hooks +## Trigger + subscribe combo hooks -For triggering tasks and immediately subscribing to their runs, we provide combo hooks, details on how to use them can be found in the [triggering](/realtime/react-hooks/triggering) section. +Trigger a task and immediately subscribe to its run. Details in the [triggering](/realtime/react-hooks/triggering) section. - **[`useRealtimeTaskTrigger`](/realtime/react-hooks/triggering#userealtimetasktrigger)** - Trigger a task and subscribe to the run - **[`useRealtimeTaskTriggerWithStreams`](/realtime/react-hooks/triggering#userealtimetasktriggerwithstreams)** - Trigger a task and subscribe to both run updates and streams -## Other Realtime subscription hooks +## Subscribe hooks ### useRealtimeRun @@ -654,3 +654,21 @@ export function MyComponent({ ``` This allows you to change the ID of the subscription based on some state. Passing in a different ID will unsubscribe from the current subscription and subscribe to the new one (and remove any cached data). + +## Frequently asked questions + +### How do I show a progress bar for a background task in React? + +Use `metadata.set()` inside your task to update a progress value, then read it with `useRealtimeRun` in your component. The hook re-renders your component on every metadata change. See [Using metadata to show progress](#using-metadata-to-show-progress-in-your-ui) above for a complete example. + +### What's the difference between run updates and streaming? + +Run updates (this page) give you **run state**: status, metadata, and tags. They're for progress bars, status badges, and dashboards. [Streaming](/realtime/react-hooks/streams) gives you **continuous data** like AI tokens or file chunks. Use run updates for "how far along is my task?" and streaming for "show me the output as it generates." + +### Can I subscribe to multiple runs at once? + +Yes. Use `useRealtimeRunsWithTag` to subscribe to all runs with a specific tag (e.g., `user:123`), or `useRealtimeBatch` for all runs in a batch. Each yields an array of run objects that update in real time. + +### Do I need to set up polling or WebSockets? + +No. The hooks handle the connection automatically using Trigger.dev's Realtime infrastructure (built on [Electric SQL](/realtime/how-it-works)). Just pass a run ID and an access token. diff --git a/docs/realtime/react-hooks/triggering.mdx b/docs/realtime/react-hooks/triggering.mdx index 50320ccd48f..6801adb8e67 100644 --- a/docs/realtime/react-hooks/triggering.mdx +++ b/docs/realtime/react-hooks/triggering.mdx @@ -1,10 +1,10 @@ --- -title: Trigger hooks +title: "Trigger tasks from React" sidebarTitle: Triggering -description: Triggering tasks from your frontend application. +description: "Trigger background tasks from React components and optionally subscribe to their progress or stream their output." --- -We provide a set of hooks that can be used to trigger tasks from your frontend application. +Trigger tasks directly from your React components. You can fire-and-forget, or trigger and immediately subscribe to the run's progress or streamed output. For triggering tasks from your frontend, you need to use “trigger” tokens. These can only be used diff --git a/docs/runs/metadata.mdx b/docs/runs/metadata.mdx index d0dff36758c..4e6f01369c7 100644 --- a/docs/runs/metadata.mdx +++ b/docs/runs/metadata.mdx @@ -1,10 +1,12 @@ --- title: "Run metadata" sidebarTitle: "Metadata" -description: "Attach a small amount of data to a run and update it as the run progresses." +description: "Attach structured data to a run and update it as the task progresses. Use metadata for progress tracking, user context, intermediate results, and more." --- -You can attach up to 256KB of metadata to a run, which you can then access from inside the run function, via the API, Realtime, and in the dashboard. You can use metadata to store additional, structured information on a run. For example, you could store your user’s full name and corresponding unique identifier from your system on every task that is associated with that user. Or you could store the progress of a long-running task, or intermediate results that you want to access later. +**Metadata lets you attach up to 256KB of structured data to a run and update it while the task runs.** Subscribers (via [React hooks](/realtime/react-hooks/subscribe) or [backend](/realtime/backend/subscribe)) get those updates in real time, making metadata the simplest way to build progress bars, status indicators, and live dashboards. + +You can access metadata from inside the run function, via the API, Realtime, and in the dashboard. Common uses: progress percentage, current step, user context, intermediate results. ## Usage diff --git a/docs/tasks/overview.mdx b/docs/tasks/overview.mdx index b2bca9bc1e1..c7705dc4867 100644 --- a/docs/tasks/overview.mdx +++ b/docs/tasks/overview.mdx @@ -64,7 +64,7 @@ Anything you return from the `run` function will be the result of the task. Data ### `retry` options -A task is retried if an error is thrown, by default we retry 3 times. +A task is retried if an error is thrown. By default, we retry 3 times. You can set the number of retries and the delay between retries in the `retry` field: @@ -84,6 +84,16 @@ export const taskWithRetries = task({ }); ``` +| Option | What it does | +|---|---| +| `maxAttempts` | Total number of attempts (including the first). Default: 3 | +| `factor` | Exponential backoff multiplier. Each retry delay = previous delay x factor. With `factor: 1.8` and `minTimeoutInMs: 500`, retries wait 500ms, 900ms, 1620ms, etc. | +| `minTimeoutInMs` | Delay before the first retry | +| `maxTimeoutInMs` | Cap on the delay between retries | +| `randomize` | Add jitter to retry delays to prevent multiple failing tasks from retrying in lockstep | + +Task-level retry settings override the defaults in your `trigger.config` file. + For more information read [the retrying guide](/errors-retrying). It's also worth mentioning that you can [retry a block of code](/errors-retrying) inside your tasks as well. @@ -145,7 +155,7 @@ You can register global lifecycle hooks that are executed for all runs, regardle ```ts import { tasks } from "@trigger.dev/sdk"; -tasks.onStart(({ ctx, payload, task }) => { +tasks.onStartAttempt(({ ctx, payload, task }) => { console.log("Run started", ctx.run); }); @@ -160,12 +170,12 @@ tasks.onFailure(({ ctx, error }) => { ### `init.ts` -If you create a `init.ts` file at the root of your trigger directory, it will be automatically loaded when a task is executed. This is useful if you want to register global lifecycle hooks, or initialize a database connection, etc. +If you create an `init.ts` file at the root of your trigger directory, it will be automatically loaded when a task is executed. This is useful for registering global lifecycle hooks, initializing a database connection, etc. ```ts init.ts import { tasks } from "@trigger.dev/sdk"; -tasks.onStart(({ ctx, payload, task }) => { +tasks.onStartAttempt(({ ctx, payload, task }) => { console.log("Run started", ctx.run); }); ``` diff --git a/docs/tasks/streams.mdx b/docs/tasks/streams.mdx index a54d03fab23..c8cec9dc5a0 100644 --- a/docs/tasks/streams.mdx +++ b/docs/tasks/streams.mdx @@ -1,10 +1,12 @@ --- -title: "Realtime Streams" +title: "Streaming data from tasks" sidebarTitle: "Streams" -description: "Stream data in realtime from your Trigger.dev tasks to your frontend or backend applications." +description: "Pipe continuous data from your Trigger.dev tasks to frontend or backend clients in real time. Stream AI completions, file chunks, progress updates, and more." --- -Realtime Streams allow you to pipe streaming data from your Trigger.dev tasks to your frontend or backend applications in real-time. This is perfect for use cases like streaming AI completions, progress updates, or any continuous data flow. You can also **send data into** running tasks with [Input Streams](#input-streams) for bidirectional flows (e.g. cancel buttons, approvals). +**Streams let you pipe data from a running task to your frontend or backend as it's produced.** Think AI completions token by token, progress updates, or file chunks. You can also **send data into** running tasks with [Input Streams](#input-streams) for bidirectional flows (cancel buttons, approvals). + +For subscribing to **run state changes** (status, metadata, tags) instead, see [Realtime](/realtime/overview). Streams require SDK version **4.1.0 or later** (`@trigger.dev/sdk` and `@trigger.dev/react-hooks`). @@ -14,7 +16,7 @@ Realtime Streams allow you to pipe streaming data from your Trigger.dev tasks to ## Overview -Realtime Streams provide: +Streams provide: - **Unlimited stream length** (previously capped at 2000 chunks) - **Unlimited active streams per run** (previously 5) diff --git a/docs/triggering.mdx b/docs/triggering.mdx index a30b5b33ade..ad746012f88 100644 --- a/docs/triggering.mdx +++ b/docs/triggering.mdx @@ -29,6 +29,10 @@ Trigger tasks **from inside a another task**: When you trigger a task from your backend code, you need to set the `TRIGGER_SECRET_KEY` environment variable. If you're [using a preview branch](/deployment/preview-branches), you also need to set the `TRIGGER_PREVIEW_BRANCH` environment variable. You can find the value on the API keys page in the Trigger.dev dashboard. [More info on API keys](/apikeys). + +**Which trigger pattern should I use?** If your triggering code can import the task definition (same codebase), use `yourTask.trigger()` for full type safety. Use `tasks.trigger()` with a type-only import when the task runs in a separate service or you need to avoid bundling task code into your app (common in Next.js). Both do the same thing at runtime. + + If you are using Next.js Server Actions [you'll need to be careful with bundling](/guides/frameworks/nextjs#triggering-your-task-in-next-js).