npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astro-font-loader

v0.3.2

Published

Astro integration for loading fonts into build artifacts with configurable output paths and media query-based conditional preloading.

Readme

Astro Font Loader

typescript astro

astro-font-loader hooks into the astro build process to copy selected fonts from installed font packages into the local build artifacts.

[!NOTE] Why use this instead of the built-in Astro Fonts API? astro-font-loader was originally designed as a package based font solution, but continues due to two limitations.

The first is that there are no controls over output file paths. Astro's built-in font handling places font files in hashed, opaque paths. This makes it difficult to configure Early Hints (103 responses) or Link headers since you can't predict the final font URLs ahead of time. You end up writing a custom build script anyways to create predictable paths in this case.

The second is that there is no media query support for font loading. There is no way to conditionally load fonts based on viewport size (e.g., min-width media queries). This means all font weights and variants are downloaded on every device, even if they're only used on larger screens.

Installation

# Using npm
npm i astro-font-loader

# Using yarn
yarn add astro-font-loader

# Using pnpm
pnpm add astro-font-loader

How It Works

  1. Setup Phase: During Astro's config setup, the integration:

    • Locates the specified font packages in your node_modules
    • Matches @font-face rules from the package CSS by font-family, font-weight, and font-style
    • Prepares the list of font files to be copied
  2. Build Phase: After Astro completes the build:

    • Copies the matched font files to the output directory
    • Ensures fonts are available in your production build

Usage

Basic Setup

Add the integration to your astro.config.mjs or astro.config.ts file. The variant name should match the font-family value in the package's CSS @font-face rules:

import { defineConfig } from 'astro/config';
import { fontsIntegration } from 'astro-font-loader';

export default defineConfig({
  integrations: [
    fontsIntegration({
      outputDirectory: "fonts",
      fonts: [
        {
          family: "Roboto",
          source: { type: "package", package: "@company/design-system-fonts" },
          variants: [
            { name: "Roboto", weight: 400, styles: ["normal"] },
            { name: "Roboto", weight: 700, styles: ["normal"] },
          ],
        },
      ],
    }),
  ],
});

Multiple Font Families

A single package can provide multiple font families. Each family gets its own entry in the fonts array:

fontsIntegration({
  outputDirectory: "fonts",
  fonts: [
    {
      family: "Berkeley Mono",
      source: { type: "package", package: "@company/design-system-fonts" },
      variants: [
        { name: "Berkeley Mono v2 Variable", weight: [100, 900], styles: ["normal", "oblique"] },
      ],
    },
    {
      family: "EB Garamond",
      source: { type: "package", package: "@company/design-system-fonts" },
      variants: [
        { name: "EB Garamond", weight: 600, styles: ["normal"] },
        { name: "EB Garamond", weight: 700, styles: ["normal"] },
      ],
    },
  ],
})

Custom Style File

By default, the integration looks for CSS at src/index.css within the package. You can override this with styleFile:

{
  family: "Custom Font",
  source: {
    type: "package",
    package: "@company/fonts",
    styleFile: "dist/fonts.css",
  },
  variants: [
    { name: "Custom Font", weight: 400, styles: ["normal"] },
  ],
}

FontLoader Component

The FontLoader component generates <link rel="preload"> tags and inline @font-face CSS. Use it alongside the integration — the integration copies font files to the build output, while the component injects the HTML needed to load them.

---
import FontLoader from 'astro-font-loader/FontLoader.astro';

const source = { type: "package" as const, package: "@company/design-system-fonts" };
---
<html>
  <head>
    <FontLoader
      fonts={[
        {
          family: "Berkeley Mono",
          source,
          variants: [
            { name: "Berkeley Mono v2 Variable", weight: [100, 900], styles: ["normal", "oblique"] },
          ],
        },
        {
          family: "EB Garamond",
          source,
          variants: [
            { name: "EB Garamond", weight: 600, styles: ["normal"] },
            { name: "EB Garamond", weight: 700, styles: ["normal"] },
          ],
        },
      ]}
      outputDirectory="fonts"
      preload={[
        { variant: "Berkeley Mono v2 Variable" },
        { variant: "EB Garamond", weight: 600 },
        { variant: "EB Garamond", weight: 700, media: "(min-width: 641px)" },
      ]}
    />
  </head>
  <body><slot /></body>
</html>

Selective Preloading with Media Queries

The preload prop accepts an array of entries that match variants by their CSS font-family name, and optionally by weight and styles for per-variant granularity. Each entry can include an optional media query to conditionally preload fonts based on viewport size:

preload={[
  { variant: "Berkeley Mono v2 Variable" },                    // always preload
  { variant: "EB Garamond", weight: 600 },                     // always preload semibold
  { variant: "EB Garamond", weight: 700, media: "(min-width: 641px)" },  // bold on desktop only
]}

Fonts matched by an entry in preload get a <link rel="preload"> tag. Fonts not listed in preload still get their @font-face CSS injected — they load normally without being preloaded.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | fonts | FontConfig[] | (required) | Font configurations to load | | outputDirectory | string | (required) | Output directory name in generated URLs | | preload | PreloadEntry[] | [] | Variants to preload, with optional weight/style narrowing | | root | string | process.cwd() | Root directory for resolving font packages |

PreloadEntry

| Property | Type | Required | Description | |----------|------|----------|-------------| | variant | string | Yes | CSS font-family name to match for preloading | | weight | number \| [number, number] | No | Narrow to a specific weight. Omit to match all weights | | styles | string[] | No | Narrow to specific styles. Omit to match all styles | | media | string | No | Media query for the preload link |

Additional Documentation