Skip to main content
This guide shows you how to install Workflow DevKit in an Express application using Nitro as the build system.
1

Install dependencies

Install the required packages:
npm install workflow express nitro rollup
npm install -D @types/express
Nitro provides the build system needed to compile workflows. Learn more at nitro.build.
2

Configure Nitro

Create a nitro.config.ts file with the Workflow module:
nitro.config.ts
import { defineNitroConfig } from 'nitro/config';

export default defineNitroConfig({
  modules: ['workflow/nitro'],
  vercel: { entryFormat: 'node' },
  routes: {
    '/**': { handler: './src/index.ts', format: 'node' },
  },
});
This configuration:
  • Enables the Workflow Nitro module
  • Routes all requests to your Express app
  • Uses Node.js format for compatibility with Express
3

Create your Express app

Create src/index.ts with your Express application:
src/index.ts
import express from 'express';
import { start } from 'workflow/api';
import { handleUserSignup } from '../workflows/user-signup.js';

const app = express();
app.use(express.json());

app.post('/api/signup', async (req, res) => {
  const { email } = req.body;
  await start(handleUserSignup, [email]);
  return res.json({ message: "User signup workflow started" });
});

export default app;
4

Update package.json scripts

Add development and build scripts:
package.json
{
  "scripts": {
    "dev": "nitro dev",
    "build": "nitro build",
    "start": "node .output/server/index.mjs"
  }
}
5

Enable TypeScript support (Optional)

Add the Workflow TypeScript plugin to your tsconfig.json for IntelliSense:
tsconfig.json
{
  "compilerOptions": {
    "plugins": [
      {
        "name": "workflow"
      }
    ]
  }
}

How it works

The Express + Nitro integration:
  • Uses Nitro’s build system to compile workflows
  • Generates workflow route handlers at .well-known/workflow/v1/*
  • Supports both development (with HMR) and production builds
  • Routes all non-workflow requests to your Express app
  • Automatically handles workflow execution and resumption

Example workflow

workflows/user-signup.ts
import { sleep } from "workflow";

export async function handleUserSignup(email: string) {
  "use workflow";

  const user = await createUser(email);
  await sendWelcomeEmail(user);
  await sleep("1 day");
  await sendOnboardingEmail(user);

  return { userId: user.id, status: "onboarded" };
}

async function createUser(email: string) {
  "use step";
  console.log(`Creating user with email: ${email}`);
  return { id: crypto.randomUUID(), email };
}

async function sendWelcomeEmail(user: { id: string; email: string }) {
  "use step";
  console.log(`Sending welcome email to user: ${user.id}`);
}

async function sendOnboardingEmail(user: { id: string; email: string }) {
  "use step";
  console.log(`Sending onboarding email to user: ${user.id}`);
}

Development

Run the development server:
npm run dev
Trigger a workflow:
curl -X POST --json '{"email":"[email protected]"}' http://localhost:3000/api/signup

Production

Build and start the production server:
npm run build
npm start

Next steps

Core Concepts

Learn about workflows and steps

Nitro Integration

Learn more about the Nitro integration

Build docs developers (and LLMs) love