# signals.dart brings Preact style signals to Dart and Flutter

> signals.dart is a Dart implementation of the Preact Signals model, split across seven pub packages that cover the core primitives, Flutter integration, linting and devtools. The dependency tracking is automatic and the API surface is small, but the Flutter layer is where the real design decisions sit.

**rodydavis/signals.dart** — Reactive programming made simple for Dart and Flutter

- Repository: https://github.com/rodydavis/signals.dart
- Website: http://dartsignals.dev
- Stars: 821 · Forks: 86
- Language: Dart
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/rodydavis-signals-dart

## A port of Preact Signals, not a new state management framework

signals.dart is described as reactive programming made simple for Dart and Flutter, and the design is explicitly borrowed from Preact Signals. The README links the Preact article on signal boosting as the origin point, which matters because it tells you what the library is trying to be: a small set of primitives where the framework works out the dependency graph for you instead of asking you to declare it.

The result is closer to a reactive primitive library than to a full application architecture. There is no store class to subclass, no provider hierarchy to configure, and no serialisation layer to learn. You create values, read them where you need them, and the library tracks who read what. That is a narrower tool than a conventional state container, and it is easier to reason about once you accept that the tracking is implicit.

The project is published under the Apache-2.0 licence, which is one of the more permissive and well understood choices for code you might embed in a commercial Flutter application. The repository is not archived and the last push was on 2026-09-14, so work on the code is continuing.

## Lazy evaluation moves computation cost to the moment of reading

Two properties define the model. The first is fine grained reactivity: dependencies are tracked automatically and freed when no longer needed, so a signal that nobody reads does not hold on to the graph that would rebuild it.

The second is laziness. Signals only compute values when read. If a signal is not read, it will not be computed. That is a real behavioural difference from eager frameworks, where a change notification is often pushed to subscribers regardless of whether the new value is consumed. With signals, work follows reads, and a value that nobody asks for costs nothing beyond its declaration.

Lazy evaluation also changes how you think about expensive derivations. A computed value that is read by several widgets is evaluated once per change rather than once per subscriber, but only if the library caches it that way, and the documentation does not spell out the caching detail in the README itself. Anyone depending on exact evaluation counts would need to check the full documentation at dartsignals.dev rather than assume the usual behaviour. The general direction is clear, the precise semantics are not, and that gap is worth closing before you rely on it for hot paths.

## Seven packages instead of one, so you only take what you need

The repository is a melos managed monorepo and the published packages are listed in a table in the README. The set covers a wide range of needs: the `signals` package, the lower level `signals_core`, the Flutter integration `signals_flutter`, the `signals_lint` rules package, `signals_hooks`, `preact_signals`, and a `signals_devtools_extension` that has no pub listing of its own.

Splitting the packages this way is the practical decision most teams will care about. A Flutter application that only needs the primitives does not have to take the widget integration, and a non Flutter Dart project can avoid `signals_flutter` entirely. The lint package exists because the API has rules that a human reviewer or a static analyser should enforce, which is a good sign that the maintainers expect misuse to be the main failure mode.

The plugin entry also points at a VS Code extension listed on the marketplace under `rodydavis.signals-dart`. The README mentions it in a single line with a link, so its exact feature set is not something you can judge from the repository alone.

## Flutter rebuilds happen at the widget level rather than the tree level

The Flutter-specific claim in the README is surgical rendering: widgets can be rebuilt surgically, only marking dirty the parts of the widget tree that need to update and, importantly, only if mounted. The mounted check is the detail that matters. Unmounted widgets are skipped rather than dirtied, which removes a class of work that a broader invalidation approach would otherwise perform.

The Flutter skills in the repository describe this layer as element level reactive UI integration, and they mention high frequency GPU rendering bypasses and lifecycle side effects as separate topics. That suggests the intended usage is not a single reactive root but signals attached to individual elements, which is a meaningfully different shape from wrapping a whole screen in one observable.

The platform reach is wide for a Flutter library, and worth stating plainly: the README says the packages support Dart JS (HTML), Shelf Server, CLI (and Native), VM, and Flutter on Web, Mobile and Desktop. Signals can be used in any Dart project, so the primitives are not locked to Flutter at all.

## The AI assistant skills install with one skills.sh command

A newer addition to the repository is a set of prepackaged developer Skills that let AI coding assistants work on reactive systems built with this library. They live under the `./skills` directory and are described as fully modular. The individual skills map to specific concerns: `signals-preact-dart` covers the core primitives (`signal`, `computed`, `effect`, `batch`, `untracked`), `signals-dart` covers async work such as `FutureSignal` and `StreamSignal`, reactive collections and writable computed signals (`linkedSignal`), `signals-flutter` covers element level integration and `.watch(context)` extensions, and `signals-migration-6-to-7` covers upgrading from v6.x to v7.0.0.

The README gives two ways to use them. The automated path installs everything into your global AI environment through the skills.sh registry CLI:

```bash
npx skills add rodydavis/signals.dart
```

The manual path is to reference the path of the desired skill directory in your prompt, or load the relevant `SKILL.md` files as context. That second route has no install step at all, which is useful if you would rather not add anything to your global environment.

One caveat: this repository-level tooling is separate from the library itself. Installing the skills does not add the package to your pubspec.

## Version 7 was a breaking jump, and the gap since v6 spans nearly two years

The release record shows three tagged versions. v7.0.0 shipped on 2026-05-26 and v7.1.0 followed on 2026-05-29, three days later. Before that, v6.0.2 dates from 2024-12-02, so the v6 line sat idle for roughly a year and a half before the major version landed.

Because 7.0.0 is a major release, upgrading is not a matter of bumping a constraint. The repository anticipates this: the `signals-migration-6-to-7` skill is described in detail, with instructions, patterns and refactoring techniques for moving applications from v6.x to v7.0.0. That is a helpful artefact, and it is still a migration rather than a drop in replacement.

The two release dates three days apart also suggest that the v7 line was stabilised quickly after the break, while the long gap before it means anyone on v6 is facing a version jump of considerable size. Projects that pinned v6 for stability should read the changelog at CHANGELOG.md in the repository before planning the upgrade.

## Where the README stops and the documentation takes over

The README is a signpost rather than a manual. It links the full documentation at dartsignals.dev for anyone starting out, and it describes the API surface as small but says that there are a few rules to follow. That combination is the main adoption risk in this project: the entry cost is low only if you are willing to learn the rules, because mistakes in reactive code tend to show up as effects that do not rerun or values that update too often.

The rules themselves are documented, but a reader looking only at the repository files gets a feature list, a package table and a skills directory. The README does not document, for example, how dependency cleanup interacts with long-lived subscriptions, or what the exact evaluation and caching rules are for nested computed values. The `signals_lint` package is the closest thing to an answer, since lint rules can encode the rules that a code review would otherwise catch.

For the Flutter path, the skills directory is the more useful artefact, because it covers element level integration and the `.watch(context)` extensions that the README itself only names in passing.

## Conclusion

signals.dart suits Flutter teams that want fine grained reactivity without a large state management framework, and it is a reasonable fit for plain Dart projects that want the same primitives on the VM or the web. It is a poor fit for a team unwilling to read the rules of the signal API, because dependency tracking is automatic rather than explicit. Before adopting it, read the v6 to v7 migration notes in the skills directory, check that your widgets tolerate element level rebuilds, and pin the package version because v7.0.0 was a breaking release.

## FAQ

### What is signals.dart and what problem does it solve?

signals.dart is a Dart and Flutter library for reactive programming, described as reactive programming made simple. It provides a fine grained reactivity system based on Preact Signals that automatically tracks dependencies and frees them when no longer needed, so you do not have to wire up subscriptions by hand.

### How do I add signals.dart to a Flutter project?

The packages are published on pub.dev, and the README links the `signals`, `signals_core`, `signals_flutter`, `signals_lint`, `signals_hooks` and `preact_signals` packages there. The README itself does not give an exact add command, so take the dependency name from the package listing you need rather than guessing a version constraint.

### What is the difference between signals.dart and other Dart state management libraries?

The difference is that dependency tracking is automatic rather than declared, and values are lazy: a signal is only computed when it is read. The README describes this as based on Preact Signals, with a small API surface built from primitives such as `signal`, `computed`, `effect`, `batch` and `untracked`.

## Sources

- [License: Apache-2.0](https://github.com/rodydavis/signals.dart/blob/main/LICENSE)
- [Project website](http://dartsignals.dev)
- [README](https://github.com/rodydavis/signals.dart/blob/main/README.md)
- [Releases](https://github.com/rodydavis/signals.dart/releases)
- [rodydavis/signals.dart on GitHub](https://github.com/rodydavis/signals.dart)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rodydavis-signals-dart
