Skip to content

Desktop app: font selection doesn't work reliably (ghostty-web font loading) #12605

Closed as not planned

Description

@mrm007

Bug

Selecting a font in Desktop Settings → General → Font doesn't work reliably. Some fonts never render, others only render correctly after an app restart, and some work fine. The terminal falls back to IBM Plex Mono (the default) when it fails.

Investigation

Font wiring is correct

The three layers of the font system are internally consistent:

  1. @font-face registration (packages/ui/src/components/font.tsx) — bundles Nerd Fonts as woff2 and registers them (e.g. font-family: "Fira Code Nerd Font")
  2. Font family lookup (packages/app/src/context/settings.tsx) — monoFonts map references matching names (e.g. "Fira Code Nerd Font", ...)
  3. Terminal application (packages/app/src/components/terminal.tsx) — passes fontFamily to ghostty-web Terminal constructor and updates it reactively

The @font-face names and monoFonts lookup names match. The CSS custom property --font-family-mono is set correctly. The wiring is not the problem.

The problem: ghostty-web canvas rendering

The terminal uses ghostty-web (Ghostty compiled to WebAssembly), NOT xterm.js:

import type { Ghostty, Terminal as Term, FitAddon } from "ghostty-web"

The canvas renderer doesn't inherit CSS font-family — it needs fonts passed explicitly, which the code does. But there's no document.fonts.ready check before Terminal creation. The @font-face woff2 fonts use font-display: swap, meaning:

  1. Terminal is created immediately
  2. ghostty-web measures character cells and builds glyph cache using fallback font metrics
  3. Bundled woff2 fonts finish loading later
  4. ghostty-web never re-measures or rebuilds its glyph cache

This is a known class of bug with canvas-based terminal renderers and web fonts (see xtermjs/xterm.js#1164 for the xterm.js equivalent).

Evidence: font-specific behavior

Testing from the font dropdown:

Font Behavior
IBM Plex Mono ✅ Works (it's the default/fallback, always loaded)
Iosevka ✅ Works
Fira Code ❌ Falls back to IBM Plex Mono
Inconsolata ⚠️ Renders better after app restart (supports race condition theory)

Iosevka working suggests it loads faster or ghostty-web handles it differently. Inconsolata improving after restart supports the timing theory — cached/preloaded fonts from the previous session are available immediately on restart.

DOM elements also affected

The font issue isn't canvas-only. Inspecting the text input area shows:

  • Parent div has class .font-mono with font-family: var(--font-mono)
  • The CSS variable contains the correct font stack (e.g. "Fira Code Nerd Font", ...)
  • Yet the text input also renders in the fallback font

This suggests the @font-face woff2 fonts may not be loading/resolving correctly in the Tauri webview for all font families, or there's a timing issue affecting both DOM and canvas rendering.

Suggested fix

Wait for fonts to load before creating the Terminal:

// In terminal.tsx, before `new mod.Terminal(...)`:
await document.fonts.ready

const t = new mod.Terminal({
  fontFamily: monoFontFamily(settings.appearance.font()),
  // ...
})

And/or preload the selected font specifically:

const fontFamily = monoFontFamily(settings.appearance.font())
await document.fonts.load(`14px ${fontFamily}`)

Reproduction

  1. Open Desktop app → Settings → General → Font → select "Fira Code"
  2. Open a terminal tab
  3. Terminal renders in IBM Plex Mono despite the selection
  4. Switch to "Iosevka" → terminal renders correctly
  5. Switch back to "Fira Code" → falls back to IBM Plex Mono again

Environment

  • macOS Sequoia 15.7.3 (arm64, Apple M4)
  • OpenCode Desktop v1.1.53

Activity

  1. github-actions commented on Feb 7, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of or related to existing issues. Please check:

    The core issue is that the hardcoded font family names in the font selector use Nerd Fonts v2 naming conventions. These related issues suggest improving the font system overall by allowing dynamic/custom fonts rather than maintaining a hardcoded list.

    Feel free to ignore if these don't address your specific case.

  2. mrm007 commented on Feb 7, 2026

    @mrm007
    Author

    This isn't a feature request for custom fonts or a dynamic font system. It's a bug: the existing hardcoded names are wrong.

    The font selector already lists 11 Nerd Fonts. Users select one, expect it to work, and it silently falls back to IBM Plex Mono with no indication anything went wrong. The fix is updating the strings in the monoFonts map to match Nerd Fonts v3 naming — a one-line-per-entry change in packages/app/src/context/settings.tsx.

  3. changed the title [-]Desktop app: Nerd Font family names are outdated, all fall back to IBM Plex Mono[/-] [+]Desktop app: font selection doesn't work reliably (ghostty-web font loading)[/+] on Feb 7, 2026
  4. kud commented on Mar 30, 2026

    @kud

    I've got the same issue here. We can't customise the font of the terminal which breaks the glypicons used usually by nerd fonts.

  5. removed
    webRelates to opencode on web / desktop
    on May 3, 2026
  6. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions