v0.11.0

23 October 2026

Visitor prefs, the {cache} tag, an origin check in place of CSRF tokens, and a reworked admin editing flow.

Added

  • $app->prefs stores visitor preferences in a cookie. Declare them in config as "prefs": {"theme": ["default", "dark"]}: slug keys, the first value the default. A cookie only ever yields a declared value, and a visitor holding any pref is not served cached pages. Cookie in the Toolkit reads, sets and forgets cookies.
  • {cache 'name', 300} ... {/cache} keeps a region of a template in the fragment cache for 300 seconds. key: replaces the page URL and query that otherwise scope it.
  • The email fieldtype.
  • San::term() for search input, Str::wordCount().
  • @ui components take the shared item shape: breadcrumbs, footer (with an end slot), stats (with direction), hero (buttons use the button partial), card (an icon, and link: 'card' for a whole-card link) and list (badges, with descriptions stripped of tags). menu takes trail: true for a strip of section tabs.
  • Admin: reorder pages by dragging in the tree, one-click publish in the statusbar, rename, move and delete in the edit menu, the new-page form in the edit panel, and field errors shown inline.

Changed

  • CSRF tokens are replaced by an origin check. Request::isCrossOrigin() rejects a browser request from another origin using Sec-Fetch-Site, else Origin, and the session cookie is SameSite=Lax. SessionRoot::csrf(), requireCsrf() and verifyCsrf() are removed, and forms no longer carry a _csrf field.
  • New child pages are limited to the views a section lists.
  • Every collection item needs a page: create() rejects an empty parent. This reverses the item with no page added in v0.10.0.
  • A file field on a collection item attaches files of its page.
  • The new-user form is built from user fields, and the remaining admin forms use the standard field UI.
  • The admin login redirects through its own route.
  • select posts its keys, and deleting warns when locked pages are beneath.

Comments

No comments yet. Be the first!

Loading form…