Image Edit Studio
Edit one image, version by version: mark it up and say what to change, erase, or expand it, then compare each edit with what it was made from and branch from any version.

Paint over what to change. Tab reaches the marks: arrow keys move one, Enter edits its note, Delete removes it.
Installation
pnpm dlx shadcn@latest add https://mgp.paukraft.com/r/image-edit-studio.jsonYour server
The block never sees your API key. Each edit builds its request and hands it to the client, which posts it to your server:
POST /api/bfl/*endpoint → POST https://api.bfl.ai/v1/{endpoint}
with your x-key header and the body
GET /api/bfl/poll?url= → GET the task's polling_url, after
checking it's on bfl.ai; once Ready,
save result.sample to your storage
and return your URL in its placeMasks and marked-up images go as data URLs, and an object URL image is read into one. Your server may upload them to storage and send BFL the URL instead. Marking up a result reads its pixels, so have your poll route return the result saved to your storage, not BFL's URL.
What an edit sends
There's no inpaint or erase mode to pick. Mark up the image with Markup and say what to change, and the edit follows from what's there:
| Prop | Type | Default |
|---|---|---|
| Edit | flux3ImageSomething said, as a prompt or notes on the marks: FLUX 3 gets the image with the marks drawn in and is told to change only what's marked. Where an area is painted or boxed, the result is laid back only inside it, so every other pixel stays. | — |
| Erase | erasePaint or boxes and nothing said: what's marked is removed, by mask. | — |
| Expand | outpaintThe canvas from Outpaint Frame, optionally locked to a shape, with an optional prompt. | — |
ImageEditStudio
| Prop | Type | Default |
|---|---|---|
| image | stringThe image to edit: a URL, data URL or object URL. A new one starts a new history. | — |
| client | BflClientReaches the BFL API through your server: createBflClient(base), or your own submit and poll. | — |
| price | (request: BflRequest) => numberYour price for one request, in your unit, from its endpoint and body. Omit to show no costs. | — |
| balance | numberWhat the user can spend; edits costing more disable. | — |
| onSpend | (cost: number, request: BflRequest) => voidCalled as each request is sent, retries included, with its cost. | — |
| formatCost | (cost: number) => ReactNodeLabels costs, e.g. as money. | formatCredits |
| defaultTool | "edit" | "expand"The tool it opens on, e.g. "expand" behind a host's Resize action. | "edit" |