Skip to content

meragix/qora

Repository files navigation


Logo

Qora

Server-state management for Dart and Flutter.
Explore the docs »

View Examples · Report Bug · Request Feature

qora CI likes pub points license sdk

Qora is what server-state management looks like when it's built for Flutter from the ground up. Fetch, cache, synchronize, and mutate server data with a declarative API, without writing isLoading flags, try/catch blocks, or cache invalidation logic ever again.

If you've used TanStack Query on the web, this will feel familiar. If you haven't, it's the pattern where server data is treated as a synchronized cache with its own lifecycle, not as global UI state.


Quick Start

dependencies:
  qora_flutter: ^1.0.0
void main() {
  final client = QoraClient();

  runApp(
    QoraScope(
      client: client,
      child: const MyApp(),
    ),
  );
}

Now bind any query to the widget tree:

QoraBuilder<User>(
  queryKey: ['users', userId],
  fetcher: () => api.getUser(userId),
  builder: (context, state, fetchStatus) => switch (state) {
    Loading(:final previousData) => previousData != null
        ? UserCard(previousData)
        : const CircularProgressIndicator(),
    Success(:final data) => UserCard(data),
    Failure(:final error, :final previousData) => previousData != null
        ? Column(children: [UserCard(previousData), ErrorBanner(error)])
        : ErrorScreen(error),
    _ => const SizedBox.shrink(),
  },
)

The same API works in pure Dart:

final user = await client.fetchQuery<User>(
  key: ['users', userId],
  fetcher: () => api.getUser(userId),
  options: const QoraOptions(staleTime: Duration(minutes: 5)),
);

Capabilities

Core Description
Stale-while-revalidate Show cached data instantly, refresh in the background
Request deduplication 10 widgets, same key → 1 network call
Two-axis state model QoraState (data lifecycle) and FetchStatus (engine status) are fully independent
Automatic retry Exponential backoff with configurable policy
Optimistic updates Update UI before the server responds, roll back on failure
Reactive invalidation Invalidate a key → every subscriber rebuilds
Advanced Description
Offline mutation queue FIFO replay on reconnect with jitter-based backoff
Infinite queries Paginated data with maxPages memory window
Obfuscation-safe persistence Disk cache that survives Dart obfuscation in release builds
Zero code generation Pure Dart 3 sealed classes + pattern matching, no build_runner
DevTools overlay In-app debug panel (debug mode only, zero overhead in release)

Why Qora?

Existing state management solutions for Flutter (Bloc, Riverpod, Provider) are excellent for UI state: theming, auth, form state, navigation. But server data is different. It has its own concerns: loading states, error states, staleness, background refresh, cache invalidation, optimistic updates, offline queues.

Mixing these concerns into a general-purpose state store means you're reinventing the same patterns for every feature. Qora handles them all in one place: one cache, one lifecycle, one API.


Packages

Package CI Pub
qora build qora
qora_flutter build qora_flutter
qora_hooks build qora_hooks
qora_devtools_overlay build qora_devtools_overlay

Install

Flutter

dependencies:
  qora_flutter: ^1.0.0

Pure Dart

dependencies:
  qora: ^1.0.0

DevTools overlay (in-app debug panel)

dev_dependencies:
  qora_devtools_overlay: ^1.0.0
void main() {
  final tracker = OverlayTracker();
  final client = QoraClient(tracker: tracker);

  runApp(
    QoraInspector(
      tracker: tracker,
      client: client,
      child: QoraScope(
        client: client,
        child: const MyApp(),
      ),
    ),
  );
}

The QoraInspector widget is stripped from release builds automatically; zero overhead in production.


DevTools

Qora ships with developer tooling across two surfaces.

In-app overlay (stable): a draggable panel inside your running app, similar to TanStack Query's overlay. Add qora_devtools_overlay to dev_dependencies and wrap your app with QoraInspector. Zero overhead in release builds.

IDE extension (under development): a native tab inside Flutter DevTools with live query inspection, mutation timeline, network activity monitoring, and a query dependency graph. Not yet published on pub.dev. Use the in-app overlay in the meantime.

Both surfaces share the same event protocol and are independent of each other.


Documentation

Full guides, API reference, and examples: qora.meragix.dev


Contributing

Contributions are welcome. See CONTRIBUTING.md for the development workflow, testing guidelines, and architectural principles. For a sense of where the project is heading, check ROADMAP.md.


License

This project is licensed under the MIT License; see LICENSE.

Acknowledgments

About

An all-in-one data layer for Dart, providing efficient caching, request deduplication, offline queuing, and data persistence out of the box.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages