tom_core_flutter
The thin binding layer that brings the kernel onto a Flutter target: it re-exports the whole kernel barrel and tom_reflection, and adds widgets that bind to observable kernel state, form primitives, typed UI properties, client-side platform detection and client auth helpers.
Overview
From the module readme.md file:
What it enables
Enables Flutter clients on the kernel, Observable-bound widgets, Client-side auth.
Relationships
Standalone โ no declared relationships.
tom_core_flutter
> Attribution. The Tom Framework is developed by Peter Nicolai Alexis Kyaw. > These packages are BSD-3-Clause licensed and internal (publish_to: none).
> โ ๏ธ Work in progress โ unstable API. The Tom Core packages are under active > development and not yet stable. Their version numbers carry no promise about > API maturity: they are publishing counters, not semver. The patch number is > bumped on every change โ including breaking changes โ so a patch bump may > break you. Expect the public surface to shift without notice. Not recommended > for production use yet.
Flutter integration layer for the Tom Framework โ re-exports tom_core_kernel
and adds Flutter widgets and client utilities.
Overview
tom_core_flutter is the thin binding layer that brings the platform-neutral
tom_core_kernel onto a Flutter target. It re-exports the entire kernel barrel (observable state, dependency injection, security, resources, runtime utilities) plus
tom_reflection, so a Flutter app that depends on
tom_core_flutter gets both the kernel API and the Flutter-specific extensions through a single import.
What it adds on top of the kernel is deliberately small:
- Observing widgets that rebuild when a kernel
TomObservablenotifies. -
UI-bound properties โ typed
TomProperty<T>accessors over the kernel
resource tree. - Client configuration โ a machine-scoped settings holder that resolves from the shipped config resources, persists this install's overrides, and is observable per field and as a whole. -
Preferences โ machine-local user preferences behind one platform-independent API, with the storage backend chosen by DI rather than by an
if (kIsWeb) at the call site, plus the typed client for the account-level preferences the server holds. -
Client platform detection โ the Flutter/web/IO variant selector for TomPlatformUtils. -
Client security โ the framework-owned second-factor flow: a ready-made enrol-and-challenge panel over a seam onto the application's own auth client, pluggable per-mechanism rendering resolved through a registry, and the shipped TOTP mechanism.
Relationship to tom_flutter_ui
tom_core_flutter is the low-level binding layer; it is not the application widget toolkit. The rich, ACL-aware widget set โ the declarative forms framework, the advanced-container-layout engine, theming, and
resource_auth โ lives in tom_flutter_ui. Any UI or forms work should reach for
tom_flutter_ui; tom_core_flutter only carries the kernel binding helpers.
The two demo/test harnesses make the split concrete: tom_flutter_form_test
and tom_flutter_ui_test
target tom_flutter_ui + tom_core_kernel directly โ they do
not depend on tom_core_flutter. Reach for tom_core_flutter
when you want the kernel on Flutter with the minimal binding helpers; reach for tom_flutter_ui
when you want the full UI/forms/ACL toolkit.
Installation
This package is internal to the Tom workspace and consumed by path (it is publish_to: none), so there is no
dart pub add line:
dependencies:
tom_core_flutter:
path: ../tom_core_flutter
Then import the single barrel โ it re-exports tom_core_kernel and tom_reflection, so you rarely import those directly:
import 'package:tom_core_flutter/tom_core_flutter.dart';
SDK: Dart ^3.10.4 with the Flutter SDK. Modules that use reflection (security adaptors) require
dart run build_runner build to generate *.reflection.dart.
Features
Observing widgets (observing)
| Type | What it is |
|---|---|
TomObservingWidget<T extends TomObservable> |
A
StatefulWidget
that rebuilds its
child
builder whenever the bound
subState
notifies
|
TomObservingWidgetState<T> |
The TomObserver state behind the widget (registers/rebuilds on notify) |
ValueListenableObserver<T extends TomObservable> |
Bridges a kernel TomObservable to a Flutter Listenable/listener |
Resources (resources)
| Type | What it is |
|---|---|
TomProperty<T> |
Typed accessor over the kernel resource/config tree, with .withDefault fallback |
TomStringProperty
/
TomIntProperty
/
TomDoubleProperty
/
TomBoolProperty
|
Concrete typed property variants |
Client configuration (configuration)
| Type | What it is |
|---|---|
TomBaseClientConfiguration |
Base class for a client app's machine-scoped settings holder โ declare, load, observe, persist |
TomSetting<T> |
One observable setting: a TomObject<T> plus its dotted key and its baseline |
TomClientConfigurationStore |
Two-method interface (read / write) for where overrides are persisted |
TomMemoryClientConfigurationStore / TomFileClientConfigurationStore |
Process-lifetime and JSON-file stores |
TomClientConfigurationException |
Module failures, with stable dotted keys |
Only the install's overrides are persisted, so shipping a new default in an app update still reaches installs that never touched that key. See
doc/configuration.md.
Preferences (preferences)
| Type | What it is |
|---|---|
TomDevicePreferences |
The typed API for this device's preferences โ resolved as a bean, never constructed at the call site |
TomStoredDevicePreferences |
The shipped implementation: the typed API over a store, holding the single encode/decode decision |
TomDevicePreferenceStore |
Two-method (
read
/
write
) backend interface โ the only platform-specific part
|
TomPlatformDevicePreferenceStore |
The backend for the current target (JSON file /
localStorage
/ loud failure), selected at compile time
|
TomMemoryDevicePreferenceStore |
A store that persists nothing beyond the process |
TomDevicePreferenceJson |
The stored JSON document, written once for every persistent backend |
TomDevicePreferenceException |
Device-store failures, with stable dotted keys |
TomUserPreferencesClient |
The typed client for the
account's
preferences โ the same method set, over the server's
/preferences/*
routes
|
TomUserPreferencesClientException |
Client failures, with stable dotted keys |
Two stores, one vocabulary. Preferences that must not follow the user โ the last account used
here, whether biometric unlock is on this device โ stay on the device; the ones that should follow the user live server-side and are reached through
TomUserPreferencesClient. The keys, the DTO and the codec are the kernel's and both stores carry the same method set, so a preference can move between them without a call site changing. The client writes no URIs: every request is resolved from the kernel's
tomUserPreferencesApi declaration, so it and the server are two readings of one contract. See
doc/preferences.md.
Runtime (runtime)
| Type | What it is |
|---|---|
clientPlatformUtils |
Returns the platform-appropriate
TomPlatformUtils
(Flutter/web/IO/neutral), selected at compile time
|
Security (security)
| Type | What it is |
|---|---|
Tom2FAFlowPanel |
Renders whichever stop of a second-factor login the controller reports โ chooser, enrolment or challenge |
Tom2FAFlowController |
The seam an application implements over its own auth client: five moves, two pieces of read-only state |
Tom2FAClientMechanism |
One mechanism's client-side rendering, paired with its server adaptor by mechanism key alone |
Tom2FAClientRegistry |
The process-wide mechanism catalog the flow dispatches through |
Tom2FAEnrolmentPanelContext / Tom2FAChallengePanelContext |
What a mechanism's two panels are given to render themselves |
TomTotp2FAClientMechanism |
The shipped authenticator-app mechanism, registered under 'totp' |
Tom2FATexts |
Every resource key the second-factor UI resolves, and the helpers that resolve them |
TomQrCodeView |
A QR code painted from the pure-Dart qr encoder, themed like any other widget |
Little things (little_things)
| Type | What it is |
|---|---|
TomClientException |
Client-side exception extending the kernel TomException |
TomClientUIException |
UI-surfaced client exception (extends TomClientException) |
Quick start
Rebuild a widget automatically whenever an observable kernel value changes:
import 'package:tom_core_flutter/tom_core_flutter.dart';
final counter = TomInt(0);
final widget = TomObservingWidget<TomInt>(
subState: counter,
builder: (state, _) => Text('Count: ${~state}'), // ~ reads the value
);
counter | 5; // | sets the value โ the widget rebuilds with "Count: 5"
Example projects
Each module ships a self-contained example under example/. Because the barrel pulls in
flutter/material (and thus dart:ui), run them under the Flutter toolchain (flutter test
/ a Flutter entry point).
| Example | Demonstrates |
|---|---|
example/observing/
|
ValueListenableObserver bridging a TomObservable to a Flutter listener |
example/resources/
|
Resolving typed config via
TomProperty
subclasses and
.withDefault
, and both construction-time failures โ an unconfigured obligatory key and a value of the wrong type
|
example/configuration/
|
Declaring a client settings holder, loading overrides, observing, and persisting only what changed |
example/preferences/
|
Registering a device store once, typed reads/writes, persistence across a restart, reading and writing the account store over a real socket, and the device-over-server precedence |
example/runtime/
|
Obtaining the platform-appropriate
TomPlatformUtils
, querying its predicates beside the Flutter target that decides them, and taking an HTTP client from it
|
example/security/
|
Walking a
Tom2FAFlowController
through all three stops of a second-factor login โ chooser, enrolment and challenge โ plus the registry rule that decides what the chooser may list, and resource resolution with its missing-key behaviour
|
example/little_things/
|
The two client exception types and the type-based discrimination pattern |
> Cross-package sample. The > tom_core_samples/core_client_sample
> project builds a login-gated todo client on this package โ CRUD forms whose > fields render hidden / read-only / disabled / editable straight from the > role's four-state authorization matrix. See the >
samples map for the full learning path.
Usage
Observing kernel state in a widget
final name = TomString('Ada');
TomObservingWidget<TomString>(
subState: name,
builder: (state, _) => Text(~state), // rebuilds on every notify
);
name | 'Grace'; // widget now shows "Grace"
Reading typed configuration
final timeout = TomIntProperty.withDefault('http.timeoutSeconds', 30);
final seconds = ~timeout; // 30 when the key is unset
Holding this install's settings
class AppConfiguration extends TomBaseClientConfiguration {
AppConfiguration({super.store});
late final TomSetting<bool> darkMode;
@override
void declareSettings() {
darkMode = boolSetting('client.ui.darkMode', false);
}
}
final config = AppConfiguration(store: TomFileClientConfigurationStore(path));
await config.load(); // adopt this install's persisted overrides
config.darkMode | true; // observers fire, per field and holder-wide
await config.save(); // persist the overrides โ and only those
Storing a preference on this device, and on the account
// The one line in an application that knows where machine-local state lives.
TomBean.withType(
TomDevicePreferences,
TomStoredDevicePreferences(TomPlatformDevicePreferenceStore(location)),
);
final preferences = TomDevicePreferences.resolve()!;
await preferences.set('device.biometricUnlock', true);
// The account store: the same method set, no URI written by the caller.
final account = TomUserPreferencesClient(baseUri: Uri.parse(serverRoot));
await account.set(TomUserPreferenceKeys.theme, 'dark');
// Device value wins while it exists; the account value is the cross-device
// default, consulted only for a key this device has never written. The account
// side stays a callback so a device-only app need not carry an HTTP client.
final theme = await preferences.getPreferred<String>(
TomUserPreferenceKeys.theme,
() => account.get<String>(TomUserPreferenceKeys.theme),
);
Selecting the client platform utils
TomPlatformUtils.setCurrentPlatform(clientPlatformUtils);
// concrete variant (Flutter IO / web / neutral) chosen at compile time
Architecture
Flutter app
โ
import 'package:tom_core_flutter/tom_core_flutter.dart'
โ (re-exports the kernel + tom_reflection)
โโโโโโโโโโโผโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
observing resources runtime security configuration preferences
(rebuild) (TomProperty) (platform) (2FA marker) (install (device-local
settings) values)
โ
tom_core_kernel (TomObservable, TomObject,
TomUserPreferenceDto / Keys / Codec, โฆ)
โ (re-exports the whole of tom_basics)
tom_basics (TomPlatformUtils, TomFallbackPlatformUtils, โฆ)
| Type | Responsibility |
|---|---|
TomObservingWidget | Rebuilds a subtree when its observable notifies |
ValueListenableObserver |
Adapts a TomObservable to a Flutter listener |
TomProperty<T> | Typed accessor over the kernel resource tree |
TomBaseClientConfiguration |
Owns the machine-scoped settings of one install |
TomSetting<T> | One observable, persistable setting |
TomClientConfigurationStore | Persists the install's overrides |
TomDevicePreferences |
The typed, platform-independent API for this device's preferences |
TomDevicePreferenceStore |
Persists the device's preferences (file / localStorage) |
clientPlatformUtils |
Selects the concrete TomPlatformUtils for Flutter |
TomClientException | Base client-side exception type |
Ecosystem
tom_basics ยท tom_crypto ยท tom_reflection
โ
tom_core_kernel
โ
โโโโโโโโโโดโโโโโโโโโโ
tom_core_flutter tom_flutter_ui
(kernel-on-Flutter (rich widgets, forms,
binding layer) ACL, theming)
โ you are here
tom_core_flutter sits directly on tom_core_kernel and re-exports it, so Flutter apps get the full kernel API through one dependency. The richer widget toolkit lives in
tom_flutter_ui. See the repository map
for the full picture.
Further documentation
-
Per-module guides under
doc/โ one markdown file per module
(doc/observing.md, doc/resources.md, doc/configuration.md, doc/preferences.md,
doc/runtime.md, doc/security.md, doc/little_things.md). - Per-module API reference under
doc/api_reference/
โ start at doc/api_reference/api_summary_index.md
for the type index and one api_summary_{module}.md per module. (doc/api/ is reserved for generated
dart doc HTML and is gitignored.) - tom_core_kernel
โ the platform-neutral building blocks re-exported here. - tom_flutter_ui
โ the full UI/forms/ACL toolkit the demo apps target.
Status
- Version: 1.2.1
- Tests: a module suite per module, each of which also runs the example
it documents, plus three guards over what the package says about itself: one over the markdown โ its links, its anchors, its tables of contents and the dependencies each module document claims โ one over the command each example tells a reader to run, and one over the comments in the test files themselves, which may state the contract under test but neither the phase of their own authorship nor a numbered section of a document that was never committed (all with
flutter test). Two module suites additionally hold their own documents to what the code does: the preferences store's list-ownership contract, and โ in resources โ the recommendation to prefer a typed subclass together with its nullable-T
exception, and the wording and number of the failures the module throws.
No count is given: a count is a claim nothing checks, and every added test would be a README edit nobody makes. What the suites do is the part worth stating, and it does not drift with the count. - License: BSD-3-Clause โ see LICENSE.
License
BSD 3-Clause License Copyright (c) 2024-2026, Peter Nicolai Alexis Kyaw All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.