Lagrange v1.8: Fonts and Warnings

This release focuses on a customizable font library, and improves the appearance and behavior of warnings and error messages. Thanks to the unbundled fonts, this release is the slimmest one yet.

πŸ‘» Breaking changes

Please note the following when upgrading:

Font library

Lagrange's custom text renderer attempts to be as portable and dependency-free as possible. By managing its own fonts, the app can work the same way on every platform, including mobile devices where you cannot easily install new fonts.

In previous releases, the font library has been hardcoded to only support a handful of fonts that were all bundled with the app. You were downloading several megabytes of (the same!) fonts on every upgrade, and the set of fonts wasn't even that extensive. While access to system fonts still is not available, the hardcoding is now history and you are able to install additional fonts. The requirement that all fonts are in TrueType format remains.

From there you can, if you so choose, conveniently download and install additional fonts specifically configured for the app. I plan on extending this library as I stumble on nice and/or unique fonts that work well in Lagrange. I expect most of these will be freely distributable OFL-licensed fonts.


While you can just install individual TrueType fonts, to get the most out of the text renderer, they need to be combined into a fontpack. This is a ZIP archive with metadata for Lagrange that determines which font file corresponds to which style, and controls when and how the fonts are going to be used.

Installing a font(pack) is as easy as viewing the file in Lagrange and clicking the "Install" button in the bottom of the page. This way you can install fonts via Gemini pages or by dropping a previously downloaded .fontpack/.ttf file on the Lagrange window.

I have documented the fontpack format on the Help page (section 5), and the new "about:fonts" management interface provides some assistance in setting up a fontpack. There is quite a bit of detail here, so if interested, check out the new Fonts section (2.4), as well.

Unbundling the library

Having this online library now enables unbundling all additional fonts from the binary packages, substantially reducing their size. The old set of fonts is provided as a single (Gemini) download if you wish to keep using them.

When upgrading the app in the future, all the installed fonts remain available on your system.

However, unbundling the fonts also means saying goodbye to the old defaults: Nunito is gone, and all text is now displayed in Source Sans. It has considerably narrower metrics, so you may also want to adjust the line width setting. On the upside, using the same font throughout the UI and page content makes for a very visually consistent experience.

Of course, now you are free to change the UI font, too:

Next steps

Unraveling all the hardcoded font management logic into a more dynamic system was quite a bit of work, so in this release I've focused on the basics and left some of the finer details for later. For example, more intelligence could be added when loading individual TrueType fonts. In many cases, multiple styles/weights of the same typeface could be auto-grouped into one fontpack. This is somewhat limited by what information stb_truetype can extract, but I think a file name based solution could be workable, too.

When it comes to system (and OpenType) fonts, using those will require introducing new dependencies into the build. There will also need to be platform-specific exceptions, like using the Core Text API on Apple platforms. Therefore, this still remains a longer-term objective but one that is worth pursuing. In an ideal world, users already have all the fonts they need (i.e., for the languages they speak) installed on their systems, and Lagrange should be able to use them directly.

Redesigned warnings and errors

In past releases, error messages have been presented as dynamically generated Gemtext pages. This has the problem that they couldn't always be distinguished from page content received from the server. Also, the first iteration of the "Untrusted Certificate" warning banners was a bit crude, aiming more to be noticeable than nice-looking. In v1.8, I've redesigned both of these and made them distinct from page content. It is no longer possible to create a page that mimics an error message.

All warnings and errors now appear as part of the site banner. Warnings in the banner are also interactive, so clicking on them is a convenient way to perform relevant actions.

Compatibility warnings

So far all warning/error messages have been related to either error codes defined in the protocol, or failures in the network and TLS layers. This release adds a couple of warnings related to content presentation and compatibility issues:

The first one is pretty straightforward, and gives you a convenient way to access the font library to install more fonts. It doesn't currently tell you exactly which characters are missing or which fonts should be installed; that you'll need to figure out on your own. I'm thinking of some sort of Unicode block lookup that could let me recommend specific fonts in the font collection, but that is a topic for the future. (Also, possibly preempted by access to system fonts.)

The second one needs a bit of unpacking. Gemini, and Gopher before it, has rather strong roots in the terminal, so you sometimes encounter ANSI escape sequences sprinkled into pages, with the purpose of altering the visual attributes of content β€” something that Gemini clients are explicitly allowed to ignore. This warning will highlight when any ANSI escape codes are found on the page. You can dismiss the warning on a per-site basis, but not globally for every site.

My intention with this warning is two-fold:

1) Make the reader aware that the content is assumed to be viewed in a terminal emulator, or some other program that supports ANSI escape codes.

2) Inform capsule owners that they are making possibly unfounded assumptions about support for ANSI escapes.

If you serve content via Gemini, please be aware that ANSI escapes may not be understood by clients, and may in fact disrupt the behavior of a client in unexpected ways. For instance, consider a screen reader or a web proxy that doesn't filter out the codes. You should only employ ANSI escapes when the user has somehow indicated that is their preference.

You can read more about ANSI escape codes in Help (section 2.4.2).

UI improvements

...and Markdown?

The Lagrange repository was my benchmark here, although the feature still lacks any way to present tables.

This experimental feature is included in v1.8, but the conversion to Gemtext is only triggered when viewing documents on "file://" URLs. In any other context, "text/markdown" gets displayed as plain text. This way, because the original document is on your file system and viewable by other means, it doesn't matter if Lagrange's rendition of it is incomplete. It also means that one isn't tempted to use Markdown instead of Gemtext on Gemini capsules.

The foremost reason why this feature is included is that I enjoy having a Markdown viewer that looks and behaves like Lagrange. In the grand scheme of things, this is pretty low on the priority list but when and if I continue working on it, I'll most likely make it a MIME hook, which achieves the same functionality without having to be built in.


I'm thinking this could be a good time to dedicate a whole month for general polishing and taking care of various smaller issues. For example, I've been wondering why window resizing has become extremely slow on my Ubuntu XFCE desktop. I also think I'm going to enjoy choosing a bunch of fonts for the online library.

πŸ“… 2021-10-30

🏷 Lagrange

CC-BY-SA 4.0

The original Gemtext version of this page can be accessed with a Gemini client: gemini://