apps/docs/content/starter-kits/image-pipeline.mdx
To build with an image pipeline starter kit, run this command in your terminal:
npm create tldraw@latest -- --template image-pipeline
The template works out of the box with placeholder images. To connect real AI providers, create a .dev.vars file:
REPLICATE_API_TOKEN=<your key>
Use the Image Pipeline Starter Kit to build:
<StarterKitBento type="image-pipeline" />Nodes are custom tldraw shapes that represent pipeline steps. Each node has typed input and output ports — there are six port data types (image, text, model, number, latent, and any) that enforce connection compatibility. Connections are also shapes, rendered as color-coded bezier curves that use tldraw's binding system to stay attached to specific ports.
Ports are color-coded by data type and enforce compatibility during connection. When you drag a connection, only compatible ports highlight as valid targets. The system also prevents cycles, replaces existing connections on single-input ports, and supports multi-input ports that accept multiple connections.
The execution engine builds a DAG (directed acyclic graph) from your node connections and resolves dependencies automatically. Independent branches execute in parallel. Each node receives its input values, runs its operation, and passes results downstream. Nodes show loading states during execution and cache their results.
The starter kit integrates with AI providers through a Cloudflare Worker backend. The Generate node sends prompts, model selection, and parameters (steps, CFG scale, seed) to the worker, which dispatches to providers like Replicate. When no backend is configured, the system returns placeholder SVGs so you can explore the full UI without API credentials.
Beyond generation, the template includes processing nodes for upscaling, style transfer, ControlNet-guided generation, IP-Adapter reference images, blending, and image adjustments. These can be chained together to build complex multi-step image processing workflows.
To add a custom node type, create a new file in src/nodes/types/. The easiest approach is to duplicate an existing node like AdjustNode.tsx.
Define your node's data shape:
import { T } from 'tldraw'
export const CustomNode = T.object({
type: T.literal('custom'),
// your node's parameters...
})
export type CustomNode = T.TypeOf<typeof CustomNode>
Then create a node definition:
export class CustomNodeDefinition extends NodeDefinition<CustomNode> {
static type = 'custom'
static validator = CustomNode
title = 'My custom node'
icon = <span>🔧</span>
category = 'process'
getDefault() { ... }
getPorts(shape, node) { ... }
async execute(shape, node, inputs) { ... }
getOutputInfo(shape, node, inputs) { ... }
Component = CustomNodeComponent
}
Register your node in src/nodes/nodeTypes.tsx by adding it to NodeDefinitions, and add it to the sidebar in src/components/ImagePipelineSidebar.tsx.
The worker uses a provider abstraction. To add a new provider, create a class implementing the ImageProvider interface in worker/providers/. The provider receives generation parameters and returns image URLs. Register it in the provider resolution logic so it can be selected from the Model node.
The template overrides several tldraw UI components:
To further customize the UI, read up on customizing tldraw's UI as a whole.
If you build something great, please share it with us in our #show-and-tell channel on Discord. We want to see what you've built!