Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions docs/content/docs/learn/concepts/orchestration-drivers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ The same workflow code works across all drivers. Only the client initialization

## Available Drivers

### Inngest Driver

Production-grade orchestration on the Inngest platform. Handles event-driven triggers, observability, retries, and deployment at scale. **Recommended for production.**

```typescript
import { InngestClient } from "@stepkit/inngest";

const client = new InngestClient({ id: "my-app" });
```

**Use for:** Production deployments, event-driven workflows, team collaboration

[Inngest Driver Guide →](/docs/learn/driver-guides/inngest-driver)

### In-Memory Driver

Runs workflows entirely in memory with no persistence. Perfect for **testing and development** when you need fast iteration without files or databases.
Expand Down Expand Up @@ -40,24 +54,10 @@ const client = new FileSystemClient({ baseDir: "./.stepkit" });

[Filesystem Driver Guide →](/docs/learn/driver-guides/filesystem-driver)

### Inngest Driver

Production-grade orchestration on the Inngest platform. Handles event-driven triggers, observability, retries, and deployment at scale. **Recommended for production.**

```typescript
import { Client } from "@stepkit/inngest";

const client = new Client({ id: "my-app" });
```

**Use for:** Production deployments, event-driven workflows, team collaboration

[Inngest Driver Guide →](/docs/learn/driver-guides/inngest-driver)

## Choosing a driver

- **Building and testing?** Start with In-Memory or Filesystem
- **Deploying to production?** Use Inngest
- **Getting started?** Use Inngest for the best development experience and production deployment
- **Building and testing?** In-Memory or Filesystem work great for local iteration
- **Need event triggers or long-running workflows?** Use Inngest

The driver is just infrastructure. Your workflow code stays the same.
5 changes: 2 additions & 3 deletions docs/content/docs/learn/driver-guides/file-system-driver.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,5 @@ client.stop();

## Related

- [In-Memory Driver](/docs/learn/driver-guides/in-memory-driver) - For testing without persistence
- [Inngest Driver](/docs/learn/driver-guides/inngest-driver) - For production deployments

- [Inngest Driver](/docs/learn/driver-guides/inngest-driver) - For local development with observability and production deployments
- [In-Memory Driver](/docs/learn/driver-guides/in-memory-driver) - For CLI tools and automated testing
2 changes: 1 addition & 1 deletion docs/content/docs/learn/driver-guides/in-memory-driver.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: In-Memory Driver

The In-Memory driver runs workflows in memory. No persistence. When the process stops, workflow state disappears.

<Callout>Best for: Testing, development, and rapid prototyping.</Callout>
<Callout>Best for: CLI tools, automated testing, and environments where you don't need observability or a UI.</Callout>

## Installation

Expand Down
133 changes: 73 additions & 60 deletions docs/content/docs/learn/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ This guide will walk you through getting started with StepKit to build and deplo

## Installation

Install StepKit's core package along with a driver. For this guide, we'll use the [in-memory driver](/docs/learn/driver-guides/in-memory-driver), which is perfect for development and testing.
Install the StepKit Inngest driver. The Inngest driver gives you the best local development experience with built-in observability through the Inngest Dev Server.

```bash tab="npm"
npm install @stepkit/core @stepkit/local
npm install @stepkit/inngest inngest
```

```bash tab="pnpm"
pnpm add @stepkit/core @stepkit/local
pnpm add @stepkit/inngest inngest
```

```bash tab="bun"
bun add @stepkit/core @stepkit/local
bun add @stepkit/inngest inngest
```

```bash tab="yarn"
yarn add @stepkit/core @stepkit/local
yarn add @stepkit/inngest inngest
```

---
Expand All @@ -36,9 +36,11 @@ yarn add @stepkit/core @stepkit/local
Create a file to initialize your StepKit client, which will be used to create workflows.

```typescript title="client.ts"
import { InMemoryClient } from "@stepkit/local";
import { InngestClient } from "@stepkit/inngest";

export const client = new InMemoryClient();
export const client = new InngestClient({
id: "my-app",
});
```

---
Expand Down Expand Up @@ -72,47 +74,47 @@ export const processOrder = client.workflow(
async ({ input }, step) => {
// Step 1: Reserve inventory
const inventory = await step.run("reserve-inventory", async () => {
console.log(`Reserving items: ${ctx.input.items.join(", ")}`);
console.log(`Reserving items: ${input.data.items.join(", ")}`);

// Simulate inventory check
const available = ctx.input.items.every(() => Math.random() > 0.1);
const available = input.data.items.every(() => Math.random() > 0.1);

if (!available) {
throw new Error("Item out of stock - will retry");
}

return { reserved: true, items: ctx.input.items };
return { reserved: true, items: input.data.items };
});

// Step 2: Process payment
const payment = await step.run("process-payment", async () => {
console.log(`Processing payment of $${ctx.input.amount}`);
console.log(`Processing payment of $${input.data.amount}`);

// Simulate payment processing
const paymentId = crypto.randomUUID();

return {
id: paymentId,
amount: ctx.input.amount,
amount: input.data.amount,
status: "completed",
};
});

// Step 3: Wait 30 seconds before confirmation
// This doesn't consume any resources while waiting!
await step.sleep("wait-before-confirm", 30000);
await step.sleep("wait-before-confirm", 7000);

// Step 4: Send confirmation email
await step.run("send-confirmation", async () => {
console.log(`Sending order confirmation to ${ctx.input.email}`);
console.log(`Order ${ctx.input.orderId} completed!`);
console.log(`Sending order confirmation to ${input.data.email}`);
console.log(`Order ${input.data.orderId} completed!`);

return { emailSent: true };
});

// Return the final result
return {
orderId: ctx.input.orderId,
orderId: input.data.orderId,
paymentId: payment.id,
status: "completed",
items: inventory.items,
Expand Down Expand Up @@ -140,76 +142,87 @@ export const processOrder = client.workflow(
Now let's invoke the workflow. Create a file to test it:

```typescript title="main.ts"
import express from "express";
import { serve } from "inngest/express";
import { inngestify } from "@stepkit/inngest";
import { client } from "./client";
import { processOrder } from "./workflows/process-order";

async function main() {
console.log("Starting order processing workflow...\n");
const app = express();
app.use(express.json());

const result = await client.startWorkflow(processOrder, {
orderId: "ORDER-123",
items: ["laptop", "mouse", "keyboard"],
email: "[email protected]",
amount: 1299.99,
});
// Mount Inngest endpoint
app.use("/api/inngest", serve(inngestify(client, [processOrder])));

console.log("\n✅ Workflow completed!");
console.log("Result:", result);
}
const PORT = 3000;

void main();
app.listen(PORT, () => {
console.log(`🚀 Server running on http://localhost:${PORT}`);
console.log(`🔍 Inngest endpoint at http://localhost:${PORT}/api/inngest`);
});
```

Run it with:
---

## Run the Inngest Dev Server

The Inngest Dev Server provides a local UI for testing, debugging, and observing your workflows.

In one terminal, start your server:

```bash
npx tsx main.ts
# or if using Node.js directly
node --loader ts-node/esm main.ts
```

You'll see each step execute in sequence, with a 30-second pause before the confirmation step.
In a second terminal, start the Inngest Dev Server by running:

---
```bash
npx inngest-cli@latest dev -u http://localhost:3000/api/inngest
```

## Using in Your Application
Open [http://localhost:8288](http://localhost:8288) to see the Dev Server UI.

StepKit workflows can also be integrated into your application's back-end (ex: API):
---

### API Endpoint (Express)
## Testing with the Inngest Dev Server

```typescript title="routes/orders.ts"
import express from "express";
import { client } from "./client";
import { processOrder } from "./workflows/process-order";
<video controls autoPlay loop muted src="/content/docs/learn/StepKitDevServer.mp4" />

const app = express();
In the Inngest Dev Server:

app.post("/api/orders", async (req, res) => {
// Start the workflow asynchronously
const result = await client.startWorkflow(processOrder, req.body);

res.json({
message: "Order processing started",
orderId: result.orderId,
});
});
1. Click on the "Functions" tab
2. On the `process-order` function, click the "Invoke" button
3. Enter the test data

```json
{
"data": {
"orderId": "ORDER-123",
"items": ["laptop", "mouse", "keyboard"],
"email": "[email protected]",
"amount": 1299.99
}
}
```

4. Click "Invoke Function". You will be navigated to the "Runs" page and you will see your workflow running.

You'll see:
- Each step execution in real-time
- Step results and outputs
- Timing information
- Retry history if steps fail

---

## Next Steps

Now that you've built your first workflow, explore more concepts:
Now that you've built your first workflow, explore more:

- **Learn**: Dive deeper into [Concepts](/docs/learn/concepts/steps) to understand workflows, steps, and orchestration
- **Drivers**: Explore different [Driver Guides](/docs/learn/driver-guides/in-memory) for your deployment needs
{/* - **Patterns**: Check out common patterns like parallel execution, long-running workflows, and event handling */}

{/* **Key Takeaways**:
- ✅ Workflows are durable and resume from checkpoints
- ✅ Steps are atomic and automatically retry on failure
- ✅ State is persisted between steps
- ✅ Sleep without consuming resources
- ✅ Deploy anywhere your code runs */}
- **Deploy**: Check out the [Inngest Driver Guide](/docs/learn/driver-guides/inngest-driver) for deployment options
- **Examples**: See [real-world examples](/docs/learn/examples/ai-rag-workflow) of AI workflows and more

<Callout type="info">
**For testing and CLI tools**: If you're building CLI applications or need simple testing, check out the [local drivers](/docs/learn/driver-guides/in-memory-driver) (In-Memory and Filesystem).
</Callout>
Binary file not shown.
4 changes: 2 additions & 2 deletions docs/src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export function Header({ activeItem }: HeaderProps) {
<span>Blog</span>
</a>

<a href="#" class="h-full border-t-4 border-white pt-2 flex items-center justify-end text-right space-x-2 hover:opacity-70">
<svg class="w-2 h-2 fill-white" viewBox="0 0 10 10"><rect width="10" height="10" /></svg>
<a href="#" className="h-full border-t-4 border-white pt-2 flex items-center justify-end text-right space-x-2 hover:opacity-70">
<svg className="w-2 h-2 fill-white" viewBox="0 0 10 10"><rect width="10" height="10" /></svg>
<span>About</span>
</a>
*/}
Expand Down
10 changes: 5 additions & 5 deletions docs/src/components/icon-extensible.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ interface IconProps {
export function ExtensibleIcon({ className }: IconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="159" fill="none" viewBox="0 0 138 159">
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="M.441 42.049v77.112l68.218 38.556 68.218-38.556V41.068L69.64.516z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m47.488 68.516 20.978 13 21.022-13" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="M17.973 51.575v57.293l50.684 28.647 50.685-28.647V50.847l-49.956-30.13zM68.441 81.516v22" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="M47.54 68.61v23.936l21.175 11.969 21.176-11.969V68.305L69.019 55.717z" />
<path stroke="#000" stroke-dasharray="2 2" d="M69.441 20.516v35M68.441 104.016v33.5M89.941 92.016l29 16.5M47.941 69.016l-29.5-17.5M47.441 93.016l-29 15.5M89.441 68.516l29.5-15" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="M.441 42.049v77.112l68.218 38.556 68.218-38.556V41.068L69.64.516z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m47.488 68.516 20.978 13 21.022-13" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="M17.973 51.575v57.293l50.684 28.647 50.685-28.647V50.847l-49.956-30.13zM68.441 81.516v22" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="M47.54 68.61v23.936l21.175 11.969 21.176-11.969V68.305L69.019 55.717z" />
<path stroke="#000" strokeDasharray="2 2" d="M69.441 20.516v35M68.441 104.016v33.5M89.941 92.016l29 16.5M47.941 69.016l-29.5-17.5M47.441 93.016l-29 15.5M89.441 68.516l29.5-15" />
</svg>
);
}
2 changes: 1 addition & 1 deletion docs/src/components/icon-platform-language.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface PlatformLanguageIconProps {
export function PlatformLanguageIcon({ className }: PlatformLanguageIconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="160" fill="none" viewBox="0 0 138 160">
<g stroke="#242424" stroke-miterlimit="10" stroke-width=".884" clipPath="url(#a)">
<g stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" clipPath="url(#a)">
<path d="M51.602 10.995v19.472l17.217 9.731 17.227-9.731v-19.72L69.076.514z" />
<path d="m51.602 10.996 17.217 9.987 17.227-10.235M68.82 20.983V40.2M51.602 70.39v19.472l17.217 9.732 17.227-9.732V70.143l-16.97-10.235z" />
<path d="m51.602 70.391 17.217 9.988 17.227-10.235M68.82 80.379v19.215M51.602 129.539v19.463l17.217 9.731 17.227-9.731v-19.71l-16.97-10.235z" />
Expand Down
18 changes: 9 additions & 9 deletions docs/src/components/icon-refactoring.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ interface IconProps {
export function RefactoringIcon({ className }: IconProps) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="169" height="140" fill="none" viewBox="0 0 169 140">
<path stroke="#000" stroke-dasharray="2 2" d="M115.5 71.516H143c14.083 0 25.5 11.416 25.5 25.5s-11.417 25.5-25.5 25.5h-8.5" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="M100.5 109.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m100.5 109.998 17.218 9.979 17.217-10.226M117.719 119.977v19.215M31.5 109.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m31.5 109.998 17.218 9.979 17.217-10.226M48.719 119.977v19.215M65.934 109.998v19.463l17.217 9.731 17.218-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m65.934 109.998 17.217 9.979 17.218-10.226M83.152 119.977v19.215M46.5 59.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m46.5 59.999 17.218 9.978 17.217-10.226M63.719 69.977v19.215M80.934 59.998v19.463l17.217 9.731 17.218-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m80.934 59.999 17.217 9.978 17.218-10.226M98.152 69.977v19.215M62.836 10.998v19.463l17.218 9.731 17.217-9.731v-19.71L80.301.516z" />
<path stroke="#242424" stroke-miterlimit="10" stroke-width=".884" d="m62.836 10.998 17.218 9.978L97.27 10.75M80.055 20.977v19.215" />
<path stroke="#000" stroke-dasharray="2 2" d="M46.5 71.516H26c-14.083 0-25.5-11.417-25.5-25.5s11.417-25.5 25.5-25.5h37.5" />
<path stroke="#000" strokeDasharray="2 2" d="M115.5 71.516H143c14.083 0 25.5 11.416 25.5 25.5s-11.417 25.5-25.5 25.5h-8.5" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="M100.5 109.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m100.5 109.998 17.218 9.979 17.217-10.226M117.719 119.977v19.215M31.5 109.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m31.5 109.998 17.218 9.979 17.217-10.226M48.719 119.977v19.215M65.934 109.998v19.463l17.217 9.731 17.218-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m65.934 109.998 17.217 9.979 17.218-10.226M83.152 119.977v19.215M46.5 59.998v19.463l17.218 9.731 17.217-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m46.5 59.999 17.218 9.978 17.217-10.226M63.719 69.977v19.215M80.934 59.998v19.463l17.217 9.731 17.218-9.731v-19.71l-16.97-10.235z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m80.934 59.999 17.217 9.978 17.218-10.226M98.152 69.977v19.215M62.836 10.998v19.463l17.218 9.731 17.217-9.731v-19.71L80.301.516z" />
<path stroke="#242424" strokeMiterlimit="10" strokeWidth=".884" d="m62.836 10.998 17.218 9.978L97.27 10.75M80.055 20.977v19.215" />
<path stroke="#000" strokeDasharray="2 2" d="M46.5 71.516H26c-14.083 0-25.5-11.417-25.5-25.5s11.417-25.5 25.5-25.5h37.5" />
</svg>
);
}
4 changes: 2 additions & 2 deletions docs/src/components/section-rule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { HomeLayout } from 'fumadocs-ui/layouts/home';

export function SectionRule({ name, className = "", border = true }) {
return (
<div className={`max-w-[1400px] mx-auto my-0 ${className}`}>
<div className={`max-w-fd-container-[1400px] mx-auto my-0 ${className}`}>
{border ? (

<div className="relative border-t-[1.5px] border-t-[#242424] py-6">
<div aria-hidden="true" className="absolute top-[0px] left-0 h-[3px] w-[18%] bg-[#242424]" />
<div aria-hidden="true" className="absolute top-0 left-0 h-[3px] w-[18%] bg-[#242424]" />
<Content name={name} />
</div>
) : (
Expand Down
Loading