Zest

Editing

On this page

Zest never saves by copying the browser's version of the page back to disk. That would drop your comments, reformat every line, and write in whatever a script on the page had built. Instead, each change you make goes to the local server, which finds the exact bytes in the source file that produced it and changes only those.

When it cannot pin a change to exactly one place, it does not guess. It saves the change as a note for your agent and tells you why.

What saves straight to the file

You doZest writes
Rewrite words in a heading, paragraph, list item, button, captionOnly the characters you changed. Entities like & and — around them stay as written, and so do the line breaks and indentation around the text.
Replace an <img> (from the picker, by pasting a screenshot onto it, or by dropping a file on it)Its src, its alt if you gave one, and it removes srcset/sizes so the browser shows the new picture. Inside <picture>, each <source> points at the new image too.
Replace a background imageThe url(...) in a <style> block or style="" attribute.
Change a linkhref, and target="_blank" with rel="noopener" if you ask for a new tab.
Alt text, framingalt; object-fit/object-position (or background-size/background-position) in the element's style.
Page settings<title>, the description, and the share-card (og: and twitter:) tags in <head>, added if missing.

The first time you turn on Edit, Note, Insert or Live, a short hint says how it works. Each hint shows once in a browser (per site address), never again; More > Setup lists them all under Tips, with Show tips again.

Each save shows a toast with the line it changed and an Undo. ⌘/Ctrl+Z undoes the last one. After Change all, every copy on the page updates at once, and Undo puts every copy back.

What becomes a note instead, and why

SituationWhy Zest will not write it
The words appear in several places and Zest cannot tell which one you editedWriting the wrong one is worse than writing none. You choose: change all of them, or leave a note for this one.
A script on the page builds the text (React, a template, a data file)The words are not in the HTML file at all. Your agent knows where they come from. Your team's extension can make such a page live, and then Zest writes the app's source.
The edit crossed formatting: you deleted a link, or typed across bold textZest writes text, not structure.
A background image set in a separate .css fileZest edits the page, not its stylesheets.
The file changed on disk before your save arrivedSee Stale tabs below.

The page keeps showing your change until you reload, so you can carry on. The note lands in Changes under Waiting for your agent, with the exact before and after.

Zest decides "which one" by counting: it records where your text sits among identical text on the page, and matches that against the file. When a script has added extra copies, the counts disagree, and Zest uses the words just before and after yours to decide. Only when both fail does it ask.

Stale tabs

Every save carries the version of the file the tab loaded. If the file has changed since (your agent edited it, or you did in another editor), the save is refused, the tab says so, and your change becomes a note so it is not lost. Reload to carry on.

When the file changes and you are not mid-edit, the tab reloads itself and keeps your scroll position. While your agent is running a round, the tab waits and reloads once, when the round ends.

Live view

A live page (a page an app renders, which your team's extension writes; see Your team's setup) opens as a copy with its scripts taken out, so its animation, motion and scroll effects never run. Press Live on the bar (or L) to see the running page itself, from the app's own address, over the copy. Editing turns off, and pins and the selection wait. Live again, Esc, or E, N or I brings the copy back with its pins.

While Live is on, the bar offers two more steps:

Esc and L work when the focus is on Zest. A click inside the running page gives it the keys, so press Live on the bar instead. Pages that are not live have no Live button.

To edit the running page itself, with its motion, rather than its copy, use Edit here: see Editing in place. There is no Live button there, because you are already on the running page.

Versions

Zest keeps a copy of the file before every save, before every restore, and before every change made outside the editor: the last 100 per file, in .zest/history/. More > Versions lists them. View opens one in a new tab, read-only. Restore brings it back, after keeping the current one as a version too.

Pages Zest opens read-only

Zest keeps a page's permissions when it saves, and writes through a symlink rather than replacing it.

Slides

A deck gets a Slides tab in the drawer (More, then Slides). Zest switches it on for any page whose slides look like this, in either attribute order:

<section class="slide" data-sid="pricing" data-dur="45">
  <h2>Pricing</h2>
  <p data-build="1">Arrives on the first click.</p>
  <aside class="notes">What you say while this slide is up.</aside>
</section>

data-sid names the slide, data-dur is its seconds, data-build="k" marks a part that arrives on the k-th click, aside.notes is the talk track, and the class skip hides a slide in this run-through.

You doZest writes
Drag a slide in the listThe whole <section> moves, with a comment written right above it. The space between slides stays where it was.
Hide or ShowAdds or removes skip in the slide's class.
Type secondsdata-dur. The total at the top counts only the slides shown.
Write the talk track, then click awayThe text inside the slide's <aside class="notes">, added if it has none. Plain text: formatting in an old talk track is dropped, and the panel says so first.
DuplicateA copy right after the slide, named <sid>-copy, with a copy of every rule in the page's <style> that names [data-sid="<sid>"]. Every id inside the copy gets a new name (chart becomes chart-copy), and what points at it inside the copy follows: for, aria-labelledby and the other id lists, href="#…", url(#…), and the copy's own <style>. Page rules that name one of those ids are copied for the new name too. A script that looks an element up by its old id still finds the original.
New slide afterA blank slide: a heading, one line to replace, an empty talk track, 30 seconds.
RemoveThe slide goes, with its own <style>. Zest asks first and says how many open notes it has; More > Versions keeps the deck as it was. A rule in the page's <style> goes too when it can only match that slide: it names its data-sid, or an id or class nothing else in the page uses (in markup or a script), and an @media block left empty goes with it. When Zest cannot tell (the page loads a script it cannot read, or the name sits inside :not()), it keeps the rule and the change log lists it for your agent.
Save a viewA named set of hidden slides, so one deck can run long or short. Choosing a view hides exactly its slides. While a view is in use, hiding a slide changes that view. Views live in the page, in <script type="application/json" id="zest-deck-views">.

Hiding, seconds, views and the talk track change on screen at once. A move, a copy, a new slide or a removal reloads the page, so what you see is what the file says. A built page (zest.json built) gets every change in its source, and Zest runs its build.

Clicking a slide in the list moves the deck there: through the deck's own window.DeckGo(sid) if it has one, else its #n address (slide n, #n.k for build k), else by scrolling to it.

The storyboard (press T): every slide as a card as wide as its seconds, in order. Drag cards to move them; drag one to the tray below to hide it, or back to show it. Take thumbnails gives each card a picture of its slide at its last build, taken with the Chrome on your machine and kept in .zest/thumbs/. Everything else works without Chrome.

Notes on a slide. A note you leave on a deck names its slide and the build on screen, so your agent changes the right one. The slide's row in the list shows how many notes are waiting on it.

To try it: zest demo --deck copies a three-slide example into ./zest-deck and opens it. Approve its build once with zest trust zest-deck/index.html so moves and new slides show on the page straight away.

Levers

A page can say which of its values a person may tune, and Zest gives it a Levers tab (More, then Levers). Zest switches it on for any page with a levers block:

<script type="application/json" id="zest-levers">
{
  "title": "Spring launch",
  "target": ":root",
  "schema": [
    { "tab": "Look", "group": "Type", "key": "h1", "label": "headline px", "type": "range",
      "min": 32, "max": 96, "step": 1, "def": 64, "css": "--h1", "unit": "px" },
    { "tab": "Look", "group": "Colour", "key": "accent", "label": "button", "type": "color",
      "def": "#d9622b", "css": "--accent" }
  ],
  "values": {}
}
</script>

To try it: open plugin/examples/levers/index.html with zest open.

What Zest does not edit

This is deliberate. Those are changes where a person's intent and the file's structure need judgment, which is your agent's job.

Suggest a change to this page