Customization & Theming
Customize Flutter themes, semantic tokens, appearance preferences, and localization.
Theme architecture
The theme system is under lib/components/utils/themes/ and is re-exported by lib/components/utils/design_tokens.dart:
components/utils/themes/
├── app_theme.dart
├── base/design_tokens_model.dart
└── definitions/modern_theme.dart
retro_theme.dart
cozy_theme.dart
paper_theme.dartThe built-in AppTheme enum contains modern, retro, cozy, and paper, each with light/dark token definitions. theme_provider.dart applies the selected theme, brightness, accent color, text scale, bold text, reduced motion, and compact spacing.
Use semantic tokens
final tokens = ref.watch(designTokensProvider);
Container(
padding: EdgeInsets.all(tokens.contentPadding),
decoration: BoxDecoration(
color: tokens.surface,
borderRadius: BorderRadius.circular(tokens.cardBorderRadius),
),
child: Text('Hello', style: tokens.bodyPrimary),
);Prefer DesignTokens colors, text styles, spacing, component sizes, border radii, and shadows instead of hard-coded values.
Runtime appearance
Settings are persisted locally through SharedPreferences:
AppThemeMode: light, dark, system.AppTheme: modern, retro, cozy, paper.- Accent colors: emerald, blue, indigo, purple, pink, amber.
- Text scale, bold text, reduced motion, and compact mode.
Appearance works in both Account and Guest profiles and does not require a backend.
Add a theme
- Add the enum value to
components/utils/themes/app_theme.dart. - Create complete light/dark
DesignTokensconstants underthemes/definitions/. - Register both constants in
AppThemeRegistrymaps. - Add the selection/translation to
pages/settings/appearance/and the ARB files. - Regenerate generated code if annotations/providers changed.
- Test contrast, text scaling, compact mode, reduced motion, and both brightness modes.
Do not edit generated .g.dart files or leave required DesignTokens fields uninitialized.
Localization and Account preferences
Theme/appearance values are local. Language, region, timezone, and privacy preferences are managed by user_preferences_provider.dart; Account mode syncs supported values to /api/v1/app/preferences, while Guest remains local-only.
Keep profile gates explicit. A new remote preference must be guarded by isGuestLocal and added to the Laravel/Go contract before documenting it as synchronized.
Relevant files
components/utils/design_tokens.dartcomponents/utils/themes/providers/theme_provider.dartpages/settings/appearance/page.dartproviders/user_preferences_provider.dartservices/storage.dartl10n/app_*.arb
