belt functions transports errors usage

belt

Function calls over the wire — REST and WebSocket compliant.

Functions

A function is one file under functions/ and its path is its URL, so belt gains a capability by gaining a file — no new endpoint to learn, no client library to upgrade, nothing to version. This is what it serves today, with many more to come. Pick a card for its request and response shape; a green dot means this deployment is serving it right now.

image/gemini/generate 10 Credits A prompt, and optionally reference images, through Gemini.
INa prompt, an aspect ratio, an optional backdrop colour, optional reference images OUTone generated image as base64 PNG
image/strip-backdrop 1 Credit A subject on a flat backdrop, lifted onto transparency.
INan image on a flat backdrop, as base64, and the colour to strip OUTthe subject on transparency, cropped to its bounds
svg/iconice/generate Free Raw SVGs in, a ready-to-ship icon package out.
INan array of named SVGs, and the outputs you want OUTany of seven artifacts — stylesheet, variables, types, JSON model, HTML demo, Svelte and React components
svg/iconice/parse Free Raw SVGs optimized and parsed into Iconice's colour-addressable model.
INan array of named SVGs OUTeach icon optimized, its fills and strokes lifted into CSS variables

One endpoint, two ways to call

Both transports funnel into the same registry, auth and quota. Any function works over either — pick by the shape of the caller, never the function.

REST

One-shot callers — CLI, curl, CI, build scripts, agents. POST /<path> with a JSON body; the function's return value is the response body.

Simple calls also work as GET, with the query string as the body:

WebSocket

Persistent callers — a game server, a long-running app. Connect once, then every call is an awaitable send over the same socket.

Auth happens once at the upgrade — a bad token is refused before the connection opens.

Error handling

Same shape on both transports — a payload carrying error. REST also puts the status on the response; WebSocket puts the error in the reply for that event.

REST

WebSocket

Powered by Aaw

A bad key never gets this far — it is refused at the upgrade, so the socket simply fails to open.

Call belt from a backend

belt is a server-to-server tool. It authenticates with a bearer key that lives in your process environment, and every call is made by your backend on the caller's behalf — a browser reaches belt by reaching your backend first.

RuntimeHow
Bun, Node, Denobuilt-in fetch, or the aaw client over WebSocket
Build scripts, CI, agentscurl against the REST surface
Browsercall your own backend, and let it call belt
@[openFunction]

belt is a pool of network-callable functions. One file per function, addressed by its path — and that path is the URL.

1 — On belt, the function

<root>/functions/text/summarize.js

2 — On your backend, the call to belt

<root>/server/api/summary.js REST WebSocket

3 — In your client, the call to your backend

<root>/app/summary.js

Access is by invitation — a key is minted for the sections of the namespace you need. Ask for an invitation.

Request

Response

backdrop appends one sentence to your prompt, asking for that colour as a single flat fill behind the subject — the setup image/strip-backdrop expects, so the pair takes the same colour. Omit it and the prompt is sent untouched: no backdrop means you want the whole frame, and framing is yours to describe. Generation takes tens of seconds — over WebSocket, pass a timeout to match. Upstream failures come back with Gemini's own status and message.

Request

Response

Pass the same backdrop you gave image/gemini/generate and every pixel near it is cleared wholesale before the fill starts. Omit it and the colour is inferred instead — magenta backdrops still get the wholesale clear on their own. Either way the colour actually blended against is measured, not declared: the median of the border pixels, never a guess from one corner, because a render never lands on the exact hex. After the wholesale clear a flood fill walks inward from the border, stepping only between near-identical neighbours and refusing to cross into shade — so a shadow under the subject stays. Edge pixels are alpha-blended by their distance from that measured colour, and the result is trimmed to the subject's bounds. Two cases return your image byte-for-byte untouched instead of guessing: a border that is already transparent (nothing to strip), and a fill that would keep less than a tenth of the pixels (the subject blends into the backdrop). This one needs sharp, a native module, so it declares runtime: 'bun' and is absent from the edge build — it lives only on the persistent deployment. Everything else runs on both.

Request

Response

Files are keyed by the filename they are meant to be saved as. css is the whole stylesheet — custom properties plus icon[name] selectors, each sized from the SVG's own aspect ratio; variables is the custom properties alone. json is the parsed colour-addressable model, and svelte / react are components that render from it — the files land side by side, so the components import their siblings. Every SVG is optimized (SVGO) before anything is generated. An empty icons array answers 400. Icons that already carry an iconSvg from svg/iconice/parse are used as-is — parse once, generate many times. The icon rules land in @layer context — the layer stylecheat keeps its own icon rules in — so a generated set loaded next to stylecheat is settled by specificity and source order, never by layer. Unlayered or in any later layer, the base icon rule here would beat every icon[name] in stylecheat and turn each into the placeholder.

Request

Response

The model behind Iconice: every fill and stroke in the markup is rewritten to a CSS variable — var(--star-fill-color-0, currentColor) — and the original colours are collected alongside, so an icon renders in context colour by default and in its original colours on demand. svg/iconice/generate accepts these icons as-is.