Pixel for your customers
A customer can ask Pixel to change their design in the designer: “write my name in gold”, “make a picture of a fox for the photo”. Pixel changes only what the template offers the customer, within what each field allows, and the change is one step the customer can undo. That includes a photo’s adjustments where the template offers them: “make the photo black and white” sets its tone, and an adjustment the template keeps fixed is not changed, with Pixel saying so.
On a template that lets customers add layers of their own, Pixel can add,
change and remove them too: “add a line saying Happy birthday” adds a text
layer from the template’s preset and writes it. Pixel adds only the kinds
the template allows, and no more of each than its most; a request past
either is refused, as the designer refuses the customer, and Pixel’s reply
says why. It removes only layers the customer (or Pixel) added, never the
template’s own. An answer that adds, removes or changes the customer’s own layers
after the customer added or removed one while Pixel worked is not applied,
and ask() rejects as for any other failure.
Pixel is off until you turn it on for a template, in its Pixel settings
(PUT /v1/templates/by-base/{baseId}/shopper-pixel), where you also choose
what Pixel may do (change fields, which includes adding and removing the
customer’s own layers, generate a picture, cut a picture out of its
background) and how much one designer session may ask.
Each request is paid from your workspace’s credits, within those limits and
your workspace’s monthly ceiling.
In the built-in designer
Section titled “In the built-in designer”There is nothing to set up. For a template with Pixel on, the designer draws
a “Create with AI” button above the form, in Pixonaut.mount() and in your
hosted designer links, in your accent. It opens
a prompt: Enter sends it, Shift+Enter adds a line, Esc closes it. While
Pixel works the customer can cancel, which stops the request and applies
nothing of it; once Pixel has changed the design, Undo takes the change
back. A request that did not work shows one message under the prompt, with
Try again.
The button is drawn only for a template with Pixel on, and only in a
designer that holds a publishable key or a designer link. A designer whose
requests go through your server (transport) offers none: Pixel answers a
customer’s browser, never a server’s secret key.
In your own UI
Section titled “In your own UI”A designer you build yourself has the same
calls under designer.pixel:
| Call | What it does |
|---|---|
available() |
Whether the template shown offers Pixel. Draw your prompt only when it does. |
ask(prompt, { signal }) |
Ask Pixel to change the design. Resolves { reply, changed, cutOuts, layers } once Pixel’s changes are applied as one step: what Pixel says it did, each { layerId, prop } it changed, each picture it is cutting out, and each layer of the customer’s own it added or removed, as { action: 'added' | 'removed', layerId, kind } by the id it had then. All three empty means Pixel changed nothing: show its reply. signal, optional, cancels it (below). |
busy() |
Whether a request is under way. One runs at a time. |
canUndo(), undo() |
Whether there is a step of Pixel’s to take back on the design shown, and take it back: every field it changed returns to what it held before, except one the customer has changed since, and a cut-out it asked that is still running is stopped. A layer of the customer’s own it added is removed, and one it removed comes back at its place with its values, unless the customer has added or removed one since. |
on('pixel') tells your UI how a request stands, whether your code or the
built-in control asked it:
status |
When |
|---|---|
'asking' |
A request was sent. |
'done' |
Its changes are applied; reply, changed, cutOuts and layers as ask() resolves them. |
'failed' |
It did not work. |
'cancelled' |
It was cancelled through its signal. |
'undone' |
undo() took a step back; changed names the fields it restored, and layers the layer changes it took back. |
When Pixel cuts a picture out of its background, the cut-out takes the
picture’s place once it is done, a moment after ask() resolves, as a
customer’s own upload’s cut-out does.
Cancelling a request
Section titled “Cancelling a request”Pass an AbortSignal to cancel a request under way. The request stops, the
api stops Pixel’s work on it, nothing it answered is applied, and ask()
rejects with the signal’s reason (an AbortError, for abort() with
none). on('pixel') hears 'cancelled', never 'failed', and
on('error') hears nothing. A cancelled request is paid for as any is: the
model calls Pixel made before it stopped.
const controller = new AbortController();cancel.addEventListener('click', () => controller.abort());await designer.pixel.ask(prompt.value, { signal: controller.signal });When it does not work
Section titled “When it does not work”Whatever stops a request — Pixel turned off, a session’s limit or the
monthly ceiling reached, your credits run out, the network down — ask()
rejects with a PixelUnavailableError, changes nothing, and on('error')
hears that same error with action: 'pixel'. An ask() refused before it
is sent, while another request is under way or for a template that does not
offer Pixel, rejects with it too, but tells on('pixel') and on('error')
nothing. The error says nothing of why, on purpose:
show your customer one message that it did not work right now. You are told
the reason instead: a limit or your credits running out raises a
notification in the studio.
Example
Section titled “Example”<div id="pixel" hidden> <label for="pixel-prompt">Ask Pixel</label> <input id="pixel-prompt" maxlength="2000" placeholder="Write my name in gold" /> <button id="pixel-ask" type="button">Ask</button> <p id="pixel-status" role="status"></p> <button id="pixel-undo" type="button" hidden>Undo</button></div>const designer = await Pixonaut.mount('#canvas', { publishableKey: 'pk_…', templateId: 'name-sign@3', showForm: false,});
const box = document.querySelector('#pixel');const prompt = document.querySelector('#pixel-prompt');const ask = document.querySelector('#pixel-ask');const status = document.querySelector('#pixel-status');const undo = document.querySelector('#pixel-undo');
box.hidden = !designer.pixel.available();
designer.on('pixel', (event) => { const busy = event.status === 'asking'; prompt.disabled = busy; ask.disabled = busy; undo.hidden = busy || !designer.pixel.canUndo(); if (event.status === 'asking') status.textContent = 'Pixel is working on it…'; if (event.status === 'done') status.textContent = event.reply; if (event.status === 'undone') status.textContent = '';});
ask.addEventListener('click', async () => { try { await designer.pixel.ask(prompt.value); prompt.value = ''; } catch (error) { if (!(error instanceof Pixonaut.PixelUnavailableError)) throw error; status.textContent = "Pixel couldn't do that right now. Please try again."; }});
undo.addEventListener('click', () => designer.pixel.undo());Pixel’s words in the built-in control follow the designer’s language, and you
can change them with messages, as any of the designer’s words: the
pixel.* keys.
Questions? Write to [email protected].