| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
why: Test font deployment before merging to master. what: - Add docs-fonts to push trigger branches (revert after verification)
why: Standardize on IBM Plex Sans / Mono across projects without committing ~227KB of binary font files to the repo. what: - Add sphinx_fonts extension that downloads fonts at build time, caches in ~/.cache/sphinx-fonts/, and generates @font-face CSS - Configure IBM Plex Sans (400/500/600/700) and IBM Plex Mono (400) with CSS variable overrides for Furo theme - Add actions/cache step in docs workflow for font cache persistence - Gitignore generated font assets in docs/_static/
why: Furo sets --font-stack on body, which overrides :root via direct declaration. Our fonts.css loaded but never rendered. what: - Change CSS variable selector from :root to body in _generate_css() - Same specificity + later source order ensures our override wins
why: The browser doesn't discover font URLs until it parses fonts.css, which itself must wait for the HTML to load. This creates a waterfall (HTML → CSS → font download) that causes a visible Flash of Unstyled Text (FOUT) — the page renders with system fallback fonts, then swaps to IBM Plex once the fonts arrive. Preload hints in <head> tell the browser to start downloading fonts immediately, in parallel with CSS parsing, so fonts arrive before first paint and the swap is invisible. what: - Add sphinx_font_preload config option to sphinx_fonts extension accepting (family, weight, style) tuples for selective preloading - Compute preload filenames in _on_builder_inited() and pass them to templates via html-page-context event handler - Emit <link rel="preload" as="font" type="font/woff2" crossorigin> tags in page.html template's extrahead block - Preload only 3 critical above-the-fold weights: Sans 400 (body), Sans 700 (headings), Mono 400 (code) — other variants load on demand - Rename layout.html → page.html and extend !page.html instead of !layout.html — Furo theme blocks layout.html inheritance (its layout.html is deliberately an error page) note: The original approach used Sphinx's add_css_file() for preload tags, but Sphinx appends ?v=<hash> query strings to those URLs. The @font-face declarations in fonts.css reference fonts without query strings, so the browser treated them as different resources — downloading each font twice and defeating the preload entirely. The template-based approach produces URLs without query strings, matching @font-face exactly: one download, zero FOUT.
why: IBM Plex's OpenType features (kern, liga) weren't being leveraged, and code blocks inherited prose text-rendering that can break monospace grid alignment. what: - Add font-kerning, font-variant-ligatures, letter-spacing to body - Add optimizeSpeed + kerning/ligature/spacing resets for pre/code/kbd/samp
why: Every <img> on the docs site lacked dimension hints, causing Cumulative Layout Shift (CLS) on page load — content jumped as images rendered. External badge images (shields.io, Codecov) were especially slow, and the 447KB demo GIF blocked rendering on hard refresh. what: - Add :width:, :height:, :loading: lazy to image directives in index.md (888×589), cli/shell.md (878×109), developing.md (1030×605) - Add CSS aspect-ratio per image to reserve proportional space before load; override docutils inline height with height: auto !important so Furo's max-width: 100% scales without distortion - Add content-visibility: auto on all img for off-screen decode skip - Add CSS height: 20px for shields.io / badge.svg / codecov.io badges to prevent 0→20px shift while external images load - Add sidebar/brand.html template override with width="200" height="200" decoding="async" on logo <img> (above-fold, no lazy loading)
why: Every page navigation re-downloads and re-parses 8 CSS files, 7 JS files, 3 fonts, re-renders the sidebar, SVG icons, and the entire layout. Only the article content, right-panel TOC, and active sidebar link actually change between pages. what: - Create docs/_static/js/spa-nav.js (~170 lines, vanilla JS, no deps) - Intercept internal link clicks via event delegation on document - Fetch target page, parse with DOMParser, swap three DOM regions: .article-container, .sidebar-tree, .toc-drawer - Preserve sidebar scroll position, theme state, all CSS/JS/fonts - Replicate Furo's cycleThemeOnce for swapped .content-icon-container - Inject copy buttons on new code blocks via cloneNode from template (ClipboardJS event delegation picks up new .copybtn elements) - Minimal scrollspy (~25 lines) replaces Gumshoe for swapped TOC - AbortController cancels in-flight fetches on rapid navigation - history.pushState/popstate for back/forward browser navigation - Debounced prefetch on hover (65ms) for near-instant transitions - Progressive enhancement: no-op if fetch/DOMParser/pushState absent - Skip interception for search.html, genindex, external links, modifier-key clicks, download attrs, and #sidebar-projects links - Fallback to window.location.href on network error or missing DOM - Register script in conf.py setup() with loading_method="defer"
Codecov Report❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
@@ Coverage Diff @@
## master #1022 +/- ##
==========================================
- Coverage 81.01% 81.01% -0.01%
==========================================
Files 28 28
Lines 2623 2628 +5
Branches 492 492
==========================================
+ Hits 2125 2129 +4
- Misses 367 368 +1
Partials 131 131 ☔ View full report in Codecov by Sentry.
|
Sorry, something went wrong.
…flow why: font-display: swap causes visible text reflow when IBM Plex loads because the system fallback (Arial) has different character dimensions. what: - Add sphinx_font_fallbacks config with size-adjust/ascent/descent overrides - Generate fallback @font-face declarations in fonts.css (Capsize formula) - Include fallback families in --font-stack CSS variables
why: badges flash in from zero width because width: auto computes to 0 before the image loads, causing cumulative layout shift. what: - Add min-width: 60px to reserve approximate badge width - Add border-radius: 3px matching shields.io badge shape - Add background placeholder that disappears behind loaded badge
why: all links render with class="current" then JS replaces the hostname-matching link with a bold span, causing a visible reflow when IBM Plex fonts load with different metrics than the fallback. what: - Remove misleading class="current" from all project links - Hide #sidebar-projects until JS resolves active state (.ready class) - Use textContent instead of innerHTML for safer DOM manipulation
…sfade why: SPA navigation instantly replaces DOM content, causing a jarring visual jump between pages instead of a smooth transition. what: - Wrap swap+reinit in document.startViewTransition() when available - Add 150ms crossfade animation via ::view-transition pseudo-elements - Progressive enhancement: unsupported browsers get instant swap
why: The view transitions block was inserted between the "Image layout shift prevention" section header and its rules, orphaning the comment. what: - Move view transitions comment + rules to end of file - Keep image section header contiguous with its img/badge rules
why: Image is below the fold; lazy loading defers fetch until needed. what: - Add :loading: lazy to the figure directive in about_tmux.md
why: font-display swap causes visible text reflow (FOUT). Matching the tony.nl/cv approach: block rendering until preloaded fonts arrive, and inline the @font-face CSS to eliminate the extra fonts.css request. what: - Change font-display from swap to block - Move @font-face CSS from external fonts.css to inline <style> in <head> - Use pathto() in template for correct relative font URLs at any page depth - Remove _generate_css() function (CSS now generated in Jinja template)
| Back | FazBrowse Home | New Git URL |
Summary
Overhaul the docs frontend for faster, smoother page loads:
Fonts
sphinx_fonts extension downloads fonts at build time, caches in ~/.cache/sphinx-fonts/, generates @font-face CSS, and overrides Furo's CSS variables on body (not :root — Furo's body declarations win otherwise). Three critical weights are preloaded via <link rel="preload"> in the template to avoid FOUT. The template approach avoids Sphinx's ?v= query string on add_css_file() URLs, which caused double downloads when the @font-face URLs didn't match.
Fallback metrics: System font stacks (-apple-system, Segoe UI, etc.) get size-adjust, ascent-override, descent-override, and line-gap-override values derived from Capsize metrics. This ensures the fallback font occupies the same space as IBM Plex, eliminating visible text reflow when the web font loads.
Typography
Body text gets font-kerning: normal, font-variant-ligatures: common-ligatures, and letter-spacing: -0.01em to tighten IBM Plex's slightly wide default tracking. Code blocks (pre, code, kbd, samp) override these with optimizeSpeed, font-kerning: none, and letter-spacing: normal to preserve fixed-width grid alignment.
Heading scale follows a Biome-inspired approach: medium weight (500) throughout, with size and spacing carrying hierarchy instead of boldness. H4–H6 get eyebrow treatment (uppercase, muted color). Changelog headings in #history get custom overrides.
TOC panel widened from 15em to 18em min-width with inner padding on .toc-sticky for better readability on wrapped entries.
Layout shift
Images get width/height/loading="lazy" attributes, aspect-ratio CSS reserves space before load, and the sidebar logo gets decoding="async". Shields.io badges get fixed 20px height, 60px min-width, and a background placeholder to prevent 0→20px shift. The brand template sets explicit width/height/decoding on the logo.
SPA navigation
Every page navigation previously triggered a full reload — re-downloading 8 CSS files, 7 JS files, 3 fonts, and re-rendering the entire layout. Only the article, TOC, and active sidebar link actually change.
The script intercepts clicks on internal <a> tags via event delegation, fetches the target page, parses it with DOMParser (no script execution), and swaps three regions:
What gets swapped: .article-container, .sidebar-tree, .toc-drawer
What is preserved: sidebar scroll position, theme toggle state, all <link>/<script> tags, font preloads, .sidebar-brand, .sidebar-search-container, #sidebar-projects, mobile header
Post-swap reinit:
Skip interception for: external links, search.html/genindex.html/py-modindex.html, modifier-key clicks (Ctrl/Meta = new tab), #sidebar-projects links, same-page hash links, download attributes
Failure modes: network error or missing selectors → falls back to window.location.href
View Transitions
DOM swaps are wrapped in document.startViewTransition() when available. The CSS sets animation-duration: 150ms on ::view-transition-old(root) and ::view-transition-new(root) for a quick crossfade. Browsers without the API get an instant swap (no polyfill needed).
Sidebar visibility gate
#sidebar-projects starts with visibility: hidden via CSS and gets a .ready class added by JS after the active link is set. This prevents a flash where all project links briefly appear unstyled before the active state is applied.
CI
Docs build workflow temporarily includes docs-fonts branch. Font files are cached via actions/cache keyed on the extension source to avoid re-downloading on every build.
Continues from a58026b. See also #1021.
Test plan