AtlatestRenderedmarkdown
Readme
<@>Releasesreleases

<!-- Authoring notes for release entries (this comment is not published):

  • Match the voice and structure of the existing sections below.
  • Lead with real user impact: what changed for someone using Lantern and why it matters, not the internal implementation. Keep it concise, a few sentences an item.
  • Each release: a ## X.Y.Z heading, a one-paragraph summary, then ### subsections. Prefer concrete specifics (a metric, a command, a symptom) over vague claims.
  • No em-dashes; use commas, colons, or separate sentences.
  • Note "Existing projects build without changes" when it is true. -->

Lantern Releases

0.1.3

A big idle-CPU cut for every Lantern desktop app. The run loop no longer polls on a timer while nothing is happening: it blocks on the windowing system's own event descriptors and wakes only when there is real work, so an idle app costs a fraction of what it used to. Existing projects build without changes.

The event loop sleeps when idle

Lantern's run loop previously spun several polling timers (a 5ms bridge drain, a periodic quit watcher, a short main-wait) that kept the scheduler perpetually awake, so even a completely idle window burned close to half a CPU core. The loop now does one blocking GLib iteration, sleeping on the GMainContext poll descriptors via the scheduler's await-readable-fds and draining the page bridge in the same wake, so it consumes almost nothing when the app is idle. In a Slate desktop build this dropped the Lantern process from about 44% of a core at idle to roughly 8%, with no change to responsiveness: the bridge still delivers a message the same iteration it arrives. Requires sigil 0.17.18 for await-readable-fds.

0.1.2

A control release for apps that own their own shutdown and run work in the background. An app can now quit itself or intercept the window close button from the page, and declare background services that run alongside the UI for the life of the app. Existing projects build without changes.

An app can quit and intercept the window close button

Two host controls let an app own its lifecycle from the page. app.quit closes the app cleanly, the same teardown as closing the window. And intercept-close: #t hands a window close request back to the page as an app.close-requested event and vetoes the immediate close, so the app can prompt (for example, to save unsaved work) and then call app.quit itself, instead of the window just vanishing. Slate uses both: C-x C-c and the window close button now run its save-then-quit flow.

Background services alongside the UI

An app can now declare services: in its lantern-app, a list of background goroutines that run for the whole life of the app, started inside the loop's async scope so they can freely spawn and await. Each service is a procedure that receives the same context a command handler gets, so it can reach the page and emit events. This is how a resident host task runs without blocking the UI loop: Slate's external-control socket, the one the slate command line talks to, runs as one of these.

0.1.1

Better file handling for local apps: a new lantern://local/ route streams a real file's bytes straight to the page instead of inlining them as a base64 data URI, and large directory listings return about twice as fast. Existing projects build without changes.

Stream local files to the page over lantern://local/

An app can now hand the webview a real file to load by URL. fs.serve-file registers a file the page is allowed to read and returns an opaque handle, and the page loads its bytes with <img src="lantern://local/<handle>"> (or any element that takes a URL). That replaces the old base64 data URI approach, which inflated every file by a third and pushed one giant string through the DOM. Slate's new image viewer uses this to show a picture the moment you open it. The route is handle-scoped: it serves only files an app explicitly registered through the grant-checked fs.serve-file, so it can never become an arbitrary full-disk read, and it adds no authority beyond the fs.read-file you already had.

Directory listings about twice as fast

fs.read-dir now returns its listing over the bulk data channel instead of encoding it as JSON on the host. The old path did per-character string work that grew quadratically with the listing, so a 600-file folder spent roughly 359ms of a 607ms call just on the encode. The new path is a single linear pass, and the same folder now lists in about 288ms. Folder browsing and image paging in Slate feel noticeably snappier.

A hardened asset path resolver

The lantern:// asset resolver now strips all leading slashes from a request path before resolving it. A crafted path with a leading slash could previously leave an absolute remainder that resolved off the asset root, and that case is now closed and covered by a test. This only touches the app's own asset origin: the file-serving route above was handle-scoped from the start.

0.1.0

The first release. Point Lantern at a Sigil web build and get a native desktop app: a real window, a secure JavaScript to Sigil bridge, and optional local filesystem and terminal access, built all the way down in Sigil over sigil-ffi. No Rust, no Node, no C glue. Linux-first, on GTK4 and WebKitGTK, with the backend interface leaving room for macOS and Windows later.

A native window for any Sigil web build

lantern run <dir|url> opens a web build in a real desktop window. Assets are served over the app's own lantern:// origin, so the page loads as a first-class app rather than a file:// document, and any link the page opens goes to the system browser instead of hijacking the window. The same web build still runs unmodified in a plain browser: lantern.available feature-detects the bridge, so desktop features light up when they are present and the app degrades gracefully when they are not.

A secure bridge between the page and Sigil

The page talks to the host through one channel: lantern.invoke(cmd, args) returns a Promise, and lantern.on(event, fn) subscribes to host events. The page may only invoke commands the app registered, and nothing the page supplies is ever evaluated as Sigil, so a web build cannot reach past the commands you gave it. Apps add their own commands and host-to-page events through a small plugin system.

Local filesystem and terminal access

The lantern-system plugin gives a local app real capabilities: reading and writing files, and a true terminal (a PTY) to run a shell, a build, or a coding agent in. It follows the owner model, on by default when you point Lantern at a local build (it is your own machine and your own app) and off for a remote URL unless you opt in.