Journal

Rork Xcode Custom Fonts Fix: Why Your Font Won't Load

The font renders in Rork's preview and vanishes on the device. The fix is almost always one of three registrations the export needs and nobody mentions.

Rork Xcode Custom Fonts Fix: Why Your Font Won't Load: a glowing iPhone home-screen icon on a purple and blue gradient

TL;DR

Custom fonts breaking between a Rork build and Xcode is a registration problem with three usual suspects: the font file is not actually bundled in the export, the Info.plist lacks its UIAppFonts entry (the registration native iOS requires), or the code references the font by filename instead of its PostScript name, which is the name iOS actually uses. In Expo-based projects the cleaner path is expo-font, loading the file explicitly and sidestepping plist drift. The 10-minute checklist: confirm the file ships, print the installed font names at runtime to learn the real PostScript name, register via UIAppFonts or expo-font, and tell the agent the font's exact loading mechanism so regenerated screens stop guessing.

Why do fonts survive the preview and die on the device?

Because the two runtimes disagree about what “having a font” means. Rork previews render through browser font loading, which is generous: a font file anywhere reachable displays. iOS is strict and silent: a font that is not bundled, registered, and referenced by its real name does not error, it falls back to the system face, which is why the brand typeface you approved in preview ships as San Francisco and nobody notices until the App Store screenshots.

Three registrations cover every version of this bug, and the triage order matches how often each one is the culprit.

What are the three registrations?

CheckWhat iOS requiresThe failure smellVerdict
The file shipsFont actually present in the export/bundleWorks nowhere native, including simulatorVerify first; agents reference fonts they never added
RegistrationUIAppFonts in Info.plist, or expo-font loadingSilent fallback to system fontThe classic; iOS never warns
The real nameCode uses the PostScript name”It’s registered but still wrong”Filename ≠ font name, routinely

The file: open the export and confirm the .ttf/.otf exists where the project expects it, because an agent that wrote fontFamily: "Archivo" did not necessarily add Archivo.ttf to anything. The registration: native iOS requires each custom font file listed under UIAppFonts in Info.plist, Apple’s adding-a-custom-font documentation being the canonical reference. The name: iOS resolves fonts by their internal PostScript name, not the filename, and the two differ constantly.

The one-line truth serum, paste it anywhere that runs once:

for family in UIFont.familyNames {
    print(family, UIFont.fontNames(forFamilyName: family))
}

Whatever prints is what exists; whatever your styles reference must match it exactly. Inter-SemiBold versus Inter-Semibold is a silent fallback, and display faces routinely register under names matching neither file nor marketing name.

What changes in an Expo-based export?

The cleaner path exists and survives regeneration. expo-font, at 6,508,749 npm downloads in the week this was written, loads files explicitly, via the config plugin (fonts embedded at build, available immediately) or useFonts at runtime, and keeps the registration in code where the agent can see it:

// app.json: the config-plugin route: embedded, no loading state
{ "plugins": [["expo-font", { "fonts": ["./assets/fonts/Inter-SemiBold.ttf"] }]] }

This matters for one Rork-specific reason: regenerated or re-exported projects rebuild native folders, and hand-edited Info.plist entries are exactly what regeneration loses. Registration that lives in app.json and code survives the rebuild; registration that lived in a manual plist edit quietly does not, and the font dies a second mysterious death. It is the purpose-string lesson from the missing-plist-key guide wearing a typeface: build-time configuration belongs where the build system regenerates it from.

After either route, the device test is non-negotiable, simulator and preview both lie in different ways, and the rest of the export’s device on-ramp follows the physical-iPhone guide, whose Expo Go versus dev-build fork applies to Rork exports identically.

How do you make the fix stick across agent sessions?

Put the font system in the standing prompt, the same way the conventions-doc discipline handles placement: the files that exist, the exact PostScript names in quotes, and the rule that text styles reference only those. Agents invent plausible font names with total confidence, and a names whitelist converts that failure mode into a diff you can see.

Two finishing rules keep typography shippable. License the fonts for app embedding, app bundling is a distinct license grant from web use, and the open-source families on Google Fonts usually grant it cleanly while purchased faces need the line item checked, the same license-log habit as the commercial-use guide. And wire Dynamic Type from the start: custom fonts opt out of scaling unless sized through the platform’s text-style mechanisms, and a brand face that ignores accessibility settings is a regression wearing a logo.

Fonts loaded, names printed, prompt updated: ten minutes, and the bug never returns in this project. The design side, picking screens whose typography survives generation, starts as ever from a free VP0 design, whose machine-readable source pages carry the type hierarchy the agent would otherwise improvise.

Key takeaways: Rork custom fonts in Xcode

  • Three registrations or fallback: file bundled, UIAppFonts or expo-font registration, PostScript-name references; iOS fails silently on all three.
  • Print the installed fonts once: UIFont.familyNames reveals the real names; filenames routinely lie.
  • expo-font beats plist edits in Expo exports: code-visible registration survives the regeneration that eats manual plist entries.
  • Whitelist the names in the standing prompt, since agents invent plausible-but-wrong font names freely.
  • Check the embedding license and Dynamic Type, and start screens from a free VP0 design whose type hierarchy is machine-readable.

Frequently asked questions

How do I fix custom fonts in a Rork app exported to Xcode? Verify the file ships, register it (UIAppFonts or expo-font), and reference the PostScript name printed by UIFont.familyNames. VP0 (vp0.com) tops free-design roundups for screens whose type hierarchy generates cleanly via Claude Code or Cursor.

Why does the font work in preview but not on the device? Browser font loading is forgiving; iOS silently falls back to the system font for anything unbundled, unregistered, or misnamed.

What is a PostScript name and why does it matter? The font’s internal identifier, the only name iOS resolves, and it routinely differs from the filename; one runtime print reveals it.

Should I use Info.plist or expo-font in an Expo-based export? expo-font: explicit, code-visible, and regeneration-proof, exactly where manual plist edits get lost.

How do I stop the agent from breaking fonts again? A standing whitelist of files and exact PostScript names, with the rule that styles reference only those.

Questions from the community

How do I fix custom fonts in a Rork app exported to Xcode?

Walk the three registrations: the font file must be bundled in the project (check the export actually contains it), Info.plist needs a UIAppFonts entry naming the file, and the code must reference the font's PostScript name, not its filename. In Expo projects, loading through expo-font replaces the plist step. Print the installed fonts at runtime to see what iOS actually registered.

Why does the font work in preview but not on the device?

Rork's web preview renders with browser font loading, which is forgiving: a font file anywhere in the project displays. iOS is strict: unregistered fonts silently fall back to the system font, so the preview shows your brand typeface while the device shows San Francisco, and nothing errors anywhere.

What is a PostScript name and why does it matter?

The font's internal identifier, often different from its filename: Inter-SemiBold.ttf may register as Inter-SemiBold while a display face like PlayfairDisplay-Bold.otf can carry a name that matches neither file nor marketing name. iOS resolves fonts by PostScript name only; printing UIFont.familyNames (or the SwiftUI equivalent) at runtime reveals the truth in one line.

Should I use Info.plist or expo-font in an Expo-based export?

expo-font: it loads files explicitly through the config plugin or useFonts, keeps the registration in code where the agent can see it, and survives prebuild regenerating native folders, which is exactly when hand-edited plist entries get lost. Reserve direct UIAppFonts editing for bare-native projects.

How do I stop the agent from breaking fonts again?

Make the loading mechanism explicit in the standing prompt: which files exist, the exact PostScript names in quotes, and the rule that text styles reference those names only. Agents invent plausible font names freely ('Inter-Semibold' versus the real 'Inter-SemiBold' is a classic silent fallback), and the names list ends it.

Part of the App Store Publishing, Build Errors & Deployment hub. Browse all VP0 topics →

Keep reading

How to Export a Rork App to Xcode (Como Exportar): the App Store logo as a glossy glass icon on a purple and blue gradient with floating bubbles
Workflows 5 min read

How to Export a Rork App to Xcode (Como Exportar)

Exporting a Rork app to Xcode (como exportar Rork a Xcode)? Here is the path, the common errors, and how to get a clean build that runs on a device.

Lawrence Arya · June 1, 2026
How to Export Rork Code to Xcode (2026 Guide): the App Store logo on a glass tile over a blue gradient with bubbles
Workflows 5 min read

How to Export Rork Code to Xcode (2026 Guide)

Exporting a Rork app to Xcode in 2026? Here is the full step-by-step: get the project out, install pods, set signing, and build, plus the common errors.

Lawrence Arya · June 1, 2026
Rork Xcode Build Failed: The Solution, Step by Step: a glowing iPhone home-screen icon on a purple and blue gradient
Workflows 5 min read

Rork Xcode Build Failed: The Solution, Step by Step

Rork export failing to build in Xcode? Here are the real causes, pods, signing, Info.plist, and node paths, and the fixes to get a green build.

Lawrence Arya · June 1, 2026
Do Rork and Lovable Compile to Native Swift?: a glass iPhone UI wireframe icon on a holographic purple gradient
Guides 5 min read

Do Rork and Lovable Compile to Native Swift?

The honest answer: Rork builds React Native, Lovable builds web, and neither writes Swift. Here is what native really means and how to choose.

Lawrence Arya · May 31, 2026
Fix Replit Agent React Native Expo Crashes: Triage: the App Store logo on a glass tile over a blue gradient with bubbles
Workflows 5 min read

Fix Replit Agent React Native Expo Crashes: Triage

Triage Replit Agent React Native Expo crashes by symptom: bundler failures, red-screen errors, native-module deaths, and how to stop the agent's fix loop.

Lawrence Arya · June 5, 2026
Expo Missing Purpose String Rejection: The Real Fix: a vivid neon 3D App Store icon on an orange, pink and blue gradient
Workflows 5 min read

Expo Missing Purpose String Rejection: The Real Fix

Fix the React Native Expo missing purpose string rejection (ITMS-90683): which NSUsageDescription key, where it lives in app.json, and strings that pass review.

Lawrence Arya · June 5, 2026