> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Customizing Your UI Kit Builder

> Customize CometChat UI Kit Builder components — modify props, styling, and behavior for React Native.

The `config.json` file handles basic feature toggles. For deeper customizations, modify the Zustand store, theme configuration, or component props directly.

***

## Understanding the Customization Architecture

The React Native UI Kit Builder uses these main files for customization:

| File          | Purpose                                   | When to Modify                               |
| ------------- | ----------------------------------------- | -------------------------------------------- |
| `config.json` | Feature flags and configuration constants | Functional changes (enable/disable features) |
| `store.ts`    | Zustand store for state management        | Runtime configuration updates                |
| Theme object  | Colors, typography, and styling           | UI/visual changes                            |

<Info>
  The `config.json` file is the source of truth for your Builder configuration. You can update it manually or by scanning a QR code with new settings.
</Info>

***

## Using the Configuration Store

The Zustand store manages your Builder configuration at runtime. Access it anywhere in your app to read or update settings.

### Reading Configuration

```tsx theme={null}
import { useConfig } from './src/config/store';

const MyComponent = () => {
  // Access entire settings object
  const settings = useConfig((state) => state.settings);
  
  // Access specific feature category
  const chatFeatures = useConfig((state) => state.settings.chatFeatures);
  
  // Access style configuration
  const styleConfig = useConfig((state) => state.settings.style);
  
  return (/* ... */);
};
```

### Updating Configuration at Runtime

```tsx theme={null}
import { useConfigStore } from './src/config/store';

// Update a specific setting
const updateFeature = () => {
  const store = useConfigStore.getState();
  store.updateSettings({
    ...store.settings,
    chatFeatures: {
      ...store.settings.chatFeatures,
      coreMessagingExperience: {
        ...store.settings.chatFeatures.coreMessagingExperience,
        photosSharing: false,
      },
    },
  });
};
```

<Note>
  Runtime changes to the store are not persisted by default. Use AsyncStorage to save and restore configurations.
</Note>

***

## Theme Customization

### Applying Builder Theme to UI Kit

The Builder configuration includes style settings that should be applied to the CometChat UI Kit theme:

```tsx theme={null}
import React from 'react';
import { CometChatThemeProvider } from '@cometchat/chat-uikit-react-native';
import { useConfig } from './src/config/store';

const App = () => {
  const styleConfig = useConfig((state) => state.settings.style);

  const theme = {
    light: {
      color: {
        primary: styleConfig.color.brandColor,
        textPrimary: styleConfig.color.primaryTextLight,
        textSecondary: styleConfig.color.secondaryTextLight,
        background: '#FFFFFF',
        border: '#E8E8E8',
      },
      typography: {
        fontFamily: getFontFamily(styleConfig.typography.font),
      },
    },
    dark: {
      color: {
        primary: styleConfig.color.brandColor,
        textPrimary: styleConfig.color.primaryTextDark,
        textSecondary: styleConfig.color.secondaryTextDark,
        background: '#141414',
        border: '#3D3D3D',
      },
      typography: {
        fontFamily: getFontFamily(styleConfig.typography.font),
      },
    },
  };

  return (
    <CometChatThemeProvider theme={theme}>
      {/* Your app components */}
    </CometChatThemeProvider>
  );
};
```

### Custom Color Palette

Override the default colors by modifying the theme object:

```tsx theme={null}
const customTheme = {
  light: {
    color: {
      primary: '#FF6B6B',        // Custom brand color
      textPrimary: '#2D3436',    // Custom primary text
      textSecondary: '#636E72',  // Custom secondary text
      success: '#00B894',        // Success state
      error: '#D63031',          // Error state
      warning: '#FDCB6E',        // Warning state
    },
  },
  dark: {
    color: {
      primary: '#FF6B6B',
      textPrimary: '#DFE6E9',
      textSecondary: '#B2BEC3',
      success: '#00B894',
      error: '#FF7675',
      warning: '#FFEAA7',
    },
  },
};
```

***

## Custom Font Integration

### Step 1: Add Font Files

Add your custom font files to the appropriate platform directories:

* **iOS:** `ios/<App>/Resources/Fonts/`
* **Android:** `android/app/src/main/assets/fonts/`

### Step 2: Link Fonts (React Native CLI)

For React Native CLI projects, create or update `react-native.config.js`:

```js theme={null}
module.exports = {
  assets: ['./assets/fonts'],
};
```

Then run:

```bash theme={null}
npx react-native-asset
```

### Step 3: Map Font Family

Create a font mapping utility:

```tsx theme={null}
import { Platform } from 'react-native';

const FONT_MAP = {
  'roboto': {
    regular: Platform.OS === 'ios' ? 'Roboto-Regular' : 'roboto_regular',
    medium: Platform.OS === 'ios' ? 'Roboto-Medium' : 'roboto_medium',
    bold: Platform.OS === 'ios' ? 'Roboto-Bold' : 'roboto_bold',
  },
  'inter': {
    regular: Platform.OS === 'ios' ? 'Inter-Regular' : 'inter_regular',
    medium: Platform.OS === 'ios' ? 'Inter-Medium' : 'inter_medium',
    bold: Platform.OS === 'ios' ? 'Inter-Bold' : 'inter_bold',
  },
  'your-custom-font': {
    regular: Platform.OS === 'ios' ? 'YourFont-Regular' : 'your_font_regular',
    medium: Platform.OS === 'ios' ? 'YourFont-Medium' : 'your_font_medium',
    bold: Platform.OS === 'ios' ? 'YourFont-Bold' : 'your_font_bold',
  },
};

export const getFontFamily = (fontName: string) => {
  return FONT_MAP[fontName] || FONT_MAP['roboto'];
};
```

***

## Component-Level Customizations

### Conditional Rendering Based on Features

Use the configuration store to conditionally render UI elements:

```tsx theme={null}
import { useConfig } from './src/config/store';

const MessageComposer = () => {
  const chatFeatures = useConfig((state) => state.settings.chatFeatures);
  const { coreMessagingExperience, deeperUserEngagement } = chatFeatures;

  return (
    <View>
      {/* Always show text input */}
      <TextInput placeholder="Type a message..." />
      
      {/* Conditionally show attachment options */}
      {coreMessagingExperience.photosSharing && (
        <PhotoAttachmentButton />
      )}
      
      {coreMessagingExperience.fileSharing && (
        <FileAttachmentButton />
      )}
      
      {deeperUserEngagement.voiceNotes && (
        <VoiceNoteButton />
      )}
      
      {deeperUserEngagement.stickers && (
        <StickerButton />
      )}
    </View>
  );
};
```

### Customizing Message Options

Control which message options appear based on configuration:

```tsx theme={null}
const MessageOptions = ({ message }) => {
  const chatFeatures = useConfig((state) => state.settings.chatFeatures);
  const { coreMessagingExperience, deeperUserEngagement, moderatorControls } = chatFeatures;

  const options = [];

  if (coreMessagingExperience.quotedReplies) {
    options.push({ label: 'Reply', action: 'reply' });
  }

  if (coreMessagingExperience.threadConversationAndReplies) {
    options.push({ label: 'Reply in Thread', action: 'thread' });
  }

  if (deeperUserEngagement.reactions) {
    options.push({ label: 'React', action: 'react' });
  }

  if (coreMessagingExperience.editMessage && message.sender.uid === currentUser.uid) {
    options.push({ label: 'Edit', action: 'edit' });
  }

  if (coreMessagingExperience.deleteMessage && message.sender.uid === currentUser.uid) {
    options.push({ label: 'Delete', action: 'delete' });
  }

  if (moderatorControls.reportMessage) {
    options.push({ label: 'Report', action: 'report' });
  }

  return <OptionsMenu options={options} />;
};
```

***

## Persisting Configuration

### Save Configuration to AsyncStorage

```tsx theme={null}
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useConfigStore } from './src/config/store';

const CONFIG_KEY = '@cometchat_builder_config';

export const saveConfig = async () => {
  try {
    const config = useConfigStore.getState();
    await AsyncStorage.setItem(CONFIG_KEY, JSON.stringify(config));
  } catch (error) {
    console.error('Failed to save config:', error);
  }
};

export const loadConfig = async () => {
  try {
    const savedConfig = await AsyncStorage.getItem(CONFIG_KEY);
    if (savedConfig) {
      const parsed = JSON.parse(savedConfig);
      useConfigStore.getState().updateConfig(parsed);
    }
  } catch (error) {
    console.error('Failed to load config:', error);
  }
};
```

### Auto-save on Configuration Changes

```tsx theme={null}
import { useEffect } from 'react';
import { useConfigStore } from './src/config/store';

const ConfigPersistence = () => {
  const config = useConfigStore((state) => state);

  useEffect(() => {
    // Debounce saves to avoid excessive writes
    const timeoutId = setTimeout(() => {
      saveConfig();
    }, 1000);

    return () => clearTimeout(timeoutId);
  }, [config]);

  return null;
};
```

***

## Layout Customization

### Dynamic Tab Configuration

```tsx theme={null}
import { useConfig } from './src/config/store';

const TabNavigator = () => {
  const layout = useConfig((state) => state.settings.layout);
  const { tabs, withSideBar } = layout;

  if (!withSideBar) {
    return <SingleChatView />;
  }

  return (
    <Tab.Navigator>
      {tabs.includes('chats') && (
        <Tab.Screen name="Chats" component={ChatsScreen} />
      )}
      {tabs.includes('calls') && (
        <Tab.Screen name="Calls" component={CallsScreen} />
      )}
      {tabs.includes('users') && (
        <Tab.Screen name="Users" component={UsersScreen} />
      )}
      {tabs.includes('groups') && (
        <Tab.Screen name="Groups" component={GroupsScreen} />
      )}
    </Tab.Navigator>
  );
};
```
