SINT
State, Injection, Navigation, Translation — The Four Pillars of High-Fidelity Flutter Infrastructure.
- About SINT
- What's New in 1.2.0
- What's New in 1.1.0
- Installing
- The Four Pillars
- Flutter Web & Deep Links
- Counter App with SINT
- Migration from GetX
- Origin & Philosophy
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:
PathTranslatoris built automatically from your registered routes + translations- Incoming URLs are canonicalized before route matching (
/libro/x→/book/x) - Outgoing URLs are localized for the browser bar (
/book/x→/libro/x) - Diacritics are normalized automatically (
Publicación→publicacion) - On mobile,
translateEndpointshas 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
ListNotifierpropagation. 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
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,
);
Injection (I)
Dependency injection without context:
Sint.put(AuthController());
Sint.lazyPut(() => ApiService());
await Sint.putAsync(() => SharedPreferences.getInstance());
final controller = Sint.find<AuthController>();
Navigation (N)
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');
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)
Flutter Web & Deep Links
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 |
Deep Link Example (Web + 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 BookDetail →
Sint.routeParam returns 'abc123' → browser shows /libro/abc123.
On mobile: Sint.toNamed('/book/abc123') →
routes to BookDetail → Sint.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
- Replace
get:withsint:inpubspec.yaml - Replace
import 'package:get/get.dart'withimport 'package:sint/sint.dart' - Your existing
Get.calls work — gradually replace withSint.to remove deprecation warnings GetMaterialApp→SintMaterialAppGetPage→SintPage
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/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_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_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/ui/bottomsheet/modal_bottomsheet_layout
- navigation/src/ui/bottomsheet/modal_bottomsheet_route
- 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