WildflowerJS

Release · September 2026

1.5

Queries write back. Computeds go async. The whole framework still ships as one script tag.

Get WildflowerJS 1.5
Optimistic writes with field-level rollback · the new query write layer

01 · Measured

On the official board

WildflowerJS debuted strongly on the official Krausest js-framework-benchmark with the Chrome 152 run released September 1, 2026. The results below were all run on the maintainer's hardware.

1.09 WF data-pool reactivity for high-throughput, ahead of every major framework.
1.16 WF standard data-list reactivity keeps pace with the fastest signal-based compilers.
0 issue flags on either entry. Both run in CSP mode: the framework's own expression parser instead of new Function, which the board flags as an issue. That path is a little slower, and the numbers above include the cost.

Weighted geometric mean slowdown, Chrome 152 · lower is better

WF-pool
1.09
Vue Vapor
1.12
Solid
1.13
WF (data-list)
1.16
Svelte
1.17
Vue
1.31

Every operation, duration in ms · creating 1,000 rows · lower is better

vanillajs (ref)
WF-pool
Vue Vapor
Solid
WF
Svelte
Vue
React

02 · New Feature

Queries write back

Since 1.3, a query declares where data comes from and keeps it fresh. In 1.5 it declares where data goes. Add to: and the same query sends changes. They land on screen immediately, the server confirms them, and a rejection rolls them back field-by-field.

The write surface is one method

write(item) is the entire write surface. The row updates before the request leaves, isStale reports until the server confirms, and a rejection reverts only the fields the failed write still owns, so overlapping edits fail independently.

A returned record applies as server truth. A temporary id corrects in place with no flicker. Loading flags, races, and rollback bookkeeping are the framework's problem now.

wildflower.query('tasks', {
    from: '/api/tasks',
    key:  'id',
    to:   '/api/tasks/:id',        // where write() sends changes
    body: item => item,            // what to send
    confirmation: data => data     // the reply applies as server truth
});

// in a component action:
this.$tasks.write({ id: 7, done: true });
// on screen now, rolled back if the server says no

Live, against a simulated server with 400 ms latency. Flip the rejection switch and watch a write roll itself back.

03 · New Feature

Computeds go async

A computed property may now return a promise. Same computed: block, same data-bind, same dependency tracking. Bindings keep the last settled value while a new one is in flight and update when it lands.

computed: {
    async user() {
        const r = await fetch('/api/users/' + this.userId);
        return r.json();
    }
}
// <h1 data-bind="user.name"></h1> and that's it

No new syntax to learn

Change a dependency and the request relaunches. A superseded request is discarded whole, so a slow response never overwrites a fast one. Errors route to the component's onError like any other computed failure.

Live. Pick the slow profile, then the fast one before it lands: the late response is discarded and the card never goes backwards.

04 · New tier

mini-pool: the games build

Entity pools are WildflowerJS's per-frame rendering primitive, built for simulations, games, and visualizations with thousands of moving entities. The new mini-pool tier ships pools without the list cluster: 55 KB compressed, the whole framework underneath.

nano
50.5 KB
mini-pool
55.0 KB
mini
73.8 KB
lite
78.0 KB
standard
81.6 KB
spa
86.1 KB
full
98.7 KB

There are seven tiers now, and every one is a single file with state, computeds, components, stores, and forms inside. Pick by the rendering primitives you need.

Also in 1.5

persist: true

A query's last confirmed rows survive in localStorage, so the next visit paints before any request leaves the machine. Only server truth is ever stored.

invalidateQueries(...names)

Invalidate several named queries in one call and await convergence across every view of the same entity.

$q.pendingWrites

A reactive count of unconfirmed writes. Bind it for a saving indicator, or check it before navigating away.

A fresh: window for the refresh ladder

Our initial query launch in v1.3 brought a refresh ladder. With v1.5 we add a fresh: token, refresh: ['focus', 'fresh:30'], which skips the refetch when the last sync is younger than 30 seconds.

Params as a function

params: may be a function resolved on every request, so polls, focus refetches, and retries carry the page you are actually on.

Sharper dev diagnostics

Dev builds catch reactive values smuggled into state, typoed refresh tokens, and case-only name typos. Each warning comes with a suggested fix.

12

fixes

The most visible one is that list rows adopted from SSR or a query now survive their first update as the same DOM nodes, so focus, selection, and third-party enhancements stay intact.

Read them all in the changelog.

One tag, as always

<script src="https://cdn.jsdelivr.net/npm/wildflowerjs@1.5/dist/wildflower.min.js"></script>

Or npm install wildflowerjs for self-hosting. Start with the quickstart or the tier guide.