Skip to content

Commit deb0a5a

Browse files
author
Amos N.
committed
fonts: swap to Nerd-patched JetBrains Mono on mobile + web
The terminal renderer was drawing ?-in-a-box for every Powerline / devicon glyph in user prompts (P10k, Starship). Plain JetBrains Mono doesn't ship those Private-Use-Area glyphs. - Mobile: replace bundled JetBrainsMono-{Regular,Bold}.ttf with the Nerd Font Mono (single-cell) variants. Drop terminal fontSize 13→12 to stop P10k right-prompt wrapping on phone-width screens. - Web (relay): subset Nerd Font woff2 (ASCII + box drawing + full PUA) to ~400KB per weight, serve from /fonts/*.woff2 via wrangler [assets] binding, declare @font-face for both weights in the web client. - Deploy-relay: sync public/fonts and the [assets] block into the generated worker tarball so self-hosters get the same fix. Bumps mobile build to 1.0.0+12 for TestFlight upload.
1 parent aae6bd4 commit deb0a5a

9 files changed

Lines changed: 48 additions & 3 deletions

File tree

1.87 MB
Binary file not shown.
1.87 MB
Binary file not shown.

apps/mobile/lib/screens/terminal_screen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ class _TerminalScreenState extends State<TerminalScreen> {
579579
textStyle: const TerminalStyle(
580580
fontFamily: 'JetBrainsMono',
581581
fontFamilyFallback: ['Menlo', 'Courier New', 'monospace'],
582-
fontSize: 13,
582+
fontSize: 12,
583583
),
584584
theme: loopsyTerminalTheme,
585585
),

apps/mobile/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
1616
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
1717
# In Windows, build-name is used as the major, minor, and patch parts
1818
# of the product and file versions while build-number is used as the build suffix.
19-
version: 1.0.0+11
19+
version: 1.0.0+12
2020

2121
environment:
2222
sdk: ^3.10.4

packages/deploy-relay/scripts/sync-worker.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import { fileURLToPath } from 'node:url';
2020
const here = dirname(fileURLToPath(import.meta.url));
2121
const pkgRoot = dirname(here);
2222
const relaySrc = join(pkgRoot, '..', 'relay', 'src');
23+
const relayPublic = join(pkgRoot, '..', 'relay', 'public');
2324
const relayPkgJson = join(pkgRoot, '..', 'relay', 'package.json');
2425

2526
const workerOut = join(pkgRoot, 'worker');
2627
const workerSrcOut = join(workerOut, 'src');
28+
const workerPublicOut = join(workerOut, 'public');
2729

2830
async function copyDir(src, dest) {
2931
await fs.mkdir(dest, { recursive: true });
@@ -44,6 +46,19 @@ async function main() {
4446
// Copy worker TS source verbatim
4547
await copyDir(relaySrc, workerSrcOut);
4648

49+
// Copy static assets (Nerd-patched font woff2). Wrangler [assets] binding
50+
// serves these directly so the web client's /fonts/*.woff2 references
51+
// resolve without a CDN dependency on self-hosted deploys.
52+
try {
53+
await copyDir(relayPublic, workerPublicOut);
54+
} catch (err) {
55+
if (err && err.code === 'ENOENT') {
56+
// Older relay checkout without public/ — skip silently.
57+
} else {
58+
throw err;
59+
}
60+
}
61+
4762
// Pull versions from the relay's own package.json so we stay in sync.
4863
const relayPkg = JSON.parse(await fs.readFile(relayPkgJson, 'utf8'));
4964
const workersTypesVersion = relayPkg.devDependencies?.['@cloudflare/workers-types'] ?? '^4.20250410.0';
@@ -76,6 +91,12 @@ main = "src/index.ts"
7691
compatibility_date = "2025-04-01"
7792
compatibility_flags = ["nodejs_compat"]
7893
94+
# Static assets — Nerd-Font-patched woff2 served at /fonts/*.woff2.
95+
# Cloudflare matches assets first, falls through to the worker for everything
96+
# else.
97+
[assets]
98+
directory = "./public"
99+
79100
# Self-hosted deploys are app-only — '/' redirects to '/app' so the deploy
80101
# has no marketing surface. The loopsy.dev relay leaves this unset and
81102
# serves the landing page at '/'.
394 KB
Binary file not shown.
394 KB
Binary file not shown.

packages/relay/src/web-client.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,26 @@ export const WEB_CLIENT_HTML = /* html */ `<!doctype html>
2929
<title>${BRAND_NAME}</title>
3030
${FAVICON_LINKS}
3131
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
32-
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Inter:wght@400;500;600&display=swap" />
32+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" />
3333
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.min.css" />
3434
<style>
35+
/* Self-hosted Nerd-Font-patched JetBrains Mono so terminal prompts that
36+
emit Powerline/devicon glyphs (P10k, Starship) render correctly
37+
instead of falling back to ?-in-a-box. Subset to the Private Use
38+
Area + box drawing + ASCII to keep each weight ~400KB. Mono variant
39+
(single-cell glyphs) is required so prompt-width math stays correct. */
40+
@font-face {
41+
font-family: 'JetBrains Mono';
42+
font-weight: 400;
43+
font-display: swap;
44+
src: url('/fonts/jbm-mono-regular.woff2') format('woff2');
45+
}
46+
@font-face {
47+
font-family: 'JetBrains Mono';
48+
font-weight: 700;
49+
font-display: swap;
50+
src: url('/fonts/jbm-mono-bold.woff2') format('woff2');
51+
}
3552
${TOKENS_CSS}
3653
html, body {
3754
width: 100%; height: 100dvh;

packages/relay/wrangler.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ main = "src/index.ts"
33
compatibility_date = "2025-04-01"
44
compatibility_flags = ["nodejs_compat"]
55

6+
# Static assets (web client font files). Cloudflare matches assets first
7+
# before invoking the Worker, so /fonts/* short-circuits to the woff2 file
8+
# without touching our fetch handler. Everything else (WS, /app, /pair, etc.)
9+
# falls through to src/index.ts as before.
10+
[assets]
11+
directory = "./public"
12+
613
# Keep the *.workers.dev URL alive in addition to the custom domain — paired
714
# phones from the pre-loopsy.dev era keep their connections working.
815
workers_dev = true

0 commit comments

Comments
 (0)