index

Optimizing This Blog: Fonts, SVG Artwork, and Navigation

This blog is a static Astro site with long technical articles, diagrams, mathematical notation, and generated artwork. Its performance costs sit mainly in the resources needed to display that content: fonts, document markup, styles, and the work of laying out a page after navigation.

The September 24 update reduced the font loaded on every page, moved repeated directory artwork into a shared SVG, and changed how styles and offscreen content are handled. It also made prefetching follow the structure of the index, where featured articles and directory rows have different browsing patterns.1

The changes address different parts of the path from a request to readable content. Their file-size effects can be measured directly, while their mechanisms explain where the browser can avoid or reuse work.

The document’s critical path

A static page still needs to be parsed and rendered. The browser receives HTML, discovers its styles and fonts, constructs the document, computes layout, and paints. During navigation, some resources can be reused, but the new article introduces its own markup and layout.

This creates several independent costs. Large HTML takes work to parse. A font discovered late can delay final typography. Repeated artwork expands the document even when it compresses well on the network. A stylesheet for a feature absent from the page adds processing without contributing to that page’s appearance.

The implementation commit records the exact changes.1 The payload measurements below refer to its 70-post publication build. Subsequent article revisions change document sizes, while the underlying resource choices remain inspectable in the source.

The Inter subset

The site previously preloaded a 345,588-byte Inter WOFF2 file. The Latin subset used for browser text is 100,176 bytes, a reduction of 245,412 bytes, or about 71 percent, for that font resource.

Subsetting works because the browser text uses only part of the original font’s glyph coverage. The unicode-range declaration identifies the characters served by the face, and font-display determines how text appears while the font is loading. Preloading makes the font discoverable before the browser would otherwise find it through the rendered text.2

The original Inter file remains available to social-card generation, which has a different coverage requirement. Browser text and build-time image rendering therefore use separate resources suited to their inputs.

This saving applies most directly to a first visit that needs the font. A warm visit may reuse an existing response from the browser cache. Page latency also includes HTML, styles, layout, and other resources, so the percentage reduction in the font file describes one component of the load.

Font selection and layout

The update also serves selected mono faces locally instead of importing a broader font package. Body text, headings, and code have different font requirements; loading the faces used by those elements makes the dependency explicit.

A preload gives a resource priority. The useful set is the faces needed early in the page, since preloading every available weight makes them compete for network capacity. The selected heading weight and body face are more likely to contribute to the first viewport than a face used only deep in an article.

Coverage affects layout as well as download size. Accented names, punctuation, code symbols, and non-Latin characters can invoke fallback fonts when a subset does not contain them. Different metrics can change line breaks. That is why the subset and the page’s actual character coverage are considered together.

Shared SVG artwork

The directory originally embedded each row’s generated SVG paths directly in the homepage. The new implementation stores those definitions in /thumbnails.svg and gives each row a small <use> reference. Featured cards and article banners remain inline.1

On the same 70-post corpus, the publication build’s homepage was approximately 177 KB. Expanding the row references back into inline artwork would make it approximately 309 KB, a difference of about 132 KB in the document. The shared sprite was about 143 KB uncompressed and 13 KB with gzip.

The distinction between document size and transfer size is important here. Gzip compresses repeated markup effectively, so moving paths into a separate file does not remove 132 KB from the compressed first-visit transfer. The cold transfer totals are similar. The main document contains less markup to parse, and the artwork becomes a separately reusable resource.

The cache boundary now follows the content boundary. A change to article text does not inherently change the SVG definitions, and a page using a row reference does not have to repeat the paths in its HTML. The actual reuse still follows the response’s cache policy and validation behavior.

Rendering the sprite in context

Each row retains its dimensions and surrounding theme styles. The external symbol supplies the drawing. This preserves the role of the artwork while changing where its markup lives.

The important rendering cases are the light and dark themes, a fresh index load, and returning to the index through client navigation. A valid <use> element establishes the reference, while the visible paths establish that the resource loaded and inherited the expected appearance.

Article banners stay inline because they represent one article at a time. Downloading the entire directory sprite for a single banner would introduce unrelated artwork into that request. Keeping the two representations separate follows their reuse patterns.

Math styles as an article dependency

The Markdown pipeline records whether an article contains math. The article layout uses that result to include a separate KaTeX stylesheet. Pages without math avoid the dependency; pages with equations load the rules and font resources needed to display them.1

This is a build-time decision. The browser receives the appropriate stylesheet link with the article rather than discovering the requirement through a later script.

Currency notation makes the classification slightly more involved. Markdown math delimiters also use dollar signs, so money prose can be parsed as inline math. The accompanying currency pass recognizes common price patterns before the page’s math flag is determined. Actual equations retain the math path.

