PYYUPSK

a self-taught dev from Thailand

Pongsakorn Thipayanate · Samutsakhon, TH ·webring

active

@pyyupsk/vite-fonts

A Vite plugin that downloads and self-hosts web fonts at build time, with zero layout shift and no runtime CDN calls.

TypeScript / Vite / Astro / Fonts· 2026

GitHub →

view .mdopen in claudeopen in chatgpt

A Vite plugin that downloads web fonts at build time and serves them from your own output, instead of calling Google Fonts or another CDN at runtime.

Features

  • Self-hosts fonts from Google Fonts, Bunny Fonts, Fontsource, or fonts.fasu.dev.
  • Generates @font-face CSS with size-adjust fallback metrics, which removes layout shift.
  • Injects <link rel="preload"> tags automatically.
  • Creates one CSS variable per font family and syncs it with a Tailwind v4 @theme block.
  • Gives you a type-safe @pyyupsk/fonts/meta module, so family keys autocomplete in your editor.
  • Caches downloaded font files, so a second build does not redownload them.

Usage

// vite.config.ts
import { fonts } from '@pyyupsk/vite-fonts'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [fonts('Inter')],
})

An Astro integration works the same way, through @pyyupsk/vite-fonts/astro. It also preloads fonts on nested static pages.

SSR Frameworks

TanStack Start, React Router and SvelteKit render HTML at request time, so the plugin cannot add preload tags. Since 0.4.0, @pyyupsk/fonts/meta exports preloads. You render them in the document head:

import * as fonts from '@pyyupsk/fonts/meta'

const links = fonts.preloads.map((p) => ({ rel: 'preload', as: 'font', crossOrigin: 'anonymous', ...p }))

Since 0.4.1, the preload list covers every subset, for example both Latin and Thai, and keeps the weight range of variable fonts.

CLI

  • bunx vite-fonts list: Shows configured fonts and cache info.
  • bunx vite-fonts clean: Clears the font cache.

← All projects