v0.0.46
5 July 2026
FieldTypeCollection and Item for registry-backed collection fields, {fragment} and {companion} Latte tags, and hidden/status/locked moved to the Record base class.
Added
FieldTypeCollection: fieldtype for ordered, registry-backed collections ofItemobjects. Scoped to a page UUID and field name.decode()returns aRecordCollectionhydrated from the registry; callable with a query DSL string to filter/sort inline ($page->items('sort=-created,limit=5')).Item: newRecordsubclass for collection items. Items live at{page_path}/_{field_name}/{shard}/{uuid}/(sharded by the first two characters of the UUID). Its template derives from the owning field definition'soptions.fields.registryFields()includesparent(owning page UUID) andfield(field name).RecordCollection::withContext(string $parent, string $field): returns a new collection carrying parent UUID and field name context, required for item creation and forFieldTypeCollectionhydration.RecordCollection::new(array $data): creates a newItemin the collection, writes itsindex.json, callssave($data), and appends it to the collection. Requires a collection that has been given context viawithContext().{fragment 'name'}...{/fragment}: Latte tag that declares a named, self-targeting fragment. Compiles to{block name}{partial 'name'}...{/partial}{/block}. Accepts optionaltarget:(override the HTMX target id) andswap:(override the swap strategy) arguments.{companion 'name'}...{/companion}: Latte tag that registers a block reachable only via its fragment URL (:name). Never renders as part of a normal page load :if (false)wrapper ensures it's compiled into the template but never emitted inline.- Registry schema 8: adds
locked,parent, andfieldcolumns;parent+fieldcomposite index;scanItems()scans_{field}subdirectories of page folders for item records.allRows(string $query): unbounded variant ofrows()for internal collection hydration.
Changed
hidden,status, andlockedmoved fromPageup toRecord, where they are now initialized from the$rowarray when provided : items hydrated from the registry skip redundant file reads for these values.Record::registryFields()andRecord::structuralKeys()now include all three at the base level.Page::structuralKeys()returns only['view'];User::structuralKeys()returns[]: both rely onRecord's base forhidden/status/locked.