Skip to content

Default the site chrome to a readable system sans font - #31

Closed
ulziibay-kernel wants to merge 2 commits into
mainfrom
hypeship/readable-default-font
Closed

ulziibay-kernel wants to merge 2 commits into
mainfrom
hypeship/readable-default-font

Conversation

@ulziibay-kernel

@ulziibay-kernel ulziibay-kernel commented Oct 28, 2026 •

Copy link
Copy Markdown

What

The whole site chrome (homepage, /docs, /bookmarks, /login, verify pages, 404s, viewer shell + comments rail, history viewer, in-doc comment overlay) rendered every word in ui-monospace at 14px — the locked "man-page brand". That's hard to read, especially on mobile.

The default is now the tried-and-tested system UI stack — -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif (the GitHub/Bootstrap lineage) at 16px / 1.6:

  • native rendering per platform (SF on macOS/iOS, Segoe UI on Windows, Roboto on Android), nothing to download, best readability on desktop and mobile
  • monospace stays where it means something: the copy-paste prompt boxes, inline code, and the history diff pane
  • all prose that lived in <pre> (hard-wrapped at ~70 chars) is now real <p> paragraphs, so text reflows properly instead of breaking mid-line
  • the space-padded footer justification becomes a flex space-between row, so it stays flush at any viewport width
  • the viewer's comment rail chrome switches to sans; comment bodies keep their Georgia serif, inline code chips stay mono
  • the man-page structure is untouched: JUSTHTML.SH(1) headline, uppercase section heads, hanging indents, quiet footer

Docs that set no font now fall back to the same sans stack

Doc HTML renders byte-pristine in the sandboxed iframe, so a doc with no font-family of its own fell back to the browser default serif — visibly different from the chrome. In the shell-embedded render (the /d/:slug viewer), we now inject the system sans stack as a last-resort default when the doc has no authored font rule (lib/docs/font-fallback.ts):

  • detection looks at real CSS contexts only — inline <style> blocks and style="" attributes; prose or code samples that merely mention font-family don't count
  • the injected rules use :where() (zero specificity), so any author CSS wins anyway
  • docs that set a font are served untouched; direct /raw fetches stay byte-pristine (the fallback rides the shell variant, like the comment overlay)

Intentionally not changed

  • auth emails (lib/auth/email.ts) — monospace email brand, out of scope for site readability
  • the OG preview image — its own aesthetic
  • docs that set their own font — "the document you publish is the document people see" still holds

Note

This overrides the earlier "always light, monospace" chrome decision documented in the code comments (the man-page layout itself is kept). Happy to revert if the mono look was load-bearing.

Verification

  • npm test: 220/220 pass; tsc --noEmit clean; next build clean
  • rendered homepage, /login, and the 404 locally at 1280×900 and 390×844: body computes to the sans stack at 16px on both, prompt boxes still compute to ui-monospace, footer flush to both edges, login input→button gap preserved (19px), no horizontal overflow on mobile
  • end-to-end against a local Postgres: a fontless public doc renders in the sans stack inside the viewer iframe (injected style present, computed font -apple-system), and a Georgia-styled doc keeps Georgia with no injection

Note

Low Risk
Presentation and optional iframe font injection only; auth and /raw byte-pristine behavior are explicitly preserved and tested.

Overview
Replaces the locked monospace man-page brand (14px everywhere) with the system UI sans stack at 16px / 1.6 across shared chrome: lib/page.ts exports SANS/MONO, manPage() and the homepage, login/docs/bookmarks/404 surfaces, root layout, verify pages, and React not-found/history shells.

Prose markup moves from hard-wrapped <pre> to <p> so copy reflows; monospace stays on prompt boxes, inline code, and the history diff pane. Footers switch from character-padded <pre> lines to a flex space-between row. List rows on /docs and /bookmarks drop <pre> wrappers in favor of normal inline links + tails.

Viewer shell (CommentsShell, overlay chips/popover, history chrome) uses sans for UI; comment bodies remain serif. lib/docs/font-fallback.ts injects a low-specificity default sans (and mono for code elements) into fontless published HTML only when served as /d/:slug/raw?overlay=1; direct /raw responses stay byte-identical. Vitest covers fallback detection and raw-route injection behavior.

Reviewed by Cursor Bugbot for commit b633fb9. Bugbot is set up for automated code reviews on this repo. Configure here.

The man-page chrome rendered all prose in 14px monospace, which is hard
to read on desktop and mobile. Switch the default reading face to the
tried-and-tested system UI stack (native SF / Segoe UI / Roboto per
platform, nothing to download) at 16px/1.6, and convert the pre-based
prose to real paragraphs. Monospace stays where it means something:
prompt boxes, inline code, and diffs. The space-padded footer becomes a
flex row so it stays flush at any width.

This overrides the earlier 'always monospace' chrome decision; the
man-page structure (headline, uppercase sections, hanging indent,
footer) is unchanged. Auth emails and the OG preview image keep their
own fonts.
@vercel

vercel Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
justhtml Ready Ready Preview Oct 28, 2026 7:34pm UTC

A doc's HTML renders byte-pristine in the sandboxed iframe, so a doc
with no font-family of its own fell back to the browser default serif —
noticeably different from the site's sans chrome. In the shell-embedded
render (the /d/:slug viewer), inject the system sans stack as a
last-resort default when the doc has no authored font rule (inline
<style> blocks and style attributes; prose or code samples that merely
mention font-family don't count). The injected rules use :where() so any
author CSS wins, and direct /raw fetches stay byte-pristine like the
comment overlay.
Comment thread lib/docs/font-fallback.ts
// or a style="" attribute. Prose or code samples that merely mention
// "font-family" must not count — a doc about CSS is not a styled doc.
function hasAuthoredFont(html: string): boolean {
const blocks = html.match(/<style[^>]*>[\s\S]*?<\/style>/gi) ?? [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A published document containing repeated unclosed <style> tags makes each shell render synchronously perform a quadratic scan, allowing repeated public requests to exhaust server CPU.

Fix on Vercel

This branch was successfully deployed

1 active deployment
Preview — b633fb9c Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant