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 footer

The 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

  • styles restyles one element: a selector and 1 to 10 labeled looks. Keys 1 to 0 try each one, as with variations.
  • insert adds markup near an anchor, or at the end of main when you name none.
  • update changes one element: its styles, its words or its markup.
  • remove takes 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-abc123

implement 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

A decided preview leaves the screen, but it stays in .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, form and object tags.
  • Event attributes, such as onclick.
  • A style attribute or a custom property: styles travel as declarations, not as markup.
  • A link that runs code, such as javascript: or data:.

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" },
  ];
}