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

tanstack-start-typekit

v0.0.1

Published

TanStack Start font loading for Google Fonts and local font files.

Readme

tanstack-start-typekit brings a small font API to TanStack Start: import Google helpers or local font helpers, register fonts during each SSR request, and let request middleware inject the generated @font-face rules into the HTML response.

This is an experimental community package and is not affiliated with TanStack.

Features

  • Google Font factory for any Google Fonts family name
  • No hardcoded Google font allowlist
  • Local font support for one file, many weights, or variable font families
  • Generated class names and optional CSS variable classes
  • Browser-safe client modules so React hydration keeps the same class names
  • Google Font CSS cached in node_modules/.cache/tanstack-start-typekit
  • Google font strategies: keep font files hosted by Google or inline them
  • Optional selector rules for app-wide font application

Font registration is request-scoped. For app-wide fonts, call your font helpers from the function passed to createFontMiddleware(). For route-specific fonts, call the helper during SSR render. Avoid relying on module-level font calls for CSS injection, because those can run outside the request collector.

Runtime Support

This package is designed for TanStack Start apps running with Node-compatible SSR runtimes such as Node.js or Bun. The server modules use Node APIs including node:fs/promises, node:async_hooks, Buffer, and process.env.

Edge and worker runtimes, including Cloudflare Workers, are not guaranteed unless your deployment provides compatible Node APIs. For those targets, prefer public font URLs or plain CSS until you verify the runtime behavior in your app.

Install

npm install tanstack-start-typekit

Add The Vite Plugin

// vite.config.ts
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import viteReact from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import font from "tanstack-start-typekit";

export default defineConfig({
  plugins: [
    font(),
    tanstackStart(),
    viteReact(),
  ],
});

The plugin configures browser-safe font modules and rewrites static relative local font paths to Vite ?url imports.

The local font rewrite is intentionally small and supports static src and path values inside localFont(...) calls. Dynamic font paths should use public URLs or be handled manually.

If you want framework-style imports, enable aliases with font({ includeFrameworkAliases: true }) and import from tanstack/font/google or tanstack/font/local. The package subpaths above are the default because they work with TypeScript without extra configuration.

Add The Request Middleware

// src/start.ts
import { createStart } from "@tanstack/react-start";
import { createFontMiddleware } from "tanstack-start-typekit/middleware";
import { registerFonts } from "./config/fonts";

export const startInstance = createStart(() => ({
  requestMiddleware: [createFontMiddleware(registerFonts)],
}));

The middleware wraps each request, collects font CSS registered during SSR, and injects the final style tag and local font preload links into HTML responses. Passing your app font registration function to createFontMiddleware() keeps global font registration inside the same request-scoped collector as the HTML injection step, which is useful when the app shell renders through server functions or cached document responses.

// src/config/fonts.ts
import googleFont from "tanstack-start-typekit/google";
import localFont from "tanstack-start-typekit/local";

const Cairo = googleFont("Cairo");

export function registerFonts() {
  Cairo({
    subsets: ["arabic", "latin"],
    weight: ["400", "700"],
    variable: "--font-cairo",
    fallback: ["Tahoma", "Arial", "sans-serif"],
    selector: ["html[lang='ar']", "body[dir='rtl']", ".font-cairo"],
    variableSelector: ":root",
  });

  localFont({
    family: "Brand Sans",
    src: "/fonts/brand-sans.woff2",
    fallback: ["system-ui", "sans-serif"],
    preload: true,
    selector: ".font-brand",
  });
}

Use A Google Font

import googleFont from "tanstack-start-typekit/google";

const Inter = googleFont("Inter");

export function Page() {
  const inter = Inter({
    subsets: ["latin"],
    weight: ["400", "700"],
    display: "swap",
    strategy: "external",
    variable: "--font-inter",
    fallback: ["system-ui", "sans-serif"],
  });

  return (
    <main className={`${inter.className} ${inter.variable}`}>
      <h1>TanStack Start pages with crisp, optimized type.</h1>
    </main>
  );
}

By default, Google font CSS keeps its fonts.gstatic.com URLs intact, so the browser loads font files from Google at runtime. To inline Google font files into the generated CSS, opt in per font:

const inter = Inter({
  weight: ["400", "700"],
  strategy: "inline",
});

Need a helper that is not exported yet?

import { createGoogleFont } from "tanstack-start-typekit/google";

const DM_Sans = createGoogleFont("DM Sans");

Use A Local Font

import localFont from "tanstack-start-typekit/local";

export function Heading() {
  const brand = localFont({
    src: [
      { path: "../fonts/Brand-Regular.woff2", weight: "400", style: "normal" },
      { path: "../fonts/Brand-Bold.woff2", weight: "700", style: "normal" },
    ],
    display: "swap",
    variable: "--font-brand",
    fallback: ["system-ui", "sans-serif"],
  });

  return <h1 className={brand.className}>Brand heading</h1>;
}

Static relative local paths in TypeScript and JavaScript files are rewritten to Vite ?url imports so Start can fingerprint and emit the files. Public URLs such as /fonts/Brand.woff2 are kept as URLs. Local font URLs are preloaded by default unless you pass preload: false.

Returned Object

Both font modules return the same shape:

type StartFont = {
  className: string;
  variable?: string;
  family: string;
  style: {
    fontFamily: string;
    fontStyle?: string;
    fontWeight?: string;
  };
};

Use className on React elements, apply variable to expose a CSS custom property, read family for a resolved font-family value, or read style when you need inline style values.