SINT

SINT Framework

State, Injection, Navigation, Translation — The Four Pillars of High-Fidelity Flutter Infrastructure.

pub package

Languages:

English Spanish Arabic French Portuguese Russian Japanese Chinese Korean Indonesian Turkish Vietnamese



About SINT

SINT is an architectural evolution of GetX (v5.0.0-rc), built as a focused framework around four pillars only:

Pillar Responsibility
S — State Management SintController, SintBuilder, Obx, .obs, Rx types, Workers, SintStatus, SintListener
I — Injection Sint.put, Sint.find, Sint.lazyPut, Sint.putAsync, Bindings, SmartManagement
N — Navigation SintPage, Sint.toNamed, Sint.toInitial, routeParam, pathParam, queryParam, middleware, SintMaterialApp, SintSnackBarStyle, web-safe back()
T — Translation .tr extension, Translations class, locale management, loadTranslations, PathTranslator, translateEndpoints

Everything outside these four pillars has been removed: no HTTP client, no animations, no string validators, no generic utilities. The result is 37.7% less code than GetX — 12,849 LOC vs 20,615 LOC.

Key principles:

  • PERFORMANCE: No Streams or ChangeNotifier overhead. Minimal RAM consumption.
  • PRODUCTIVITY: Simple syntax. One import: import 'package:sint/sint.dart';
  • ORGANIZATION: Clean Architecture structure. 5 modules, each mapping to a pillar.

What's New in 1.2.0

Focus: Flutter Web, Deep Links & i18n URL Routing — without breaking mobile.

RESTful Route Parameters

Spring Boot-inspired parameter extraction that works identically on mobile and web:

// Define routes with path parameters (same as before)
SintPage(name: '/book/:bookId', page: () => BookDetail()),
SintPage(name: '/shop/product/:productId', page: () => ProductPage()),

// Navigate (works on all platforms)
Sint.toNamed('/book/abc123');
Sint.toNamed('/shop/product/42?color=red&size=lg');

// Extract parameters — clean API, no manual parsing
String? bookId    = Sint.routeParam;                       // 'abc123'
String? productId = Sint.pathParam('productId');           // '42'
String? color     = Sint.queryParam('color');              // 'red'
String  size      = Sint.queryParamOrDefault('size', 'm'); // 'lg'
Method Equivalent (Spring Boot) Description
Sint.routeParam @PathVariable First path parameter value
Sint.pathParam('id') @PathVariable("id") Named path parameter
Sint.queryParam('q') @RequestParam Query string parameter
Sint.queryParamOrDefault('sort', 'asc') @RequestParam(defaultValue) Query with fallback

All four methods support SintTestMode for unit testing without a running app.

i18n URL Routing (translateEndpoints)

Localized URLs in the browser address bar — zero configuration beyond what you already have:

SintMaterialApp(
  translateEndpoints: true,  // Enable URL localization
  translationsKeys: AppTranslations.keys,
  locale: Locale('es'),
  sintPages: [
    SintPage(name: '/book/:bookId', page: () => BookDetail()),
    SintPage(name: '/event/:eventId', page: () => EventDetail()),
  ],
)

Your existing translations automatically power the URL routing:

// In your translations file — no extra config needed
'es': { 'book': 'libro', 'event': 'evento', ... }
'fr': { 'book': 'livre', 'event': 'evenement', ... }
'de': { 'book': 'buch', 'event': 'veranstaltung', ... }

Result:

Locale Browser URL Internal Route
EN /book/abc123 /book/abc123
ES /libro/abc123 /book/abc123
FR /livre/abc123 /book/abc123
DE /buch/abc123 /book/abc123

How it works:

  1. PathTranslator is built automatically from your registered routes + translations
  2. Incoming URLs are canonicalized before route matching (/libro/x/book/x)
  3. Outgoing URLs are localized for the browser bar (/book/x/libro/x)
  4. Diacritics are normalized automatically (Publicaciónpublicacion)
  5. On mobile, translateEndpoints has zero overhead — path translation only activates for web URL parsing

Global Snackbar Theming

Define snackbar appearance once, apply everywhere:

SintMaterialApp(
  snackBarStyle: SintSnackBarStyle(
    backgroundColor: Colors.grey[900],
    colorText: Colors.white,
    borderRadius: 12,
    margin: EdgeInsets.all(16),
    snackPosition: SnackPosition.bottom,
    duration: Duration(seconds: 3),
  ),
)

// All snackbar calls inherit the global style
Sint.snackbar('Title', 'Message');
// Call-site params still override when needed
Sint.snackbar('Error', 'Failed', backgroundColor: Colors.red);

Three-level cascade: call-site > global style > hardcoded defaults.

See CHANGELOG.md for the full list of changes.


What's New in 1.1.0

Reactive Workers

Auto-cancelling reactive listeners on SintController:

class SearchController extends SintController {
  final query = ''.obs;

  @override
  void onInit() {
    super.onInit();
    debounce(query, (q) => fetchResults(q));       // Wait 400ms after typing stops
    once(query, (_) => analytics.track('search'));  // Fire once, then auto-cancel
    ever(query, (q) => print('Query: $q'));         // Every change
    interval(query, (q) => save(q));                // Max once per second
  }
}
// All subscriptions auto-cancel on onClose(). Zero cleanup code.

SintStatus Pattern Matching

Exhaustive .when() and .maybeWhen() on SintStatus<T>:

final status = SintStatus<User>.loading().obs;

Obx(() => status.value.when(
  loading: () => CircularProgressIndicator(),
  success: (user) => Text(user.name),
  error: (err) => Text('$err'),
  empty: () => Text('No data'),
));

// Convenience: status.value.isLoading, .dataOrNull, .errorOrNull

SintListener

