Skip to content

Query() caching with stale-while-revalidate (TanStack Query style): avoid loaders on every return visit #746

Description

@Code-Victor

Hi folks 👋 I've been using OpenUI for a while now and it's genuinely great, but there's one gap that hurts the UX of everything we build with it: there's no caching between Query() and our tools, so users see loading placeholders every single time they navigate away and come back to a page, even when we fetched that exact data seconds ago.

What I'd love to see is TanStack Query style caching with stale-while-revalidate as the default behavior: when a user returns to a page, render the cached result instantly, then re-fetch in the background and update in place. No spinner, no default-value placeholder flash, and the data still ends up fresh.

The existing pieces are a solid foundation. Reactive $variable changes re-fetch dependent queries, the optional refresh-interval argument covers polling, and @Run gives manual control. What's missing is the cache layer itself:

  • Stale-while-revalidate rendering: serve the last known result for a given tool + args immediately, revalidate in the background. This is the big one for us.
  • Stale-time / cache-time control: let us say how long a result is considered fresh, so repeat visits within that window don't hit the backend at all.
  • Request deduplication: multiple components querying the same tool with the same args should share one in-flight request.
  • Declarative invalidation: today the post-mutation pattern is @Run(createResult), @Run(tickets), which means the LLM has to know every query a mutation affects. Tag-based invalidation (mutation invalidates "tickets", every query tagged "tickets" refetches) would be more robust to generation errors.
  • Cache persistence: opt-in persistence to localStorage/IndexedDB, so even a full reload or a returning session starts from cached data instead of spinners.
  • (Stretch) Retry with backoff and optimistic updates on mutations.

Since OpenUI already separates generation from execution, this fits naturally in the runtime/toolProvider layer: zero new tokens from the model, and it could even ship as a toolProvider middleware without touching OpenUI Lang itself.

With this, Queries and Mutations in OpenUI would honestly be a killer feature. I'm very open to contributing the implementation if the maintainers can weigh in on the preferred design (runtime-level cache vs. toolProvider middleware). Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions