Skip to content

Remove font loading from the library; let apps load their own fonts #855

Description

@ravisuhag

Summary

The library loads fonts itself. packages/raystack/styles/typography.css starts with four Google Fonts @import calls:

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Lora:wght@400;500&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@400;500&display=swap");
@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital@0;1&display=swap");

A component library should not decide how or where fonts load. That belongs to the app. We should remove these imports and keep only the --rs-font-* variables (the font-family names), then let each app load the fonts it needs.

Why this is a problem

  • Consumers download fonts they never use. Any app that pulls in Apsara fetches Inter, Lora, Josefin Sans, and JetBrains Mono — even if it only uses Inter. Lora and Josefin Sans only apply under [data-style="traditional"], so most apps pay for them for nothing.
  • @import blocks render. Fonts inside a CSS @import are found late by the browser, which delays paint and causes a flash of unstyled text (FOUT).
  • Extra connections. Each @import needs DNS + TLS to Google's domains before the font even downloads.
  • No control for the app. The app can't preload the font, can't set font-display, and can't self-host. All of that is decided inside the library.
  • Blocks other improvements. We can't cleanly add a 600 weight or use Inter's optical-sizing (opsz) axis, because the library pins the exact Google Fonts URL and weights.

Proposal

  1. Remove the four @import lines from packages/raystack/styles/typography.css.
  2. Keep the --rs-font-* variables (Inter, Lora, Josefin Sans, JetBrains Mono, Menlo) so component styles stay unchanged.
  3. Document how consuming apps load the fonts, for example:
    • Self-host with Fontsource — @fontsource-variable/inter (variable font, all weights from one file).
    • next/font for Next.js apps.
    • A plain @font-face or Google Fonts <link> for apps that want it.
  4. Note the optional families (Lora, Josefin Sans) are only needed for the traditional style.

Breaking change

This is a breaking change. Apps that rely on Apsara loading fonts will render in a fallback font until they load the fonts themselves. The migration is small — install the fonts and import them once at the app entry — but it must be called out in release notes with a clear before/after.

Acceptance criteria

  • No @import of font files in the library CSS.
  • --rs-font-* variables still present; components render identically once the app loads Inter.
  • Docs / README show how to load fonts in a plain Vite app and a Next.js app.
  • Migration note added to the changelog / release notes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BREAKING CHANGEenhancementNew feature or requestglobalCross-cutting issue affecting multiple components

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions