Chat previews
Type edityy:: in your agent chat and the change appears on the running page. Your code is not touched until you say so.
Asking from the chat
The change starts in your agent, not on the page. Type the keyword, then the change you want, in one message.
edityy:: add a pricing section with three cards
edityy:: make the hero heading bigger and tighter
edityy:: change this button to say Start free
edityy:: remove the grey banner above the footerThe agent calls place_preview with the instruction, an action and the payload that action needs. The page paints the result and shows it with Keep and Discard.
The four actions
stylesrestyles one element: a selector and 1 to 10 labeled looks. Keys1to0try each one, as with variations.insertadds markup near an anchor, or at the end ofmainwhen you name none.updatechanges one element: its styles, its words or its markup.removetakes one element away.
Keeping or discarding
Keep leaves the change on the page as an ordinary Edityy edit. It counts in the edits list, it travels to Save to project and get_visual_changes, and Escape still puts it back.
Discard, or Escape, puts the page back the way it was.
Several at once
When more than one preview is waiting, they show as a checkbox list instead of one card, and the canvas stays untouched until you decide. Every row reads ticked to start, keys 1 to 9 and 0 flip the tick on a row, and the one button under the list answers what the ticks say:
- Anything ticked, it reads Keep all: every ticked preview is kept, and the rest are taken back.
- Nothing ticked, it reads Discard all changes: the whole list goes back.
- The
>on a row opens where that change lands: the element it names, or the place an insert takes. Escape, or leaving edit mode, takes back everything still waiting.
Each preview has an id, such as e-abc123. In the chat you can say what to do with it:
implement e-abc123
discard e-abc123implement tells the agent to read the kept preview with get_preview and write it into your source; one kept from the canvas is also in the saved edits for get_visual_changes. discard calls decide_preview to mark it dropped.
History after the list
.edityy/previews.json, kept or discarded, and get_preview lists the past ones and returns one by id.When the place is unclear
If you name no element and the place is not obvious, the agent should ask before it paints. A preview that lands somewhere you did not mean is worse than a question.
What markup is allowed
A preview may carry structure, headings, words and pictures. It is checked twice: once on the server, and again in the page before anything is painted.
Refused, on both sides:
script,style,iframe,formandobjecttags.- Event attributes, such as
onclick. - A
styleattribute or a custom property: styles travel as declarations, not as markup. - A link that runs code, such as
javascript:ordata:.
Under the hood
The endpoint is GET, POST and DELETE /__edityy/previews. A placed preview is written to .edityy/previews.json, which the MCP server and the page both read.
The page asks the endpoint for every preview still up for a decision while the editing mode is on. One waiting preview paints; several wait as the list. A preview that names an element the page does not have is dropped, so nothing paints in the wrong place.
Next.js
Next.js needs one more route file and one more rewrite, next to the ones for the edits and variations.
app/edityy/previews/route.ts
import { previewsRoute } from "edityy";
export const { GET, POST, DELETE } = previewsRoute();next.config.ts
async rewrites() {
return [
{ source: "/__edityy/variations", destination: "/edityy/variations" },
{ source: "/__edityy/previews", destination: "/edityy/previews" },
];
}
Edityy