v0.44.0

3 November 2026

Browsers can now keep cached pages and fragments, the cache gets one get() and set(), and the registry, collection and page file APIs take the query DSL where they had near-duplicate methods.

Added

  • A view's {"cache": {"ttl": N, "client": M}} and {fragment 'name', cache: N, client: M} let a visitor's browser keep the render for up to M seconds without asking, cut to what is left of the server entry.
  • {fragment 'name'}...{else}...{/fragment} renders the body only on the :name request and the {else} placeholder everywhere else.
  • Res::cache() sets Cache-Control from named parts: public, maxAge, sharedMaxAge, revalidate, immutable.
  • path~=blog in a registry query matches the page at blog and every page beneath it; path~= is the whole tree.
  • Clockwork logs a warning when a page or fragment is served from the cache, and reports deprecations as warnings.

Changed

  • Cache has one get() and one set(). getFor(), setFor(), getVaried() and setVaried() are gone: use get($key), and set($key, $value, $ttl, per: $level, vary: true). per no longer defaults to user.
  • The page-cache methods moved from App to $app->kept: cacheMark() is mark(), cacheLevel() is level(), shortenPage() is shorten(), clientFor() stays clientFor(), and keepFragment($client) is fragment($client, $cache, $key).
  • Registry::delete(string $query): int replaces remove() and deleteSubtree(), reading the query as find() does: delete('path~=blog'), delete('type=user,uuid=user:ada'). countRows() is renamed count().
  • Registry::rows($query) returns every match and pages with limit= and offset= in the query. Its $limit and $offset parameters and allRows() are gone.
  • Collection::delete(string $query, bool $force = false): int takes the DSL and returns how many went. delete($uuid) becomes delete("uuid={$uuid}"); deleteParent() and deleteParents() become delete('parent=...', force: true).
  • PageFiles::clearVariants() also wipes a file's public mirrors, replacing clearMirror(). clearPublic($url, rows: false) replaces withdraw() and removes the folder once it is empty.
  • collection:prune deletes through Collection::delete() in batches of 500 and skips locked items.
  • Ses::destroy() forgets the session cookie, so a browser can't replay a signed-in visitor's kept page after sign-out.
  • Clockwork no longer logs the site config.
  • npm run build builds the site theme and HTMX bundle as well as the admin, and npm run watch watches the site theme.

Fixed

  • An SVG colour swap no longer warns on a colour it can't read.