vercel-labs / vercel-labs/native

Canvas: support native macOS system fonts

Open
#232 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Zig
Stars
7.7k
Forks
314
Avg merge
5h
Merged PRs (30d)
13

Description

Problem

Canvas typography currently cannot explicitly select the native macOS system font.

With Native SDK CLI 0.6.2, setting:

tokens.typography.font_id = canvas.default_sans_font_id;
tokens.typography.font_family = .system_sans;

does not make Canvas text use SF Pro. FontFamily.system_sans only maps to the CSS name system-ui, while the macOS Canvas packet carries a font_id. In appkit_host.m, the built-in resolver for the default sans IDs tries Geist family names first and only falls back to [NSFont systemFontOfSize:] when Geist is unavailable.

Registering a TTF is not an equivalent workaround: Apple's system font is not a font apps should bundle, and a bundled face loses the native metrics/rendering chosen by macOS.

Expected behavior

Provide an explicit Canvas-native way to select system fonts, for example reserved system sans/mono font IDs or a family channel that reaches native text measurement and drawing:

  • system_sans resolves through NSFont systemFontOfSize:weight: on macOS
  • system_mono resolves through NSFont monospacedSystemFontOfSize:weight:
  • medium, bold, italic, and bold-italic span variants stay in the same system family
  • measurement and drawing use the same resolver
  • existing Geist defaults remain unchanged for apps that do not opt in

Reproduction

  1. Create a macOS Canvas app with Native SDK 0.6.2.
  2. Set typography.font_family = .system_sans and keep default_sans_font_id.
  3. Render text while Geist is available.
  4. The rendered face remains Geist rather than the macOS system face.

Relevant current implementation:

  • src/primitives/canvas/tokens.zig: FontFamily.system_sans maps to system-ui
  • src/platform/macos/appkit_host.m: NativeSdkBuiltInFontForFontId prioritizes Geist for default sans IDs; NativeSdkPacketPreferredFont resolves only the packet font ID

This would let native Canvas apps use the platform's intended typography without shipping a substitute TTF.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/primitives/canvas/tokens.zig to trace the system_sans family mapping, then inspect NativeSdkBuiltInFontForFontId and NativeSdkPacketPreferredFont in src/platform/macos/appkit_host.m. Define the native system-font selection and ensure measurement and drawing use the same resolver, while preserving existing Geist defaults. Done when the requested sans and mono variants select the corresponding macOS fonts and retain their span variants.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, zig
Domain
desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.