Font Handling in loopwind

The recommended way to use fonts is through loopwind.json - configure fonts once, use everywhere.

Configure fonts in your .loopwind/loopwind.json and use Tailwind classes in templates.

Simple Setup

Define font families in .loopwind/loopwind.json without loading custom fonts (uses system fonts):

{
  "fonts": {
    "sans": ["Inter", "system-ui", "-apple-system", "sans-serif"],
    "serif": ["Georgia", "serif"],
    "mono": ["Courier New", "monospace"]
  }
}

Template usage:

export default function({ title, tw }) {
  return (
    <div style={tw('w-full h-full')}>
      {/* Uses fonts.sans from loopwind.json */}
      <h1 style={tw('font-sans text-6xl font-bold')}>
        {title}
      </h1>

      {/* Uses fonts.mono from loopwind.json */}
      <code style={tw('font-mono text-sm')}>
        {code}
      </code>
    </div>
  );
}

Result: Uses system fonts, falls back to Inter for rendering.

Complete Setup (With Font Files)

Load custom font files for brand-specific typography in .loopwind/loopwind.json:

{
  "fonts": {
    "sans": {
      "family": ["Inter", "system-ui", "sans-serif"],
      "files": [
        { "path": "./fonts/Inter-Regular.woff", "weight": 400 },
        { "path": "./fonts/Inter-Bold.woff", "weight": 700 }
      ]
    },
    "mono": {
      "family": ["JetBrains Mono", "monospace"],
      "files": [
        { "path": "./fonts/JetBrainsMono-Regular.woff", "weight": 400 }
      ]
    }
  }
}

Project structure:

your-project/
├── .loopwind/
│   ├── loopwind.json
│   └── templates/
└── fonts/
    ├── Inter-Regular.woff
    ├── Inter-Bold.woff
    └── JetBrainsMono-Regular.woff

Template usage (same as before):

<h1 style={tw('font-sans font-bold')}>
  {/* Uses Inter Bold from loopwind.json */}
  {title}
</h1>

Available classes:

  • font-sans - Uses fonts.sans from loopwind.json
  • font-serif - Uses fonts.serif from loopwind.json
  • font-mono - Uses fonts.mono from loopwind.json

Supported formats:

  • WOFF (.woff) - Recommended for best compatibility
  • TTF (.ttf) - Also supported
  • OTF (.otf) - Also supported
  • WOFF2 (.woff2) - Not supported by renderer

Font Loading Priority

loopwind loads fonts in this order:

  1. loopwind.json fonts (if configured with files)
  2. Bundled Inter fonts (included with CLI)

This ensures fonts work out of the box with no configuration.

Default Fonts

If no fonts are configured, loopwind uses Inter (Regular 400, Bold 700) which is bundled with the CLI. This means fonts work offline with no configuration required.

Best Practices

  1. Use loopwind.json for project-wide fonts - Configure once, use everywhere
  2. Use font classes - tw('font-sans') instead of fontFamily: 'Inter'
  3. Include fallbacks - Always add system fonts: ["Inter", "system-ui", "sans-serif"]
  4. Match names - First font in family array is used as the loaded font name
  5. Relative paths - Font paths are relative to loopwind.json location

Examples

Minimal Setup (System Fonts)

{
  "fonts": {
    "sans": ["Inter", "-apple-system", "sans-serif"]
  }
}

Uses system Inter if available, falls back to Noto Sans for rendering.

Brand Fonts Setup

{
  "fonts": {
    "sans": {
      "family": ["Montserrat", "sans-serif"],
      "files": [
        { "path": "./fonts/Montserrat-Regular.woff", "weight": 400 },
        { "path": "./fonts/Montserrat-Bold.woff", "weight": 700 }
      ]
    }
  }
}

Loads and uses Montserrat for all templates.

Multi-Font Setup

{
  "fonts": {
    "sans": {
      "family": ["Inter", "sans-serif"],
      "files": [
        { "path": "./fonts/Inter-Regular.woff", "weight": 400 },
        { "path": "./fonts/Inter-Bold.woff", "weight": 700 }
      ]
    },
    "serif": {
      "family": ["Playfair Display", "serif"],
      "files": [
        { "path": "./fonts/Playfair-Regular.woff", "weight": 400 }
      ]
    },
    "mono": {
      "family": ["Fira Code", "monospace"],
      "files": [
        { "path": "./fonts/FiraCode-Regular.woff", "weight": 400 }
      ]
    }
  }
}

Loads different fonts for each style class.

External Font URLs

Load fonts directly from CDNs without downloading files:

{
  "fonts": {
    "sans": {
      "family": ["Inter", "sans-serif"],
      "files": [
        {
          "path": "https://unpkg.com/@fontsource/inter@5.0.18/files/inter-latin-400-normal.woff",
          "weight": 400
        },
        {
          "path": "https://unpkg.com/@fontsource/inter@5.0.18/files/inter-latin-700-normal.woff",
          "weight": 700
        }
      ]
    }
  }
}

You can also mix local and external fonts:

{
  "fonts": {
    "sans": {
      "family": ["Inter", "sans-serif"],
      "files": [
        { "path": "./fonts/Inter-Regular.woff", "weight": 400 },
        {
          "path": "https://unpkg.com/@fontsource/inter@5.0.18/files/inter-latin-700-normal.woff",
          "weight": 700
        }
      ]
    }
  }
}

Note: Use WOFF format (.woff) for best compatibility. WOFF2 is not supported by the underlying renderer.

Performance

  • Font caching - Fonts load once and are cached for all renders
  • Video optimization - 90-frame video loads fonts once, not 90 times
  • No CDN delays - Local fonts load instantly

Next Steps