ankitects / ankitects/anki

PROPOSAL: Bundle and apply brand fonts (Reddit Sans / Mukta) across UI and Svelte pages

Open
#5,219 2 comments 0 reactions 1 assignee Claimed by @ianoff View on GitHub
Dominant language
Rust
Stars
31.2k
Forks
3.2k
Avg merge
2d 8h
Merged PRs (30d)
72

Description

### Summary
Adopt the new brand typefaces — **Reddit Sans** (headers/titles) and **Mukta** (body text) — across the desktop app's native Qt chrome and SvelteKit-rendered pages (stats/graphs, deck options, editor UI, congrats, import dialogs, etc.).

### Background
Neither surface currently has an explicit font direction:
- Web/Svelte pages set `body { font-family: inherit }` ([[base.scss:47](https://claude.ai/epitaxy/anki/ts/lib/sass/base.scss)](anki/ts/lib/sass/base.scss)) and inherit whatever Qt injects.
- Qt injects a different hardcoded/system font per platform in `AnkiWebView.standard_css()` ([[webview.py:581](https://claude.ai/epitaxy/anki/qt/aqt/webview.py)](anki/qt/aqt/webview.py)) — Segoe UI on Windows, hardcoded `"Helvetica"` on Mac, GTK theme font on Linux.
- Native Qt widgets (menus, dialogs, toolbars) have no app-wide font set at all — `QApplication.setFont()` / `QFontDatabase.addApplicationFont()` are unused anywhere in the codebase.

Result: inconsistent, platform-dependent typography with no brand identity.

### Explicitly out of scope
- **The card reviewer surface is excluded.** No font changes to `ts/reviewer/reviewer.scss` / `reviewer_extras.scss` or the review webview.
- The per-notetype "card font" (user-configurable template font in Card Layout / Fields, `clayout.py` / `fields.py`) is unrelated and must not be touched.

### Font weights to bundle
- **Reddit Sans** (headers): **Extra Bold**, **Semi Bold**, **Regular** — Extra Bold preferred as the default heading weight, per brand guidelines; Semi Bold/Regular used in places seen in the brand guide.
- **Mukta** (body): **Light**, **Regular**, **Bold**, and *Italic*.

### Fallback stack
`font-family: "Reddit Sans", Helvetica, Arial, sans-serif;` for headers and `font-family: "Mukta", Helvetica, Arial, sans-serif;` for body — a generic sans-serif fallback is sufficient for any weight/glyph gaps (e.g. missing CJK coverage); no special-casing needed.

### Proposed approach
1. **Bundle font assets** — add Reddit Sans / Mukta (e.g. via `@fontsource/*` npm packages), restricted to the weights above, and wire a new `CopyFiles` build action in `build/configure/src/web.rs` + `aqt.rs`, following the existing MathJax/MDI-icon precedent. Reference via CSS `url()`, not JS import (esbuild has no woff loader configured).
2. **Licensing** — add npm deps, run `just fix-minilints` to auto-populate `ts/licenses.json` (both fonts are SIL OFL, no AGPL conflict).
3. **Web/Svelte side** — add font-family tokens to `_vars.scss` / `_root-vars.scss` (e.g. `--font-family-heading` → Reddit Sans Extra Bold + fallback stack, `--font-family-body` → Mukta Regular + fallback stack, with Semi Bold/Regular/Bold/Light/Italic available as needed); update `base.scss`'s `body { font-family: inherit }` to the new stack. Cascades to all SvelteKit routes via `+layout.svelte` → `base.scss` in one change.
4. **Qt embedded webviews** — update `AnkiWebView.standard_css()` to inject the bundled fonts (with fallback stack) instead of the current per-platform fallback (still excluding the reviewer webview specifically).
5. **Qt native chrome** — load the fonts via `QFontDatabase.addApplicationFont()` at startup and apply via `QApplication.setFont()` and/or a `font-family` rule added to the QSS in `ThemeManager._apply_style()` ([[theme.py:246](https://claude.ai/epitaxy/anki/qt/aqt/theme.py)](anki/qt/aqt/theme.py)), with the same fallback stack.

### Files likely touched
`build/configure/src/web.rs`, `build/configure/src/aqt.rs`, `package.json`, `ts/licenses.json` (auto), `ts/lib/sass/_vars.scss`, `ts/lib/sass/_root-vars.scss`, `ts/lib/sass/base.scss`, `qt/aqt/webview.py`, `qt/aqt/theme.py`, `qt/aqt/main.py`.

### Acceptance criteria
- [ ] Reddit Sans Extra Bold renders for primary headings, with Semi Bold and Regular available as secondary heading weights, on all Svelte-rendered pages except the reviewer.
- [ ] Mukta Regular renders for body text, with Light, Bold, and Italic variants available and applied where the design calls for them.
- [ ] Native Qt dialogs/menus/toolbars render in the new fonts on Windows, Mac, and Linux.
- [ ] Helvetica/Arial/sans-serif fallback applies cleanly when a glyph or weight isn't covered by the bundled fonts.
- [ ] Reviewer surface is visually unchanged.
- [ ] Per-notetype card font setting is unaffected.
- [ ] Fonts render correctly fully offline (no CDN dependency).
- [ ] License entries for the new font packages appear correctly in `ts/licenses.json`.

### Risks / open questions
- None outstanding — weight set now covers Extra Bold/Semi Bold/Regular (headers) and Light/Regular/Bold/Italic (body), with Helvetica/Arial/sans-serif as an accepted fallback for any gaps.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.