Client navigation exercises the dependency in both directions. A math article needs its stylesheet when reached from a non-math page, and a fresh context establishes that the page is not relying on a stylesheet retained from an earlier visit. These cases connect the build-time classification to the browser’s resource lifecycle.

Offscreen rendering

Long articles contain blocks with substantial layout and paint work: code listings, figures, tables, equations, and diagrams. The stylesheet applies content-visibility: auto to selected blocks and supplies an estimated intrinsic size.3

Supporting browsers can skip some rendering work for those blocks while they are offscreen. The content remains in the document, and its network bytes are still part of the page. The saving is in when rendering work is performed.

The intrinsic-size estimate gives the browser a provisional layout before it renders the block. As the actual content becomes relevant, its true dimensions replace that estimate. Tall code blocks, wide tables, and anchor navigation make this behavior visible, because their geometry affects the position of surrounding content.

The table of contents also moved from a global per-scroll update loop to intersection-observer-driven updates. The top gradient uses a CSS scroll-driven animation where supported. These changes reduce the amount of JavaScript tied directly to scrolling while preserving the navigation and visual behavior.1

Prefetching follows browsing intent

Astro supports prefetch strategies based on hover, focus, viewport entry, and other triggers.4 The index uses viewport-based prefetching for featured links and hover or focus for directory rows.

The difference follows the page’s structure. Featured articles are a small set of likely destinations. The directory is a large collection that readers may scan without opening most of it. Warming every row as it enters the viewport can transfer many articles that are never visited.

Hover and focus provide a more selective signal for the directory. They allow the browser to begin fetching a chosen article before activation. A touch interaction has less advance notice, so its request sequence can differ from the pointer path.

Prefetching and prerendering perform different amounts of work. Prefetching obtains resources in advance; prerendering can prepare a document for a later navigation.5 The configuration enables Astro’s supported client-prerender path, with actual behavior determined by browser support and policy.

The useful tradeoff is between work before the click and time after it. Recording prefetched bytes and subsequent visits establishes how much of the background work contributes to navigation. A lower click-to-content time and a smaller total browsing transfer are related but distinct objectives.

Reproducing the payload measurements

The current build can be inspected with:

bun install --frozen-lockfile
bun run build
bun -e 'import { statSync } from "node:fs"; for (const p of ["dist/index.html", "dist/thumbnails.svg", "public/fonts/Inter.woff2", "public/fonts/Inter-latin.woff2"]) console.log(p, statSync(p).size)'
gzip -c dist/index.html | wc -c
gzip -c dist/thumbnails.svg | wc -c

The file sizes separate raw document storage from compressed transfer payload. The same corpus and build settings isolate the effect of an implementation change. Comparing an older 61-post index with a newer 70-post index would combine engineering changes with content growth.

Browser verification adds the execution context: a fresh homepage, a warm article switch, a math article, and a long mobile page. The publication checks covered article rendering, artwork, math-style loading, and mobile overflow. These establish that the changed resource paths still deliver the intended content.

Field timing answers the remaining performance question. Click-to-usable-content distributions, separated by device and cache state, show how the resource changes affect readers. The established result is the reduced font resource and lighter homepage markup, together with more selective loading and rendering. Each addresses a specific cost in delivering the same technical material.

References

Footnotes

  1. Site source, commit 8e5049f, September 24, 2026. Fonts, thumbnail sprite, conditional math styles, rendering, and navigation changes. ↩ ↩2 ↩3 ↩4 ↩5

  2. Ilya Grigorik, Optimize WebFont loading and rendering, web.dev. Subsetting, preloading, and font-display behavior. ↩

  3. MDN, content-visibility. Rendering containment and offscreen behavior. ↩

  4. Astro, Prefetch. Supported prefetch strategies and configuration. ↩

  5. MDN, Speculative loading. Distinctions between prefetching and prerendering. ↩

Follow a font dependency to the first readable frame

The browser needs usable font metrics and styles before it can paint a stable text layout.

  1. Document

    Parse the page and discover its stylesheet and font references.

  2. Resource reuse

    Fetch or reuse the font subset and shared SVG resource.

  3. Layout

    Shape text and compute line breaks with the selected font metrics.

  4. Paint

    Draw the visible content; defer eligible offscreen work.

Reducing bytes and avoiding repeated work improve different parts of the same path.

Different caches remove different work

These mechanisms have distinct lifetimes and do not make all rendering free.

CaseReused objectWork that can remain
HTTP cacheFont, CSS, or SVG response bytesDOM construction, styles, layout, and painting
Document preloadAn already fetched destination documentParsing, script setup, and layout unless separately reused
Offscreen containmentAn estimated layout footprintVisible blocks still need complete layout and painting

Name the reused resource before attributing a navigation improvement to caching.