Local World
The Local World (@workflow/world-local) is a filesystem-based workflow backend designed for local development and testing. It stores workflow data as JSON files on disk and provides in-memory queuing.
The local world is perfect for local development because it:
- Requires no external services or configuration
- Stores data as readable JSON files for easy debugging
- Provides instant feedback during development
- Works seamlessly with Next.js development server
How It Works
Storage
The local world stores all workflow data as JSON files in a configurable directory:
.workflow-data/
├── runs/
│ └── <run-id>.json
├── steps/
│ └── <run-id>/
│ └── <step-id>.json
├── hooks/
│ └── <hook-id>.json
└── streams/
└── <run-id>/
└── <stream-id>.jsonEach file contains the full state of a run, step, hook, or stream, making it easy to inspect workflow data directly.
Queuing
The local world uses an in-memory queue with HTTP transport:
- When a step is enqueued, it's added to an in-memory queue
- The queue processes steps by sending HTTP requests to your development server
- Steps are executed at the
.well-known/workflow/v1/stependpoint
The queue automatically detects your development server's port and adjusts the queue URL accordingly.
Authentication
The local world provides a simple authentication implementation since no authentication is required or enforced in local development.
getAuthHeaders(): Promise<Record<string, string>> {
return Promise.resolve({});
}Configuration
Data Directory
By default, workflow data is stored in .workflow-data/ in your project root. This can be customized through environment variables or programmatically.
Environment variable:
export WORKFLOW_EMBEDDED_DATA_DIR=./custom-workflow-dataProgrammatically:
import { createEmbeddedWorld } from '@workflow/world-local';
const world = createEmbeddedWorld({ dataDir: './custom-workflow-data' });Port
By default, the embedded world automatically detects which port your application is listening on using process introspection. This works seamlessly with frameworks like SvelteKit, Vite, and others that use non-standard ports.
Auto-detection example (recommended):
import { createEmbeddedWorld } from '@workflow/world-local';
// Port is automatically detected - no configuration needed!
const world = createEmbeddedWorld();If auto-detection fails, the world will fall back to the PORT environment variable, then to port 3000.
Manual port override (when needed):
You can override the auto-detected port by specifying it explicitly:
import { createEmbeddedWorld } from '@workflow/world-local';
const world = createEmbeddedWorld({ port: 3000 });Base URL
For advanced use cases like HTTPS or custom hostnames, you can override the entire base URL. When set, this takes precedence over all port detection and configuration.
Use cases:
- HTTPS dev servers (e.g.,
next dev --experimental-https) - Custom hostnames (e.g.,
local.example.com) - Non-localhost development
Environment variable:
export WORKFLOW_EMBEDDED_BASE_URL=https://local.example.com:3000Programmatically:
import { createEmbeddedWorld } from '@workflow/world-local';
// HTTPS
const world = createEmbeddedWorld({
baseUrl: 'https://localhost:3000'
});
// Custom hostname
const world = createEmbeddedWorld({
baseUrl: 'https://local.example.com:3000'
});Usage
Automatic (Recommended)
The local world is used automatically during local development:
# Start your Next.js dev server
npm run dev
# Workflows automatically use local worldManual
You can explicitly set the local world through environment variables:
export WORKFLOW_TARGET_WORLD=local
npm run devDevelopment Workflow
A typical development workflow with local world:
-
Start your dev server:
npm run dev -
Trigger a workflow:
curl -X POST --json '{"email":"test@example.com"}' http://localhost:3000/api/signup -
Inspect the results:
- Use the CLI or Web UI
- Check JSON files in
.workflow-data/ - View development server logs
Inspecting Data
Using Observability Tools
The local world integrates with the Workflow DevKit's observability tools:
# View runs with CLI
npx workflow inspect runs
# View runs with Web UI
npx workflow inspect runs --webLearn more in the Observability section.
Limitations
The local world is designed for development, not production:
- Not scalable - Uses in-memory queuing
- Not persistent - Data is stored in local files
- Single instance - Cannot handle distributed deployments
- No authentication - Suitable only for local development
For production deployments, use the Vercel World.
API Reference
createEmbeddedWorld
Creates a local world instance:
function createEmbeddedWorld(
args?: Partial<{
dataDir: string;
port: number;
baseUrl: string;
}>
): WorldParameters:
-
args- Optional configuration object:-
dataDir- Directory for storing workflow data (default:.workflow-data/orWORKFLOW_EMBEDDED_DATA_DIRenv var) -
port- Port override for queue transport (default: auto-detected →PORTenv var →3000) -
baseUrl- Full base URL override for queue transport (default:http://localhost:{port}orWORKFLOW_EMBEDDED_BASE_URLenv var)
-
Returns:
-
World- A world instance implementing the World interface
Examples:
import { createEmbeddedWorld } from '@workflow/world-local';
// Use all defaults (recommended - auto-detects port)
const world = createEmbeddedWorld();
// Custom data directory
const world = createEmbeddedWorld({ dataDir: './my-data' });
// Override port
const world = createEmbeddedWorld({ port: 3000 });
// HTTPS with custom hostname
const world = createEmbeddedWorld({
baseUrl: 'https://local.example.com:3000'
});
// Multiple options
const world = createEmbeddedWorld({
dataDir: './my-data',
baseUrl: 'https://localhost:3000'
});Learn More
- World Interface - Understanding the World interface
- Vercel World - For production deployments
- Observability - Monitoring and debugging tools