| j / k | Scroll down / up |
| gg | Scroll to top |
| G | Scroll to bottom |
| / | Open search |
| ? | Show this help |
| Esc | Close search / help |
| n / N | Next / previous section |
| h | Go to landing |
| d | Go to docs |
| : | Command mode — type section name |
Press ? or Esc to close
Five layers. Strict responsibilities between them. Each layer has exactly one job — nothing leaks across boundaries.
Stateless widgets only. Reads Cubit/Bloc state via BlocBuilder, dispatches events — nothing else. No business logic, no store calls, no API calls.
Screens are StatefulWidget only to call cubit methods in initState. All visual decisions come from design tokens — never raw colors or hardcoded sizes.
Cubit is the default — simple, lightweight, no boilerplate. Multiple Cubits per feature are allowed when concerns are clearly separate (e.g. form state vs data state).
Bloc when you need event transformations (debounce, throttle, switchMap), event history/traceability, or complex event→state chains. Not "better" — just more structured when complexity warrants it.
State always has an initial() factory and copyWith(). Always emit loading before an async operation — never jump directly to success.
Extends BaseStore (in config/network/). Orchestrates the cache strategy: checks local first, fetches remote if stale, returns ApiResponse<T>.
All try/catch happens inside BaseStore — feature stores never write their own try/catch. The Store decides what to call and when. BaseStore decides how errors are wrapped.
DataSource — raw HTTP only. Returns raw Response. No base class needed. No business logic, no parsing, no try/catch. Just HTTP calls.
Local (opt-in) — sqflite CRUD only. Handles freshness via cached_at. Only added when offline is a confirmed requirement.
app/ is composition only — no business logic. Only global/core services registered at bootstrap: ApiClient, AppDatabase, GlobalErrorCubit, ThemeCubit, LocalizationCubit.
config/ is stateless, globally available, zero feature imports. Interceptors: AuthInterceptor (token + 401 refresh lock), LoggingInterceptor (debug only), ErrorInterceptor (maps errors → GlobalErrorCubit).