@fcannizzaro/streamdeck-react

Font Management

How to load and configure fonts for rendered Stream Deck UI.

Why Fonts Are Required

The renderer cannot access system fonts from the Stream Deck runtime. It needs font file data (ArrayBuffer or Buffer) passed explicitly.

Supported formats by backend:

FormatNative Binding (default)WASM
.ttf
.otf
.woff
.woff2

If you're using the WASM backend (takumi: "wasm"), only TTF and OTF fonts are supported.

The googleFont() helper downloads TTF fonts directly from Google Fonts — no npm package needed. Font files are cached to .google-fonts/ in your project directory, so only the first run requires network access.

import { createPlugin, googleFont } from "@fcannizzaro/streamdeck-react";

const inter = await googleFont("Inter");

const plugin = createPlugin({
  fonts: [inter],
  actions: [...],
});

Multiple Weights

const fonts = await googleFont("Inter", [
  { weight: 400 },
  { weight: 700 },
]);

const plugin = createPlugin({ fonts, actions: [...] });

Single Variant

const bold = await googleFont("Inter", { weight: 700 });
const italic = await googleFont("Inter", { weight: 400, style: "italic" });

Multiple Families

const [inter, robotoMono] = await Promise.all([
  googleFont("Inter"),
  googleFont("Roboto Mono"),
]);

const plugin = createPlugin({
  fonts: [inter, robotoMono],
  actions: [...],
});

Disk Cache

Downloaded fonts are saved to .google-fonts/ in the current working directory. Subsequent calls read from disk without any network access. Add this directory to your .gitignore:

.gitignore
.google-fonts/

To force a re-download, delete the cache directory.

GoogleFontVariant

interface GoogleFontVariant {
  weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
  style?: "normal" | "italic";
}

Both fields are optional. Defaults: weight: 400, style: "normal".

FontConfig Interface

interface FontConfig {
  name: string;
  data: ArrayBuffer | Buffer;
  weight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
  style: "normal" | "italic";
}

Loading Fonts Manually

If you need fonts not available on Google Fonts, you can load them manually via readFile:

import { readFile } from "node:fs/promises";

const fonts = [
  {
    name: "Inter",
    data: await readFile("./fonts/Inter-Regular.ttf"),
    weight: 400 as const,
    style: "normal" as const,
  },
  {
    name: "Inter",
    data: await readFile("./fonts/Inter-Bold.ttf"),
    weight: 700 as const,
    style: "normal" as const,
  },
];

If using the WASM backend (takumi: "wasm"), use .ttf or .otf files only. WOFF and WOFF2 are not supported in WASM mode. The default native-binding backend supports all formats including .woff and .woff2.

Using Fonts in Components

The renderer resolves fonts by matching fontFamily, fontWeight, and fontStyle:

<span style={{ fontFamily: 'Inter', fontWeight: 700 }}>Bold text</span>
<span style={{ fontFamily: 'Inter', fontWeight: 400 }}>Regular text</span>

If a requested weight isn't loaded, the nearest available weight is used.

Font Bundle Size

Each font weight/style is a separate file:

  • Latin-only subset: ~50-300KB
  • CJK character sets: ~1-5MB

Plugins shipping multiple fonts will have a larger bundle. Consider subsetting fonts to reduce size.

On this page