Chuyển đến nội dung chính

Bài đăng

Hiddify Next: UI Flutter trên lõi tunnel

Client proxy/VPN sống ở rìa quyền OS. Hiddify Next ghép UI Flutter với lõi tunnel hiệu năng cao (dòng Sing-box/Go) để UI vẫn biểu đạt trong khi data path nhàm chán và nhanh. Bài học Status là stream. Latency, server đang nối, lỗi phải là một model nhất quán. Config là data. Import/export profile; đừng hardcode endpoint trong widget. API VPN nền tảng là phần khó — cô lập sau service interface. Cạm bẫy Pin và thermal khi tunnel always-on. Chính sách store khác nhau cho app VPN. Dùng repo này khi cần tham chiếu Flutter backed by service , không chỉ CRUD thuần. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Harmony Music: pattern player offline-first

App nhạc offline là vấn đề storage, scan và lifecycle service. Player kiểu Harmony giữ index thư viện local và playback service sống sót khi UI điều hướng. Pattern Scan một lần, nghe filesystem event sau. Queue nằm trong controller/service, không trong widget màn hình. Notification/media session nền tảng là UX bắt buộc. Cạm bẫy Thư viện lớn cần index tăng dần. Đừng chặn frame đầu bằng scan full SD. So với Spotube nếu bạn còn cần catalog streaming. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Golden Toolkit: regression hình ảnh có chủ đích

Golden Toolkit: regression hình ảnh có chủ đích golden_toolkit đáng chú ý vì nó giải quyết ma trận thiết bị, font, biến thể surface và diff golden dễ đọc. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu testGoldens ( 'profile variants' , (tester) async { await loadAppFonts (); await tester. pumpWidgetBuilder ( const ProfileCard ()); await screenMatchesGolden (tester, 'profile-card' ); }); Checklist trước khi ship Đọc README và changelog của package đúng version đang pin. Viết một test cho lifecycle, lỗi và hành vi khi app về background. Kiểm tra Android, iOS, web hoặc desktop đúng pl...

Hiddify Next: Flutter UI over a tunnel core

Proxy/VPN clients live at the edge of OS permissions. Hiddify Next pairs a Flutter UI with a high-performance tunnel core (Sing-box/Go lineage) so the UI stays expressive while the data path stays boring and fast. Lessons Status is a stream. Latency, connected server, and errors should be one consistent model. Config as data. Import/export profiles; do not hardcode endpoints in widgets. Platform VPN APIs are the hard part — isolate them behind a service interface. Pitfalls Battery and thermal costs of always-on tunnels. Store policy differences for VPN apps. Use this repo when you need a reference for service-backed Flutter rather than a pure CRUD app. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

Harmony Music: offline-first player patterns

Offline music apps are storage, scanning, and service lifecycle problems. Harmony-style players keep a local library index and a playback service that survives UI navigation. Patterns Scan once, listen to filesystem events later. Queue lives in a controller/service, not in a screen widget. Platform notification/media sessions are required UX. Pitfalls Large libraries need incremental indexing. Do not block first frame on a full SD card scan. Compare with Spotube if you also need streaming catalogs. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

Golden Toolkit: visual regression with intent

Golden Toolkit: visual regression with intent golden_toolkit is useful because it focuses on device matrices, fonts, surface variants, and readable golden diffs. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point testGoldens ( 'profile variants' , (tester) async { await loadAppFonts (); await tester. pumpWidgetBuilder ( const ProfileCard ()); await screenMatchesGolden (tester, 'profile-card' ); }); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app background/foreground behavior. Ve...

go_router: Điều hướng Flutter lấy URL làm trung tâm

go_router: Điều hướng Flutter lấy URL làm trung tâm go_router đáng chú ý vì nó giải quyết routing khai báo, deep link, redirect và ShellRoute. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu final router = GoRouter ( redirect : (context, state) => isSignedIn || state.uri.path == '/login' ? null : '/login' , routes : [ GoRoute (path : '/' , builder : (_, __) => const HomePage ()), GoRoute (path : '/orders/:id' , builder : (_, state) => OrderPage (id : state.pathParameters[ 'id' ] ! )), ], ); Checklist trước khi s...

FVM: ghim Flutter version theo từng repository

FVM: ghim Flutter version theo từng repository fvm đáng chú ý vì nó giải quyết file version, parity với CI, onboarding team và nhịp migration. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu fvm use stable fvm flutter pub get fvm flutter test fvm flutter build apk -- release Checklist trước khi ship Đọc README và changelog của package đúng version đang pin. Viết một test cho lifecycle, lỗi và hành vi khi app về background. Kiểm tra Android, iOS, web hoặc desktop đúng platform mà app hỗ trợ. Ghi lại owner, upgrade cadence và kế hoạch rollback trong repo. Pitfall hay gặp Ghim version cả ở CI và docs; setting ...

Freezed: model bất biến và union an toàn hơn

Freezed: model bất biến và union an toàn hơn freezed đáng chú ý vì nó giải quyết data class bất biến, JSON union, copyWith và state UI exhaustive. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu @freezed sealed class LoadState < T > with _$LoadState < T > { const factory LoadState . idle () = Idle < T >; const factory LoadState . loading () = Loading < T >; const factory LoadState . data ( T value) = Data < T >; const factory LoadState . failure ( Object error) = Failure < T >; } Checklist trước khi ship Đọc README và changelog của package đúng versi...

go_router: URL-first navigation for Flutter

go_router: URL-first navigation for Flutter go_router is useful because it focuses on declarative routing, deep links, redirects, and ShellRoute. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point final router = GoRouter ( redirect : (context, state) => isSignedIn || state.uri.path == '/login' ? null : '/login' , routes : [ GoRoute (path : '/' , builder : (_, __) => const HomePage ()), GoRoute (path : '/orders/:id' , builder : (_, state) => OrderPage (id : state.pathParameters[ 'id' ] ! )),...

FVM: pin Flutter versions per repository

FVM: pin Flutter versions per repository fvm is useful because it focuses on version files, CI parity, team onboarding, and migration cadence. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point fvm use stable fvm flutter pub get fvm flutter test fvm flutter build apk -- release Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app background/foreground behavior. Verify every platform your product supports, not only the developer machine. Record ownership, upgrade cadence, and rollback notes in the repository. ...

Freezed: safer immutable models and unions

Freezed: safer immutable models and unions freezed is useful because it focuses on immutable data classes, JSON unions, copyWith, and exhaustive UI states. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point @freezed sealed class LoadState < T > with _$LoadState < T > { const factory LoadState . idle () = Idle < T >; const factory LoadState . loading () = Loading < T >; const factory LoadState . data ( T value) = Data < T >; const factory LoadState . failure ( Object error) = Failure < T >; } Production checklist Read the RE...

ForUI: component headless dễ tiếp cận cho Flutter

ForUI: component headless dễ tiếp cận cho Flutter forui đáng chú ý vì nó giải quyết control có thể ghép, theme, keyboard behavior và accessibility. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu FButton ( onPress : submit, child : const Text ( 'Save' ), ); FPopoverMenu ( control : FButton (onPress : openMenu, child : const Text ( 'More' )), menu : [ FPopoverMenuItem (onPress : archive, child : const Text ( 'Archive' )), ], ); Checklist trước khi ship Đọc README và changelog của package đúng version đang pin. Viết một test cho lifecycle, lỗi và hành vi khi ...

Forui: hệ thống UI Flutter có chủ kiến

Forui đặt cược khác “Material ở khắp nơi”: cấu trúc chặt, default mạnh và theme được thiết kế như một hệ thống. Khi nào nên đánh giá Sản phẩm muốn một look nhất quán mobile/desktop. Bạn chán override internal component Material. Accessibility là yêu cầu launch, không phải backlog. Cạm bẫy Adopt hệ thống UI đầy đủ là migration. Pilot một luồng (settings + form) trước khi rewrite cả app. So Forui với package material_ui độc lập nếu team vẫn muốn Material của Google làm nền. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

flutter_secure_storage: secret nằm sau keychain của platform

flutter_secure_storage: secret nằm sau keychain của platform flutter_secure_storage đáng chú ý vì nó giải quyết Keychain, Keystore, encrypted shared preferences và migration. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu const storage = FlutterSecureStorage (); await storage. write (key : 'refresh_token' , value : refreshToken); final token = await storage. read (key : 'refresh_token' ); await storage. delete (key : 'refresh_token' ); Checklist trước khi ship Đọc README và changelog của package đúng version đang pin. Viết một test cho lifecycle, lỗi và hành vi khi app về back...

ForUI: accessible headless components for Flutter

ForUI: accessible headless components for Flutter forui is useful because it focuses on composable controls, theming, keyboard behavior, and accessibility. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point FButton ( onPress : submit, child : const Text ( 'Save' ), ); FPopoverMenu ( control : FButton (onPress : openMenu, child : const Text ( 'More' )), menu : [ FPopoverMenuItem (onPress : archive, child : const Text ( 'Archive' )), ], ); Production checklist Read the README and changelog for the exact version you pin. Add one test...

Forui: an opinionated Flutter UI system

Forui takes a different bet than “Material everywhere”: strict structure, strong defaults, and a theme system designed as a system. When to evaluate it Product wants one coherent look across mobile/desktop. You are tired of overriding Material component internals. Accessibility is a launch requirement, not a backlog item. Pitfalls Adopting a full UI system is a migration. Pilot one flow (settings + forms) before a full rewrite. Compare Forui with material_ui standalone packages if your team still wants Google Material as the base. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

flutter_secure_storage: secrets behind platform keychains

flutter_secure_storage: secrets behind platform keychains flutter_secure_storage is useful because it focuses on Keychain, Keystore, encrypted shared preferences, and migration. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point const storage = FlutterSecureStorage (); await storage. write (key : 'refresh_token' , value : refreshToken); final token = await storage. read (key : 'refresh_token' ); await storage. delete (key : 'refresh_token' ); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, ...