The workspace terminal is rendered with xterm.js using a fixed font stack. Users who run NeoVim (and similar TUI tools) in the workspace terminal rely on Nerd Font glyphs for icons, statuslines, and prompts (Starship, Powerlevel10k, file explorers, etc.). Without a Nerd Font, those glyphs render as missing-character boxes.
Shipping a Nerd Font from the server is unnecessary if the browser can use a Nerd Font already installed on the user’s machine. Preferring popular local Nerd Fonts via local() gives the best experience for NeoVim/TUI users while keeping the existing monospace fallbacks for everyone else.
Approach
Use a CSS @font-face family that resolves to popular locally installed Nerd Fonts, then put that family first in the xterm.js fontFamily stack.
1. Define a local Nerd Font alias
Add a stylesheet used by the terminal component (today TerminalResourceReference only loads terminal.js + xterm assets; add a small terminal.css dependency, or an equivalent shared place that the terminal page loads) with:
local() matching is OS/browser-specific (family name vs PostScript name). Verify the listed names against common Nerd Font installs on macOS, Windows, and Linux; adjust names if needed after manual checks.
Scope this to the workspace terminal first (not every code / monospace surface), unless product decides to widen later.
2. Apply it in xterm.js (actual integration point)
The terminal font is not set via generic CSS code selectors. It is set in:
The current stack quotes 'Menlo, Courier' as one family name. That is a bug: the browser looks for a font literally named Menlo, Courier, so Menlo and Courier never participate as separate fallbacks. Correct quoting is unquoted Menlo, Courier (or 'Menlo', 'Courier'). Fix this in the same change.
Elsewhere in the UI the monospace stack already uses the correct form (Menlo, Courier, monospace).
4. Documentation (onedev/docs)
Update workspace / terminal docs so users know:
The terminal prefers a locally installed Nerd Font when available.
Which font family names are probed (the list above).
That users must install one of those fonts on the client machine (the machine running the browser), not inside the workspace container.
That without a matching local font, behaviour falls back to the existing monospace stack.
5. Test plan
Browser with JetBrainsMono Nerd Font (or another listed font) installed: NeoVim / Starship / nerd-font test glyphs render correctly in the workspace terminal.
Browser with no Nerd Font installed: terminal still usable with Consolas / Liberation Mono / Menlo / Courier / monospace; no layout breakage.
Confirm Menlo/Courier fallbacks work after the quoting fix on systems where Consolas / Liberation Mono are absent.
Spot-check macOS, Windows, and at least one Linux desktop browser for local() name resolution.
Out of scope
Bundling/serving a Nerd Font file from OneDev.
User-configurable font picker UI (can be a later improvement).
Follow-up from issue #2979.
Motivation
The workspace terminal is rendered with xterm.js using a fixed font stack. Users who run NeoVim (and similar TUI tools) in the workspace terminal rely on Nerd Font glyphs for icons, statuslines, and prompts (Starship, Powerlevel10k, file explorers, etc.). Without a Nerd Font, those glyphs render as missing-character boxes.
Shipping a Nerd Font from the server is unnecessary if the browser can use a Nerd Font already installed on the user’s machine. Preferring popular local Nerd Fonts via
local()gives the best experience for NeoVim/TUI users while keeping the existing monospace fallbacks for everyone else.Approach
Use a CSS
@font-facefamily that resolves to popular locally installed Nerd Fonts, then put that family first in the xterm.jsfontFamilystack.1. Define a local Nerd Font alias
Add a stylesheet used by the terminal component (today
TerminalResourceReferenceonly loadsterminal.js+ xterm assets; add a smallterminal.cssdependency, or an equivalent shared place that the terminal page loads) with:Notes:
local()matching is OS/browser-specific (family name vs PostScript name). Verify the listed names against common Nerd Font installs on macOS, Windows, and Linux; adjust names if needed after manual checks.code/ monospace surface), unless product decides to widen later.2. Apply it in xterm.js (actual integration point)
The terminal font is not set via generic CSS
codeselectors. It is set in:server-core/.../web/component/terminal/terminal.jsChange to something like:
Ensure the
@font-facestylesheet is loaded before/with the terminal soLocalNerdFontresolves when xterm measures glyphs.3. Fix existing font-stack quoting bug (same line)
The current stack quotes
'Menlo, Courier'as one family name. That is a bug: the browser looks for a font literally namedMenlo, Courier, so Menlo and Courier never participate as separate fallbacks. Correct quoting is unquotedMenlo, Courier(or'Menlo', 'Courier'). Fix this in the same change.Elsewhere in the UI the monospace stack already uses the correct form (
Menlo, Courier, monospace).4. Documentation (
onedev/docs)Update workspace / terminal docs so users know:
5. Test plan
nerd-fonttest glyphs render correctly in the workspace terminal.local()name resolution.Out of scope
Acceptance
'Menlo, Courier'quoting bug is fixed.