wrkflw
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Last Updated: November 20, 2025
wrkflw is a TypeScript-first workflow engine for Val Town, inspired by Mastra. It enables building strongly-typed, composable workflows that run on Val Town's serverless platform with SQLite-backed persistence.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Workflow │ │ Execution │ │ SQLite │
│ Builder │───▶│ Engine │───▶│ Storage │
│ (workflow.ts) │ │ (engine.ts) │ │ (storage.ts) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Step │ │ Workflow │ │ API Server │
│ Definition │ │ Run │ │ (Optional) │
│ (step.ts) │ │ (run.ts) │ │ (api-server) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Define reusable workflow steps with Zod schemas
- Strong typing for inputs/outputs
- Access to workflow context (previous results, state)
- Fluent API:
.then(step).then(step).commit() - Automatic type inference through step chains
- Compile-time type checking
- Sequential step execution
- State persistence after each step
- Error handling and result capture
- SQLite-backed workflow snapshots
- Track execution path and step results
- Query runs by workflow ID or status
- HTTP requests (GET, POST)
- Data transformation (map, filter, pick)
- Utilities (delay, logger, template)
- Type Safety: Full TypeScript inference across workflows
- Val Town Native: Works with HTTP, Cron, Email triggers
- Visualization: Mermaid diagrams + React canvas visualizer
- Persistence: ACID-compliant SQLite storage
- Composability: Steps and workflows as reusable modules
When resuming development, start here:
- Run Examples:
deno run --allow-all examples/simple-workflow.ts - Test Types:
deno check backend/index.ts - Visualize:
deno run --allow-all examples/api-server-example-local.ts - Frontend Dev:
cd frontend && npm run dev
# Backend (Deno) deno lint # Lint backend code deno fmt # Format backend code deno check backend/index.ts # Type check # Frontend (Node) cd frontend && npm run dev # Start visualizer cd frontend && npm run build # Build for production # Code Quality npx @biomejs/biome check --write # Fix all issues
backend/ # Core workflow engine (Deno)
├── index.ts # Main exports
├── types.ts # TypeScript definitions
├── step.ts # Step creation
├── workflow.ts # Workflow builder
├── engine.ts # Execution engine
├── storage.ts # SQLite persistence
└── prebuilt-steps.ts # Ready-to-use steps
examples/ # Usage examples
├── simple-workflow.ts
├── http-trigger.ts
└── api-server-example-local.ts
frontend/ # React visualizer (Vite)
└── src/components/ # Canvas workflow viewer
const workflow = createWorkflow({
id: 'my-workflow',
inputSchema: z.object({ data: z.string() }),
outputSchema: z.object({ result: z.string() }),
})
.then(step1)
.then(step2)
.commit();
const run = await workflow.createRun();
const result = await run.start({ inputData: { data: "hello" } });
execute: async ({ inputData, getStepResult }) => {
const previousResult = getStepResult(step1);
return { result: previousResult.value + 1 };
}
- Add New Prebuilt Steps: Extend
backend/prebuilt-steps.ts - Enhance Visualization: Improve React canvas in
frontend/ - Advanced Control Flow: Parallel execution, branching
- Error Recovery: Retry logic, fallback steps
- Performance: Optimize SQLite queries, add indexes
backend/types.ts- Core type definitionsbackend/workflow.ts- Workflow builder implementationbackend/engine.ts- Execution logicexamples/simple-workflow.ts- Basic usage patternAGENTS.md- Development guidelines and commands
Get started with a template: