A graph, not a chain
Declare needs/provides; green-tea topologically sorts it. No ordering bugs, no positional guesswork — each route runs only its slice of the graph.
Most frameworks make you keep the whole request in your head: which middleware ran, whether req.user exists by now, what fired in what order. green-tea puts the request on the page — you declare what each step needs and produces, and the framework computes the order, type-checks the wiring, and can print the whole thing.
A graph, not a chain
Declare needs/provides; green-tea topologically sorts it. No ordering bugs, no positional guesswork — each route runs only its slice of the graph.
The type is the contract
In the typed flow core, a handler that reads ctx.user fails to compile if no step produces user. “It was undefined in prod” disappears at build time.
See the request before it runs
app.explain('/users/:id') prints the ordered chain; GET /__graph__ renders it as a live diagram. Onboarding and audits are reading, not archaeology.
One primitive for real-time
Declare @Sse, @Stream, or @Ws and return an AsyncIterable — the transport streams it (SSE, ndjson, or a WebSocket duplex) with backpressure and cleanup handled. No separate gateway.
Runs wherever JS runs
Node, Deno, Bun, and the edge — the same app, you only swap the entry point. HTTP, SSE, and WebSocket behave identically on all four.