BowlerKitBowlerKit

Customization & Theming

10/11/2026

Customize the Expo theme registry, appearance settings, and semantic design tokens.

Theme architecture

The active theme is resolved by constants/theme-context.tsx from the modular registry in constants/themes/. The compatibility file constants/design-tokens.ts re-exports the same API.

constants/themes/
├── app-theme.ts
├── base/                  # token model, colors, typography, spacing
└── definitions/           # modern, retro, cozy, paper

The built-in AppTheme values are modern, retro, cozy, and paper. Each has light and dark token definitions.

Use semantic tokens

import { useTheme } from '@/constants/theme-context';

export function Card() {
  const { tokens } = useTheme();
  return (
    <View style={{
      padding: tokens.layout.contentPadding,
      backgroundColor: tokens.cardBackground,
      borderRadius: tokens.cardBorderRadius,
    }}>
      <Text style={tokens.bodyPrimary}>Hello</Text>
    </View>
  );
}

Prefer tokens.background, surface, onSurface, primary, semantic status colors, spacing, padding, layout, componentSizes, and typography over hard-coded values.

Edit a definition under constants/themes/definitions/, then keep its light/dark token shapes aligned.

Add a theme

  1. Add a value to the AppTheme enum in constants/themes/base/design-tokens.model.ts.
  2. Create complete light/dark DesignTokens definitions in constants/themes/definitions/.
  3. Register both definitions in constants/themes/app-theme.ts.
  4. Export the file from constants/themes/index.ts.
  5. Add the option and translations to app/settings/appearance.tsx and the locale files.
  6. Test contrast, large text, reduced motion, and both brightness modes.

Do not copy an incomplete token object from a guide snippet: DesignTokens contains required typography, spacing, layout, component-size, border, and elevation fields.

Profile behavior

Appearance settings are local and available in both Account and Guest profiles. They do not require the API or a backend migration.

If a new setting is account data rather than appearance data, add it to preferences-store.ts and preferences-sync.ts with an explicit Guest guard. Do not silently send Guest preferences to the API.

Relevant files

  • constants/theme-context.tsx
  • constants/themes/
  • constants/design-tokens.ts
  • app/settings/appearance.tsx
  • store/preferences-store.ts
  • services/storage.ts