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.

the image

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.json

Your 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 place

Masks 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:

PropTypeDefault
Editflux3Image

Something 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.

—
Eraseerase

Paint or boxes and nothing said: what's marked is removed, by mask.

—
Expandoutpaint

The canvas from Outpaint Frame, optionally locked to a shape, with an optional prompt.

—

ImageEditStudio

PropTypeDefault
imagestring

The image to edit: a URL, data URL or object URL. A new one starts a new history.

—
clientBflClient

Reaches the BFL API through your server: createBflClient(base), or your own submit and poll.

—
price(request: BflRequest) => number

Your price for one request, in your unit, from its endpoint and body. Omit to show no costs.

—
balancenumber

What the user can spend; edits costing more disable.

—
onSpend(cost: number, request: BflRequest) => void

Called as each request is sent, retries included, with its cost.

—
formatCost(cost: number) => ReactNode

Labels costs, e.g. as money.

formatCredits
defaultTool"edit" | "expand"

The tool it opens on, e.g. "expand" behind a host's Resize action.

"edit"