State management that gets out of the way
Blex is a lightweight, source-generator-powered state library for Blazor. You write one
[BlexState] field and one [BlexAction] method; the generator writes the
reactive properties, the dispatch plumbing, the JSON snapshots and the loading/error
lifecycle. Redux DevTools time-travel is built in.
The whole store
This is not an excerpt - it is a complete, working store. There are no action classes, no reducers, no feature registrations and no selector boilerplate.
[BlexStore(Name = "counter", Persist = true)]
public partial class CounterStore
{
[BlexState] private int _count;
[BlexState] private int _step = 1;
[BlexComputed] private int ComputeDoubleCount() => Count * 2;
[BlexComputed] private bool ComputeIsEven() => Count % 2 == 0;
[BlexAction] private void OnIncrement() => Count += Step;
[BlexAction] private void OnDecrement() => Count -= Step;
[BlexAction] private void OnSetStep(int step) => Step = step;
}From that, the generator emits:
- reactive
Count/Stepproperties whose setters flow through the dispatch pipeline, - memoized
DoubleCount/IsEvenaccessors that invalidate themselves on every state change, - public
Increment(),Decrement()andSetStep(int)wrappers that batch their mutations into one named, recorded action, SerializeState()/DeserializeState()for snapshots, persistence and time-travel,- and the
BlexStoreBasebase type itself.
This is the very store shown above, resolved from DI. Open the Inspector at the bottom of the page to watch the actions stream in.
This store is marked Persist = true - reload the page and the count survives.
Why it exists
Fluxor is the de-facto Redux implementation for Blazor, and it works - but a single counter costs you a state class, an action class, a reducer and often an effect class, and there is no first-class DevTools time-travel. Blex keeps what makes Flux good - one observable state tree, named actions, a middleware pipeline - and deletes the ceremony with a Roslyn incremental generator.
| Task | Fluxor | Blex |
|---|---|---|
| Define a piece of state | Feature + State class | one [BlexState] field |
| Define an action | Action class + Reducer method | one [BlexAction] method |
| Action payloads in DevTools / middleware | manual | automatic (ctx.Args) |
| Derived state | manual selectors | [BlexComputed], memoized |
| Async side-effects | Effect classes | [BlexEffect] with generated loading/error |
| Effect cancellation & concurrency | manual | CancellationToken + Latest/Drop/Queue |
| Ad-hoc batched mutations | ✗ | store.Batch(name, …) |
| Reset to initial state | manual | store.ResetState() |
| Granular re-render | manual selectors | selector Subscribe(…) |
| Normalized collections | manual | BlexEntityAdapter / BlexEntityState |
| Persistence | 3rd-party | built in, with debounce + migrations |
| Undo / redo | ✗ | BlexHistory |
| Redux DevTools time-travel | ✗ | ✓ built in |
| Test helpers | ✗ | Bit.Blex.Testing harness |
| Boilerplate | high | generated away |
What's in the box
Installation
Packages, DI registration and the provider component.
Quick start
A working counter in three files.
Stores & state
[BlexStore] and [BlexState]: the reactive container and its fields.
Computed state
[BlexComputed]: memoized derived values that invalidate themselves.
Actions
[BlexAction], batching, direct assignment, Batch and ResetState.
Effects
[BlexEffect]: async work with generated loading, error and cancellation.
Components & selectors
Re-render on the state you actually use.
Cross-store coordination
React to one store's actions from another.
Entity adapter
Normalized collections with generated CRUD.
Middleware
Observe every action, or veto it before it runs.
Error isolation
Where non-fatal pipeline failures go.
Persistence
Rehydration, debouncing, versioning and migrations.
Undo & redo
In-app history over the whole state tree.
DevTools & time travel
The Redux DevTools bridge, and how to secure it.
Testing
The harness, the action log and waiting on state.
Compile-time diagnostics
Every BLEX#### the generator can report.
API reference
Every public type and member, grouped by area.
MCP server
Let an AI agent work against Blex's real API, docs and generator.
Packages
| Package | Description |
|---|---|
Bit.Blex |
The core runtime: BlexStoreBase, attributes, dispatch, middleware, persistence, entity adapter, undo/redo and BlexManager. No JS dependency. |
Bit.Blex.Generators |
The Roslyn incremental generator that writes the store plumbing. Reference it next to Bit.Blex; it ships as an analyzer only. |
Bit.Blex.Blazor |
Blazor integration: <BlexProvider>, BlexComponentBase, browser-storage persistence and the Redux DevTools bridge. |
Bit.Blex.Maui |
.NET MAUI integration: UseBitBlex() startup initializer, Preferences-backed persistence and XAML-bindable stores. |
Bit.Blex.Testing |
Test harness and assertions: BlexTestHarness, BlexActionLog, WaitForAsync. |
The docs site is the demo
Every page here runs against real stores registered in this app's
Program.cs. The Inspector at the bottom of the window shows
the live action feed, the serialized global state tree, the undo stack and the error sink -
all fed by the same public APIs you are reading about.