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.
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.
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:
Persistent callers — a game server, a long-running app. Connect once, then every call is an awaitable send over the same socket.
import aaw from '@ape-egg/async-await-websockets/client.js'; const url = `wss://belt.korte.kim?token=${process.env.BELT_API_KEY}`; const belt = aaw(url); const { files } = await belt.sendAsync( 'svg/iconice/generate', { icons, outputs: ['css'] }, 30_000 );Auth happens once at the upgrade — a bad token is refused before the connection opens.
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.
A bad key never gets this far — it is refused at the upgrade, so the socket simply fails to open.
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.
| Runtime | How |
|---|---|
| Bun, Node, Deno | built-in fetch, or the aaw client over WebSocket |
| Build scripts, CI, agents | curl against the REST surface |
| Browser | call your own backend, and let it call belt |
belt is a pool of network-callable functions. One file per function, addressed by its path — and that path is the URL.
<root>/functions/text/summarize.js
export default async ({ text, tone }, { env }) => {
// the work happens here
return { summary };
};
<root>/server/api/summary.js
<root>/app/summary.js
const response = await fetch('/api/summary', {
method: 'POST',
body: JSON.stringify({ text, tone: 'plain' })
});
const { summary } = await response.json();
Access is by invitation — a key is minted for the sections of the namespace you need. Ask for an invitation.
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.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.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.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.iconSvg from
svg/iconice/parse are used as-is — parse once, generate many times.@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.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.