Skip to content

GrzywN/expo-plugins-exercise

Repository files navigation

expo-plugins-exercise

Learning project: build an Expo config plugin that natively links TTF icon fonts for iOS & Android.

What It Does

  • Links TTF fonts to iOS (Xcode Copy Bundle Resources + UIAppFonts) & Android (assets/fonts/)
  • Patches the PostScript name embedded in each TTF to match its filename — so fontFamily works identically on both platforms, even when multiple fonts share the same internal name (common with fontello exports)
  • Ships a standalone script to patch fonts manually before committing

Project Structure

plugins/
  withIconFont.ts          # Expo config plugin — links fonts to iOS & Android
scripts/
  patchFontName.ts         # Patches PostScript names in TTF files in-place
assets/fonts/brix/
  filled-icon-font.ttf
  line-rounded-icon-font.ttf
  line-square-icon-font.ttf
src/components/brix-icons/
  BrixFilledIcon.tsx        # <BrixFilledIcon name="home" size={24} color="#000" />
  BrixLineRoundedIcon.tsx
  BrixLineSquareIcon.tsx
  IconShowcase.tsx          # Grid layout used by each tab

Getting Started

1. Patch Font Names

Run this once after downloading new fonts. It modifies each TTF in-place so the PostScript name matches the filename.

npm run patch-fonts -- assets/fonts/brix/*.ttf

Commit the patched TTF files.

2. Register Fonts in the Plugin

Add font paths to app.config.ts:

withIconFont(config, {
  fonts: [
    './assets/fonts/brix/filled-icon-font.ttf',
    './assets/fonts/brix/line-rounded-icon-font.ttf',
    './assets/fonts/brix/line-square-icon-font.ttf',
  ],
})

3. Run Prebuild

npx expo prebuild

The plugin copies each font to the correct native directory and registers it.

4. Use in React Native

import { BrixFilledIcon } from '@/components/brix-icons/BrixFilledIcon';

<BrixFilledIcon name="home" size={24} color="#333" />

fontFamily maps to the filename without extension — filled-icon-font, line-rounded-icon-font, line-square-icon-font — on both iOS & Android.

How the Plugin Works

iOS

  1. withInfoPlist — adds each filename to UIAppFonts so CoreText registers the font
  2. withXcodeProject — copies the TTF to ios/<AppName>/Fonts/ & adds it to Copy Bundle Resources via IOSConfig.XcodeUtils.addResourceFileToGroup

Android

withDangerousMod — copies the TTF to android/app/src/main/assets/fonts/. React Native resolves fonts by filename on Android, so no additional registration is needed.

Why Patch the PostScript Name?

iOS identifies fonts by their PostScript name (nameID 6 in the TTF name table), not by filename. Fontello exports all ship with PostScript name fontello — load 3 of them at once and only 1 is accessible. The patcher rebuilds the name table in memory, replacing nameIDs 1, 4 & 6 with the filename, then recomputes the table & head.checkSumAdjustment checksums.

Scripts

Command Description
npm run patch-fonts -- <file.ttf> Patch PostScript name to match filename
npx expo prebuild Generate native projects with fonts linked
npm run ios Build & run on iOS
npm run android Build & run on Android

About

Learning project: Expo config plugin for native TTF icon font linking (iOS + Android)

Topics

Resources

Stars

Watchers

Forks

Contributors