v0.0.52

7 July 2026

App-level SQLite cache, addon-provided fieldtypes and fields, auto-merged fragment controller context, and router/slug fixes.

Added

  • Cache : SQLite-backed key/value cache (site/storage/cache/{name}.db). $app->cache(string $name = 'app') returns a named Cache instance. API: get, set, has, remove, flush, remember. set() accepts an optional TTL in seconds; expired entries are evicted on has(). Enabled by default; disable per name via config.cache.{name}.enabled = false.
  • Addon fieldtypes and fields: App::typeRoots() now includes all enabled addon roots between site/ and phlat/ in the lookup chain for fieldtypes, fields, field edit templates, and loadType(). Addons can ship their own fieldtypes/ and fields/ directories that are discoverable without site overrides.
  • AddonRegistry::allRoots() : returns all registered addon root paths in registration order.
  • cache addon renamed to http-purge to avoid collision with the new Cache class concept.

Changed

  • App::renderFragment() : now merges the global controller's data (controller('app')) into the fragment context automatically, so fragment.latte has the same base variables available as a normal full-page render.
  • Route {slug} token pattern updated to [a-zA-Z0-9_-]+ : underscores are now allowed mid-slug. Str::slug() still trims both - and _ from the ends, so a slug can never start or end with either.
  • Str::slug() : preserves underscores within the string (only collapses other non-alphanumeric characters to the separator); trims both the separator and _ from both ends.
  • Addons are registered in AddonMounts unconditionally (not gated on the presence of a views/ directory) : addons that only ship fieldtypes, fields, or other assets are now properly registered.