BowlerKitBowlerKit

Customization & Theming

10/11/2026

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.dart

The 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

  1. Add the enum value to components/utils/themes/app_theme.dart.
  2. Create complete light/dark DesignTokens constants under themes/definitions/.
  3. Register both constants in AppThemeRegistry maps.
  4. Add the selection/translation to pages/settings/appearance/ and the ARB files.
  5. Regenerate generated code if annotations/providers changed.
  6. 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.dart
  • components/utils/themes/
  • providers/theme_provider.dart
  • pages/settings/appearance/page.dart
  • providers/user_preferences_provider.dart
  • services/storage.dart
  • l10n/app_*.arb