React to state without rebuilding (like BLoC's BlocListener):

SintListener<String>(
  rx: controller.errorMsg,
  listener: (msg) => Sint.snackbar(msg),
  child: MyPage(),
)

Async DI

await Sint.putAsync<SharedPreferences>(
  () => SharedPreferences.getInstance(),
);
final prefs = Sint.find<SharedPreferences>();

Hard Reset Navigation

Sint.toInitial();                                    // Full reset
Sint.toInitial(keep: {AuthController});              // Keep auth alive

Lazy Translation Loading

await Sint.loadTranslations(() async {
  final json = await rootBundle.loadString('assets/i18n/shop_es.json');
  return {'es': Map<String, String>.from(jsonDecode(json))};
});

See CHANGELOG.md for the full list of changes.


Installing

Add SINT to your pubspec.yaml:

dependencies:
  sint: ^1.2.0

Import it:

import 'package:sint/sint.dart';

High-Fidelity Performance (Benchmarks)

SINT is built for speed. Every pillar is audited against the Open Neom Standard.

Pillar Metric Result Context
S (State) Reactive .obs update 0.09 us/op 50,000 updates
S (State) Simple update() 0.11 us/op 50,000 updates
S (State) Rx with listener 6.23 us/op 30,000 updates stress test
I (Injection) Registry Lookup 1.34 us/find Depth 10 dependency resolution
N (Navigation) Middleware Latency 23 ms 5-layer middleware chain
T (Translation) Dynamic Interpolation 2.65 us/op 10,000 trParams lookups

Why SINT is faster:

  • Pillar S: Avoids Stream overhead by using direct ListNotifier propagation. 15-30x faster than BLoC.
  • Pillar I: O(1) hash lookups in the global registry with lifecycle management.
  • Pillar N: Context-less navigation removes heavy widget tree lookups during routing.

The Four Pillars

SINT — The Four Pillars

State Management (S)

Two approaches: Reactive (.obs + Obx) and Simple (SintBuilder).

// Reactive
var count = 0.obs;
Obx(() => Text('${count.value}'));

// Simple
SintBuilder<Controller>(
  builder: (_) => Text('${_.counter}'),
)

Workers for reactive side effects:

ever(rx, callback);       // Every change
once(rx, callback);       // First change only
debounce(rx, callback);   // After pause (400ms default)
interval(rx, callback);   // Max once per duration (1s default)

SintStatus for async state:

status.value.when(
  loading: () => spinner,
  success: (data) => content(data),
  error: (err) => errorView(err),
  empty: () => emptyView,
);

Full documentation

Injection (I)

Dependency injection without context:

Sint.put(AuthController());
Sint.lazyPut(() => ApiService());
await Sint.putAsync(() => SharedPreferences.getInstance());

final controller = Sint.find<AuthController>();

Full documentation

Route management without context — optimized for web deep links and mobile alike:

SintMaterialApp(
  initialRoute: '/',
  translateEndpoints: true,                          // i18n URLs (web)
  snackBarStyle: SintSnackBarStyle(...),              // Global theming
  sintPages: [
    SintPage(name: '/', page: () => Home()),
    SintPage(name: '/book/:bookId', page: () => BookDetail()),
    SintPage(name: '/search', page: () => Search()),
  ],
)

// Navigation
Sint.toNamed('/book/abc123?ref=home');
Sint.back();                                         // Web-safe
Sint.toInitial();                                    // Hard reset to home
Sint.toInitial(keep: {AuthController});              // Keep specific controllers

// RESTful parameter extraction
String? id   = Sint.routeParam;                      // 'abc123'
String? id   = Sint.pathParam('bookId');              // 'abc123'
String? ref  = Sint.queryParam('ref');                // 'home'
String  sort = Sint.queryParamOrDefault('sort', 'a'); // 'a' (default)

// Snackbar with global style
Sint.snackbar('Title', 'Message');

Full documentation

Translation (T)

Internationalization with .tr — now powers URL routing too:

Text('hello'.tr);
Text('welcome'.trParams({'name': 'Serzen'}));
Sint.updateLocale(Locale('es', 'ES'));

// Lazy loading per module
await Sint.loadTranslations(() async {
  final json = await rootBundle.loadString('assets/i18n/shop.json');
  return {'es': Map<String, String>.from(jsonDecode(json))};
});

// URL path translation (automatic when translateEndpoints: true)
// Your translation keys double as URL segment mappings:
//   'book' → 'libro' (ES), 'livre' (FR), 'buch' (DE)
//
// PathTranslator handles:
//   canonicalizePath('/libro/abc')  → '/book/abc'   (incoming)
//   localizePath('/book/abc', 'es') → '/libro/abc'  (outgoing)

Full documentation


SINT is designed with a web-first, mobile-safe philosophy. Every feature works identically across platforms, but web gets extra optimizations:

Feature Web Behavior Mobile Behavior
Sint.back() No-op if no internal history (browser arrows handle it) Standard Navigator.pop()
Sint.routeParam Extracted from browser URL path Extracted from route arguments
Sint.queryParam() Extracted from URL query string ?key=value Extracted from route arguments
translateEndpoints Localizes browser URL bar + canonicalizes incoming URLs No overhead — flag is ignored
Sint.showBackButton false (browser has native arrows) true
Default transition Transition.fade (GPU-light for web canvas) Platform default (Cupertino/Material)
Scroll behavior Drag enabled for touch, mouse, and trackpad Platform default
SintSnackBarStyle Same styling across web and mobile Same styling across web and mobile
// 1. Define routes with parameters
SintMaterialApp(
  initialRoute: '/',
  translateEndpoints: true,
  translationsKeys: AppTranslations.keys,
  locale: Locale('es'),
  sintPages: [
    SintPage(name: '/', page: () => HomePage()),
    SintPage(name: '/book/:bookId', page: () => BookDetail()),
    SintPage(name: '/profile/:userId', page: () => ProfilePage()),
  ],
)

// 2. In your controller — same code works everywhere
class BookDetailController extends SintController {
  late final String bookId;

  @override
  void onInit() {
    super.onInit();
    // Works from: browser URL, deep link, or Sint.toNamed()
    bookId = Sint.routeParam ?? '';
    loadBook(bookId);
  }
}

On web: User visits https://myapp.com/libro/abc123 → SINT canonicalizes to /book/abc123 → routes to BookDetailSint.routeParam returns 'abc123' → browser shows /libro/abc123.

On mobile: Sint.toNamed('/book/abc123') → routes to BookDetailSint.routeParam returns 'abc123'.

Same controller. Same routes. Same parameters. Zero platform checks.


Counter App with SINT

void main() => runApp(SintMaterialApp(
  initialRoute: '/',
  sintPages: [
    SintPage(name: '/', page: () => Home()),
    SintPage(name: '/other', page: () => Other()),
  ],
));

class Controller extends SintController {
  var count = 0.obs;
  increment() => count++;
}

class Home extends StatelessWidget {
  @override
  Widget build(context) {
    final c = Sint.put(Controller());
    return Scaffold(
      appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
      body: Center(
        child: ElevatedButton(
          child: Text("Go to Other"),
          onPressed: () => Sint.toNamed('/other'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: c.increment,
      ),
    );
  }
}

class Other extends StatelessWidget {
  final Controller c = Sint.find();
  @override
  Widget build(context) {
    return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

Migration from GetX

  1. Replace get: with sint: in pubspec.yaml
  2. Replace import 'package:get/get.dart' with import 'package:sint/sint.dart'
  3. Your existing Get. calls work — gradually replace with Sint. to remove deprecation warnings
  4. GetMaterialAppSintMaterialApp
  5. GetPageSintPage

Origin & Philosophy

SINT is a hard fork of GetX v5.0.0-rc. After 8 years of accumulated code, GetX's repository became inactive and carried significant unused weight. SINT strips away everything that does not serve the four pillars, resulting in a clean, maintainable foundation built with Clean Architecture principles.

GetX: "Do everything." SINT: "Do the right things."

S + I + N + T — State, Injection, Navigation, Translation. Nothing more, nothing less.


License

SINT is released under the MIT License.

Part of the Open Neom ecosystem.

Libraries

core/sint_core
core/src/domain/enums/smart_management
core/src/domain/errors/bind_error
core/src/domain/errors/obx_error
core/src/domain/extensions/sint_reset
core/src/domain/interfaces/sint_interface
core/src/domain/models/rx_bool
core/src/domain/models/rx_custom
core/src/domain/models/rx_impl
core/src/domain/models/rx_interface
core/src/domain/models/rx_list
core/src/domain/models/rx_map
core/src/domain/models/rx_num
core/src/domain/models/rx_set
core/src/domain/models/rx_string
core/src/domain/typedefs/core_typedefs
core/src/domain/typedefs/legacy_typedefs
core/src/sint_engine
core/src/sint_main
core/src/sint_queue
core/src/utils/log
core/src/utils/testing/wrapper
core/src/utils/testing/wrapper_named
core/src/utils/testing/wrapper_translations
injection/sint_injection
injection/src/bind
injection/src/domain/extensions/injection_extension
injection/src/domain/interfaces/binding
injection/src/domain/interfaces/bindings_interface
injection/src/domain/models/binds
injection/src/domain/models/instance_info
injection/src/domain/typedefs/injection_typedefs
injection/src/lifecycle
injection/src/ui/bind_element
injection/src/ui/binder
navigation/sint_navigation
navigation/src/domain/enums/pop_mode
navigation/src/domain/enums/prevent_duplicate_handling_mode
navigation/src/domain/enums/row_style
navigation/src/domain/enums/snack_hover_state
navigation/src/domain/enums/snackbar_position
navigation/src/domain/enums/snackbar_status
navigation/src/domain/enums/snackbar_style
navigation/src/domain/enums/transition
navigation/src/domain/extensions/bottomsheet_extension
navigation/src/domain/extensions/context_extensions
navigation/src/domain/extensions/dialog_extension
navigation/src/domain/extensions/event_loop_extension
navigation/src/domain/extensions/first_where_extension
navigation/src/domain/extensions/overlay_extension
navigation/src/domain/extensions/page_arg_extension
navigation/src/domain/extensions/snackbar_extension
navigation/src/domain/interfaces/custom_transition
navigation/src/domain/interfaces/sint_middleware
navigation/src/domain/mixins/sint_navigation_mixin
navigation/src/domain/mixins/sint_transition_mixin
navigation/src/domain/models/config_data
navigation/src/domain/models/path_decoded
navigation/src/domain/models/route_data
navigation/src/domain/models/route_node
navigation/src/domain/models/routing
navigation/src/domain/models/sint_snackbar_style
navigation/src/router/circular_reveal_clipper
navigation/src/router/index
navigation/src/router/middleware_runner
navigation/src/router/page_redirect
navigation/src/router/page_settings
navigation/src/router/route_decoder
navigation/src/router/route_match_result
navigation/src/router/route_matcher
navigation/src/router/route_parser
navigation/src/router/route_tree
navigation/src/router/route_tree_result
navigation/src/router/router_report_manager
navigation/src/router/sint_delegate
navigation/src/router/sint_information_parser
navigation/src/router/sint_navigator
navigation/src/router/sint_page
navigation/src/router/sint_page_route
navigation/src/router/sint_test_mode
navigation/src/router/url_strategy/impl/io_url
navigation/src/router/url_strategy/impl/stub_url
navigation/src/router/url_strategy/impl/web_url
navigation/src/router/url_strategy/url_strategy
navigation/src/sint_navigation_observer
navigation/src/ui/dialog/dialog_route
navigation/src/ui/sint_cupertino_app
navigation/src/ui/sint_material_app
navigation/src/ui/sint_root
navigation/src/ui/snackbar/snackbar
navigation/src/ui/snackbar/snackbar_controller
navigation/src/ui/snackbar/snackbar_queue
navigation/src/ui/transitions/circular_reveal_transition
navigation/src/ui/transitions/fade_in_transition
navigation/src/ui/transitions/left_to_right_fade_transition
navigation/src/ui/transitions/no_transition
navigation/src/ui/transitions/right_to_left_fade_transition
navigation/src/ui/transitions/size_transitions
navigation/src/ui/transitions/slide_down_transition
navigation/src/ui/transitions/slide_left_transition
navigation/src/ui/transitions/slide_right_transition
navigation/src/ui/transitions/slide_top_transition
navigation/src/ui/transitions/zoom_in_transition
navigation/src/ui/widgets/directionality_drag_gesture_recognizer
navigation/src/ui/widgets/sint_back_gesture_controller
navigation/src/ui/widgets/sint_back_gesture_detector
sint
SINT Framework 1.0.0
state_manager/sint_state_manager
state_manager/src/domain/mixins/equality_mixin
state_manager/src/domain/mixins/rx_ticket_provider_mixin
state_manager/src/domain/notify_data
state_manager/src/domain/sint_status
state_manager/src/domain/typedefs/state_typedefs
state_manager/src/engine/get_builder
state_manager/src/engine/list_notifier
state_manager/src/engine/notifier
state_manager/src/engine/sint_controller
state_manager/src/sint_listenable
state_manager/src/ui/obx_reacive_element
state_manager/src/ui/obx_widget
state_manager/src/ui/sint_listener
translation/sint_translation
translation/src/domain/extensions/locale_extension
translation/src/domain/extensions/trans_extension
translation/src/domain/interfaces/translations
translation/src/domain/models/intl_host
translation/src/domain/models/path_translator
translation/src/utils/translations_constants