Setting up your dashboard0 entities found · 7/34 branches scanned
Name:v0.16.0Status:planning
v0.16.0 — Registry-driven sites
The v0.16.0 milestone turns the entity registry into pages and listings, declaratively. It builds directly on v0.15.0's embedding primitives (ref / expand) and delivers three connected specs:
Not enough history yet — burndown needs at least one completed day of activity.
Collection rune (SPEC-070) — the plural counterpart to ref/expand: queries many registry entities (filter/sort/group/limit) and projects them into lists, grids, and tables, with a shared field-match grammar, per-item $item templates, heading-delimited table columns, and shared formatter functions.
Plugin-contributed routes (SPEC-069) — a contributePages pipeline phase plus a declarative entityRoutes config that synthesizes one page per registered entity, and the embed() embeddability contract.
Plan site scaffolding (SPEC-071) — the proof: a plan site built from refrakt's own plan/ via entityRoutes + collection, shipped as a create-refrakt scaffold, retiring the bespoke plan build / plan serve commands.
The collection rune core — a sentinel-emitting schema plus a postProcess resolver that queries the registry (filter/sort/group/limit) and renders the built-in layouts, with the pinned $item bound-variable contract and the per-layout body interpretation.
The rich-table path: a table collection's body uses the sections content model (heading = column separator + label, body = per-cell markdoc template with $item), with collection owning the <table>/<thead> and row alignment.
The first core plain-presentational card rune — ordinary attributes, no $item/registry knowledge — shipped as the reference implementation for collection body templates. Proves the "cards are plain runes; the template wires entity fields into attributes" model.
The built-in adapter (in @refrakt-md/content) that turns site.entityRoutes into contributed pages: selects entities by type + filter, substitutes placeholders, renders an inline render string or a render-template partial per entity with $item bound, and back-fills sourceUrl.
Make plan entities embeddable so {% expand $item.id /%} renders their bodies in entityRoutes detail pages. The plan register hook currently sets sourceUrl only; add sourceFile and an extract that returns the entity rune's transformed body. This is the prerequisite the SPEC-071 dogfood depends on.
Add a plan project type to create-refrakt that scaffolds a complete, runnable plan site: config (plugin + entityRoutes), a seed plan/, and a plan-site/ content dir (layout + dashboards), for a chosen adapter target.
Wire refrakt's own plan/ as a sites.plan site and author its plan-site/ content, proving that entityRoutes + collection replace the bespoke plan serve. This is the milestone's proof-of-practice.
Mark plan build and plan serve deprecated, pointing users at the site approach, once refrakt's own plan site proves the replacement. Keep the authoring CLI. Removing the bespoke render stack is a later release, out of scope here.
Implement the canonical field:value selector grammar from SPEC-070 as a single shared module in @refrakt-md/runes, consumed by collection, entityRoutes (SPEC-069), and backlog. The existing plugins/plan/src/filter.ts folds into it, gaining glob/regex, url resolution, and case-consistency while preserving backlog behavior.
Implement the deferBody mechanism SPEC-070's prototype validated: a catalog flag plus a pre-transform pass in the content loader that captures a rune's pristine body as a source string and empties it, so postProcess can re-parse and transform it per entity with a bound variable. Capture must happen before the page transform — by schema-transform time Markdoc has already resolved the body's $item interpolations to undefined.
Register a small set of author-facing markdoc functions — currency, date, number, join — in @refrakt-md/runes as the shared value-formatting layer, usable anywhere markdoc transforms run: collection cells, body templates, and entityRoutes render strings. Keeps formatting out of fields and out of any bespoke projection DSL.
Add the Plugin.contributePages hook and a contribution phase in the content loader (after file-page registration, before aggregation) that collects ContributedPage[] and runs them through the normal pipeline — the underlying primitive both the entityRoutes adapter and third-party plugins build on.
Generalize SPEC-066's sourceFile + extract into the embed() contract: an entity is embeddable if it has embed() or (sourceFile + extract). expand and the entityRoutes adapter accept either, so external plugins can make entities embeddable without a source file on disk.