Skip to content

Project Structure

AwaitStep is a pnpm monorepo. Top-level directories:

awaitstep/
├── apps/
│   ├── api/          ← Hono API server (Cloudflare Worker or Node.js)
│   ├── web/          ← React SPA (Vite + React Router)
│   └── docs/         ← VitePress documentation site
├── packages/
│   ├── ir/           ← Workflow IR types, schema, validation, expression parser
│   ├── codegen/      ← Code generator interface and utilities
│   ├── provider-cloudflare/ ← Cloudflare Workflows code generator + deploy logic
│   ├── db/           ← Drizzle ORM schema and migrations
│   ├── email/        ← Email sending (magic link, notifications)
│   └── node-cli/     ← CLI tool for creating and validating custom nodes
├── nodes/            ← Built-in and community node definitions
├── tooling/
│   ├── tsconfig/     ← Shared TypeScript configs
│   └── eslint/       ← Shared ESLint configs
└── plan/             ← Implementation plans and architecture docs

apps/api

The API server is built with Hono and runs on both Cloudflare Workers and Node.js. Entry points:

FilePurpose
src/index.tsApp factory — creates the Hono app, registers all routes
src/entry/serve.tsNode.js entry — reads env vars, creates DB connection, starts the server
src/entry/dev.tsDevelopment entry point with hot reload
src/routes/Route handlers (one file per resource group)
src/middleware/Auth, rate limiting, error handling

Route files are thin — they call methods on the provider interface and return responses.

apps/web

The React SPA. Key directories:

PathPurpose
src/routes/TanStack Router file-based routes
src/components/Domain-specific components (canvas, config drawers, run detail)
src/stores/Zustand stores
src/lib/Utilities, API clients, type helpers

packages/ir

The IR package defines the Workflow IR types and all logic that operates on them:

FilePurpose
src/types.tsWorkflowIR, WorkflowNode, Edge, TriggerConfig types
src/schema.tsZod validation schema
src/validate.tsSemantic validation (cycle detection, expression checks)
src/expressions.tsExpression parser and resolver ({{nodeId.path}})
src/node-definition.tsNodeDefinition, ConfigField, OutputField types
src/bundled-nodes/Built-in node definitions (http_request, etc.)

packages/codegen

Defines the WorkflowProvider interface and shared utilities (variable naming, indentation, sanitisation). Provider packages implement this interface.

packages/provider-cloudflare

Generates TypeScript from a WorkflowIR for the Cloudflare Workflows runtime:

PathPurpose
src/codegen/generate.tsTop-level code generator entry point
src/codegen/generators/One file per node type
src/codegen/bindings.tsAuto-detects Cloudflare resource bindings
src/api.tsCloudflare REST API client (deploy, trigger, run control)

packages/db

Drizzle ORM schema and migrations. Never import the DB client directly in app code — it is injected via the app factory.

nodes/

Each subdirectory is a node definition:

nodes/
├── stripe_charge/
│   ├── node.json
│   ├── README.md
│   ├── templates/
│   │   └── cloudflare.ts
│   └── tests/
│       └── cloudflare.test.ts
└── resend_send_email/
    └── ...

See Adding Nodes for how to create a new node.

Dependency rules

Packages must not have circular dependencies. The allowed dependency flow is:

ir → codegen → provider-cloudflare
db  (standalone)
email (standalone)

App code (apps/api, apps/web) may import from any package. Packages must not import from apps.