Skip to content
Taliesin User Guide

3 The live preview loop

What survives a save (scroll position, kernel state, a running canvas) and how Ctrl-click jumps from the page back to the line that made it.

The reason Taliesin exists is the edit loop: change the source, and the preview reflects it immediately, without reloading the page, losing your scroll, or resetting any live content already on screen. See Section 2.2 for what “immediately” is in milliseconds.

3.1 Incremental updates

On every save the server re-parses the document, diffs the new block list against the old one by content-hash id, and pushes only the blocks that changed over a websocket. An unchanged block is never touched, so:

  • your scroll position is preserved,
  • a running {js} cell or Three.js canvas keeps its state,
  • the page never flashes white.

The block you just edited pulses briefly when it re-renders, so your eye (or your phone) lands on the change.

3.2 Click-to-source and editor sync

In the browser preview, a plain click browses normally; Ctrl-click (Cmd-click on Mac) any block to open its exact source line in your editor (including across {{< include >}}d files) via a vscode:// deep link. The client also speaks a tali-goto / tali-cursor postMessage protocol, so an editor can host the preview and add cursor sync without forking anything. The in-repo VS Code companion (editor/vscode/) is exactly that host.

Click-to-source is VS Code only

The deep link is vscode:// and there is no configuration key for it, so Ctrl-click does nothing in Neovim, Helix or Zed. Those editors get everything taliesin lsp serves and the live preview itself; it is the jump from the page back to the editor that has one target.

Getting the companion. It is not on the VS Code Marketplace; you build the .vsix from this repository and install it yourself:

cd editor/vscode && npm install && npm run build && npx @vscode/vsce package
code --install-extension taliesin-companion-<version>.vsix

Then make sure the taliesin binary is on your PATH, or point the extension’s taliesin.path setting at it.

A chapter of a book previews as the book. Open the preview on any page that lives under a _site.yml and the companion serves the whole project and opens it at that page’s URL, so you get the nav, the breadcrumb and working cross-page links instead of an orphan page. One server serves every chapter: opening a second one reveals the preview you already have, moved to that chapter. Moving your cursor into another chapter’s file moves the preview to it too, and Ctrl-clicking a block resolves against the page you are looking at, not the one you opened.

The other direction, editor to preview, is split. Moving your cursor marks the matching block in the preview and deliberately does not move the page, so scrolling somewhere to compare two figures survives your next keystroke. When you do want the preview to come to you, press Ctrl+Alt+J (Taliesin: Reveal Cursor in Preview), which scrolls it there and leaves the keyboard focus in your editor.

Reuse the editor tab instead of opening a new one

If repeated Ctrl-clicks from a browser preview open new tabs instead of moving the cursor in the tab you already have, add "workbench.editor.revealIfOpen": true to your settings.json. The companion does not need it.

3.3 What the editor does while you write

  • Completion for front-matter keys and values, cell options and their values, cell languages, div classes, cross-references, citations, shortcode names, anchor ids, math commands, and file paths anywhere a path is legal.
  • Div attributes, narrowed to the class you wrote. ::: {.callout-note offers title= and collapse=, the two a callout reads; a plain div offers layout-ncol= and neither of those.
  • Lists and blockquotes continue on Enter, keeping the marker you chose (-, *, +, >, and task items). Pressing Enter on an empty item is how you leave the list.
  • _site.yml completion is your YAML language server’s job, not Taliesin’s: the config schema is a file you point it at with one comment line, the same step in every editor (see Configuration).

3.3.1 What the document’s structure gets you

Neither of these needs a preview window open, and neither is specific to VS Code: they are the protocol, so cmd = { "taliesin", "lsp" } gets them in Neovim, Helix or Zed too.

  • Folding follows the document’s own structure instead of indentation. Front matter, each heading down to the next of equal or shallower level, ::: divs and code fences each fold as a unit, so you can collapse a chapter to its headings.
  • Go to definition crosses files. F12 on @sec-priors jumps to the chapter that defines it, not just to a definition in the file you are in. Your open buffer still wins: an anchor you just typed and have not saved resolves to where you typed it, never to the older copy on disk. Hovering a cross-chapter reference names the page that defines it, since the number belongs to that page and is not known here.

3.3.2 Checking the pages you have not opened

The squiggles cannot do this one for you: the language server only sees files you have opened, so a chapter you have not touched all week is invisible to it. Run the project lint in the terminal instead:

taliesin build . --check-only

Every located line it prints is clickable in VS Code’s integrated terminal, straight to the file and line, whether or not that page has ever been open.

3.4 The dev menu

Every live preview carries a small dev menu: a </> button tucked in the bottom corner of the page. It belongs to the preview only, so a static build never ships it.

The button itself is a connection light: a coloured dot that reads live while the websocket is connected, reconnecting while the server restarts, and error on a failed render. A small badge appears on it when there are diagnostics waiting.

Click it to expand a panel with the preview-only tools:

  • Status and a live word count for the prose.
  • Restart kernel: drops the warm Jupyter kernel and re-runs every cell against a fresh one. Reach for it when the kernel wedges, or after you fix TALIESIN_PYTHON or install a missing package and want a clean replay.
  • A reminder that Ctrl-click (Cmd-click on Mac) opens any block’s source in your editor.
  • A theme toggle (light/dark), for the preview only: see Theming for what a reader’s built page does instead.
  • The diagnostics list (detailed below), each entry click-to-source, with the button’s badge tracking the count.

3.5 Live-edit feedback

The loop surfaces what is happening without you watching the terminal:

  • A non-fatal problem (a broken {{< include >}}, a missing kernel, a typo’d extension, a broken [@citation] or @cross-reference) appears in the dev menu’s diagnostics list.
  • A broken front matter points right at the bad line: the diagnostic shows a small code frame and is clickable to open that line in your editor.
  • A failed render throws a prominent, dismissible error overlay over the last good content, so a broken save is impossible to miss. It clears on the next successful render.
  • The watcher follows the whole document, not just the served file: editing an included subsection or the .bib re-renders the pages that depend on it.

3.6 Reading on any screen

The reading layout is responsive: wide tables, long code, display math and embedded canvases scroll within their own box instead of stretching the page, motion honours prefers-reduced-motion, and on a phone the table of contents leaves the sticky sidebar and appears inline after the article.

The preview binds to loopback only, so it is reachable from the machine running it and nowhere else. To read a draft on a phone, build it and serve the folder from somewhere both devices can see.

Pressing Cmd/Ctrl-P gives a clean print/PDF: the dev menu, the TOC handle, and any diagnostics are hidden, the palette forces light, and content flows full width without clipping code, tables, or math.