docs/manual-setup.mdx
This guide covers how to manually set up Trigger.dev in your project, including configuration for different package managers, monorepos, and build extensions. This guide replicates all the steps performed by the trigger.dev init command. Follow our Quickstart for a more streamlined setup.
Before setting up your project, you need to authenticate the CLI with Trigger.dev:
# Login to Trigger.dev
npx trigger.dev@latest login
# Or with a specific API URL (for self-hosted instances)
npx trigger.dev@latest login --api-url https://your-trigger-instance.com
This will open your browser to authenticate. Once authenticated, you'll need to select or create a project in the Trigger.dev dashboard to get your project reference (e.g., proj_abc123).
Install the required packages based on your package manager:
<CodeGroup>npm add @trigger.dev/sdk@latest
npm add --save-dev @trigger.dev/build@latest
pnpm add @trigger.dev/sdk@latest
pnpm add -D @trigger.dev/build@latest
yarn add @trigger.dev/sdk@latest
yarn add -D @trigger.dev/build@latest
bun add @trigger.dev/sdk@latest
bun add -D @trigger.dev/build@latest
For local development, you need to set up the TRIGGER_SECRET_KEY environment variable. This key authenticates your application with Trigger.dev.
TRIGGER_SECRET_KEY=tr_dev_xxxxxxxxxx
If you're using a self-hosted Trigger.dev instance, also set:
TRIGGER_API_URL=https://your-trigger-instance.com
You can run the Trigger.dev CLI in two ways:
# npm
npx trigger.dev@latest dev
# pnpm
pnpm dlx trigger.dev@latest dev
# yarn
yarn dlx trigger.dev@latest dev
Add the CLI to your package.json:
{
"devDependencies": {
"trigger.dev": "^4.0.0"
}
}
Then add scripts to your package.json:
{
"scripts": {
"dev:trigger": "trigger dev",
"deploy:trigger": "trigger deploy"
}
}
Make sure to pin the version of the CLI to the same version as the SDK that you are using:
"devDependencies": {
"trigger.dev": "^4.0.0",
"@trigger.dev/build": "^4.0.0"
},
"dependencies": {
"@trigger.dev/sdk": "^4.0.0"
}
While running the CLI dev or deploy commands, the CLI will automatically detect mismatched versions and warn you.
Create a trigger.config.ts file in your project root (or trigger.config.mjs for JavaScript projects):
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
// Your project ref from the Trigger.dev dashboard
project: "<your-project-ref>", // e.g., "proj_abc123"
// Directories containing your tasks
dirs: ["./src/trigger"], // Customize based on your project structure
// Retry configuration
retries: {
enabledInDev: false, // Enable retries in development
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
randomize: true,
},
},
// Build configuration (optional)
build: {
extensions: [], // Build extensions go here
},
// Max duration of a task in seconds
maxDuration: 3600,
});
By default, Trigger.dev will use the Node.js runtime. If you're using Bun, you can specify the runtime:
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
project: "<your-project-ref>",
runtime: "bun",
dirs: ["./src/trigger"],
});
See our Bun runtime documentation for more information.
Create a trigger directory (matching the dirs in your config) and add an example task:
import { task } from "@trigger.dev/sdk";
export const helloWorld = task({
id: "hello-world",
run: async (payload: { name: string }) => {
console.log(`Hello ${payload.name}!`);
return {
message: `Hello ${payload.name}!`,
timestamp: new Date().toISOString(),
};
},
});
See our Tasks docs for more information on how to create tasks.
If you're using TypeScript, add trigger.config.ts to your tsconfig.json include array:
{
"compilerOptions": {
// ... your existing options
},
"include": [
// ... your existing includes
"trigger.config.ts"
]
}
Add .trigger to your .gitignore file to exclude Trigger.dev's local development files:
# Trigger.dev
.trigger
If you don't have a .gitignore file, create one with this content.
If you're building a React frontend application and want to display task status in real-time, install the React hooks package:
# npm
npm install @trigger.dev/react-hooks@latest
# pnpm
pnpm add @trigger.dev/react-hooks@latest
# yarn
yarn add @trigger.dev/react-hooks@latest
# bun
bun add @trigger.dev/react-hooks@latest
import { auth } from "@trigger.dev/sdk";
// In your backend API
export async function getPublicAccessToken() {
const publicAccessToken = await auth.createPublicToken({
scopes: ["read:runs"], // Customize based on needs
});
return publicAccessToken;
}
import { useRealtimeRun } from "@trigger.dev/react-hooks";
export function TaskStatus({
runId,
publicAccessToken,
}: {
runId: string;
publicAccessToken: string;
}) {
const { run, error } = useRealtimeRun(runId, {
accessToken: publicAccessToken,
});
if (error) return <div>Error: {error.message}</div>;
if (!run) return <div>Loading...</div>;
return (
<div>
<p>Status: {run.status}</p>
<p>Progress: {run.completedAt ? "Complete" : "Running..."}</p>
</div>
);
}
For more information, see the React Hooks documentation.
Build extensions allow you to customize the build process. Ensure you have the @trigger.dev/build package installed in your project (see package installation).
Now you can use any of the built-in extensions:
import { defineConfig } from "@trigger.dev/sdk";
import { prismaExtension } from "@trigger.dev/build/extensions/prisma";
export default defineConfig({
project: "<project-ref>",
build: {
extensions: [
prismaExtension({
mode: "legacy",
schema: "prisma/schema.prisma",
migrate: true, // Run migrations on deploy
}),
],
},
});
See our Build extensions docs for more information on how to use build extensions and the available extensions.
There are two main approaches for setting up Trigger.dev in a monorepo:
Both approaches work well depending on your needs. Use the tasks package approach if you want to share tasks across multiple applications, or the app-based approach if tasks are specific to individual apps.
This approach creates a dedicated tasks package that can be consumed by multiple apps in your monorepo.
Root package.json:
{
"name": "my-monorepo",
"private": true,
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint"
},
"devDependencies": {
"turbo": "^2.4.4",
"typescript": "5.8.2"
},
"packageManager": "[email protected]"
}
pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
turbo.json:
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^lint"]
}
}
}
packages/tasks/package.json:
{
"name": "@repo/tasks",
"version": "0.0.0",
"dependencies": {
"@trigger.dev/sdk": "^4.0.0"
},
"devDependencies": {
"@trigger.dev/build": "^4.0.0"
},
"exports": {
".": "./src/trigger/index.ts",
"./trigger": "./src/index.ts"
}
}
packages/tasks/trigger.config.ts:
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
project: "<your-project-ref>", // Replace with your project reference
dirs: ["./src/trigger"],
retries: {
enabledInDev: true,
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
randomize: true,
},
},
maxDuration: 3600,
});
packages/tasks/src/index.ts:
export * from "@trigger.dev/sdk"; // Export values and types from the Trigger.dev sdk
packages/tasks/src/trigger/index.ts:
// Export tasks
export * from "./example";
packages/tasks/src/trigger/example.ts:
import { task } from "@trigger.dev/sdk";
export const helloWorld = task({
id: "hello-world",
run: async (payload: { name: string }) => {
console.log(`Hello ${payload.name}!`);
return {
message: `Hello ${payload.name}!`,
timestamp: new Date().toISOString(),
};
},
});
See our turborepo-prisma-tasks-package example for a more complete example.
apps/web/package.json:
{
"name": "web",
"dependencies": {
"@repo/tasks": "workspace:*",
"next": "^15.2.1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}
apps/web/app/api/actions.ts:
"use server";
import { tasks } from "@repo/tasks/trigger";
import type { helloWorld } from "@repo/tasks";
// 👆 type only import
export async function triggerHelloWorld(name: string) {
try {
const handle = await tasks.trigger<typeof helloWorld>("hello-world", {
name: name,
});
return handle.id;
} catch (error) {
console.error(error);
return { error: "something went wrong" };
}
}
Run the development server for the tasks package:
# From the root of your monorepo
cd packages/tasks
npx trigger.dev@latest dev
# Or using turbo (if you add dev:trigger script to tasks package.json)
turbo run dev:trigger --filter=@repo/tasks
This approach installs Trigger.dev directly in individual apps that need background tasks.
apps/web/package.json:
{
"name": "web",
"dependencies": {
"@trigger.dev/sdk": "^4.0.0",
"next": "^15.2.1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@trigger.dev/build": "^4.0.0"
}
}
apps/web/trigger.config.ts:
import { defineConfig } from "@trigger.dev/sdk";
export default defineConfig({
project: "<your-project-ref>", // Replace with your project reference
dirs: ["./src/trigger"],
retries: {
enabledInDev: true,
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
randomize: true,
},
},
maxDuration: 3600,
});
apps/web/src/trigger/example.ts:
import { task } from "@trigger.dev/sdk";
export const helloWorld = task({
id: "hello-world",
run: async (payload: { name: string }) => {
console.log(`Hello ${payload.name}!`);
return {
message: `Hello ${payload.name}!`,
timestamp: new Date().toISOString(),
};
},
});
apps/web/app/api/actions.ts:
"use server";
import { tasks } from "@trigger.dev/sdk";
import type { helloWorld } from "../../src/trigger/example";
// 👆 type only import
export async function triggerHelloWorld(name: string) {
try {
const handle = await tasks.trigger<typeof helloWorld>("hello-world", {
name: name,
});
return handle.id;
} catch (error) {
console.error(error);
return { error: "something went wrong" };
}
}
# From the app directory
cd apps/web
npx trigger.dev@latest dev
# Or from the root using turbo
turbo run dev:trigger --filter=web
You can find a growing list of example projects in our examples section.
If you run into any issues, please check our Troubleshooting page.
If you have any feedback, please let us know by opening an issue.