DEV Community

Cover image for Font Manager: Multi-format Font export for Symfony
Wolf for Symfinity

Posted on

Font Manager: Multi-format Font export for Symfony

The Problem

Typography should be one of the simplest parts of a project.

In reality, it often ends up scattered across multiple layers:

  • Bootstrap: $font-family-base variables
  • Tailwind: JavaScript configuration
  • TypeScript: type definitions
  • Design systems: W3C Design Tokens

The same font information gets copied and maintained in several places. Every update means touching multiple files, hoping everything stays in sync.

It's repetitive, error-prone, and easy to get wrong.

So I built Font Manager.

Define your fonts once and export them in whatever format your project needs — CSS, Bootstrap variables, Tailwind configuration, TypeScript definitions, design tokens, and more.

The Solution

A simple Twig function:

{{ font_manager('Ubuntu', '400 700') }}
Enter fullscreen mode Exit fullscreen mode

Configuration:

symfinity_font_manager:
    export:
        formats:
            - scss_bootstrap
            - tailwind_config
            - typescript_definitions
Enter fullscreen mode Exit fullscreen mode

One lock command:

php bin/console fonts:lock
Enter fullscreen mode Exit fullscreen mode

Every format, automatically generated. Perfectly synced.

Bootstrap Example

Before:

// Manually copy font name
$font-family-base: 'Ubuntu', sans-serif;  // ❌ Duplication
@import 'bootstrap/scss/bootstrap';
Enter fullscreen mode Exit fullscreen mode

After:

symfinity_font_manager:
    export:
        formats: [scss_bootstrap]
Enter fullscreen mode Exit fullscreen mode
php bin/console fonts:lock
Enter fullscreen mode Exit fullscreen mode
// app.scss
@import './assets/styles/fonts-bootstrap';  // ← Auto-generated
@import 'bootstrap/scss/bootstrap';
Enter fullscreen mode Exit fullscreen mode

Bootstrap uses your fonts automatically. No manual mapping. No duplication.

Tailwind Example

symfinity_font_manager:
    export:
        formats: [tailwind_config]
Enter fullscreen mode Exit fullscreen mode
// tailwind.config.js
const fonts = require('./assets/fonts-tailwind.config.js');  // ← Auto-generated
module.exports = {
  theme: { extend: { fontFamily: fonts.fontFamily } }
};
Enter fullscreen mode Exit fullscreen mode
<p class="font-sans">Your custom font, via Tailwind.</p>
Enter fullscreen mode Exit fullscreen mode

TypeScript Example

symfinity_font_manager:
    export:
        formats: [typescript_definitions]
Enter fullscreen mode Exit fullscreen mode
import { fonts, type FontFamily } from './assets/fonts';
Enter fullscreen mode Exit fullscreen mode
applyFont(element, 'sans');     // ✓ Valid
applyFont(element, 'invalid');  // ✗ TypeScript error!
Enter fullscreen mode Exit fullscreen mode

Typos caught at compile time.

The 12 Formats

CSS, SCSS, JavaScript, Design Tokens — pick what you need:

php bin/console fonts:formats
Enter fullscreen mode Exit fullscreen mode

CSS: Variables, Modules, @layer
SCSS: Variables, Bootstrap, Mixins
JavaScript: ESM, Tailwind, TypeScript
Design System: JSON, W3C Tokens, Figma, Style Dictionary

Build Tools

AssetMapper, Webpack, or Vite? Auto-detected.

Output paths adjust automatically. No config needed.

Design Systems

Export to Figma Tokens, Style Dictionary, or W3C Design Tokens:

formats:
    - design_tokens
    - figma_tokens
Enter fullscreen mode Exit fullscreen mode
npx style-dictionary build  # CSS, iOS, Android from one source
Enter fullscreen mode Exit fullscreen mode

Design once. Ship everywhere.

Privacy Options

Not just Google — choose your provider:

symfinity_font_manager:
    default_provider: 'bunny'  # GDPR-compliant, zero tracking
Enter fullscreen mode Exit fullscreen mode

Google, Bunny, Fontsource, or Local. Same API. Your choice.

How It Works

Architecture: Strategy pattern. Each format is a separate exporter.

Dependency resolution: Automatic. css_modules needs css_variables? Handled.

Build detection: Scans for webpack.config.js, vite.config.js, asset_mapper.yaml.

Output paths: Adjusted per build tool. AssetMapper → assets/styles/. Webpack → assets/.

Commands:

php bin/console fonts:formats           # List all formats
php bin/console fonts:format:info scss  # Usage instructions
php bin/console fonts:export            # Export manually
Enter fullscreen mode Exit fullscreen mode

Migrating from google-fonts

One command:

php bin/console fonts:migrate-from-google-fonts
Enter fullscreen mode Exit fullscreen mode

Config, templates, manifest — all updated automatically.

Prerequisite

Go to github.com/symfinity/recipes and follow the instructions to add the required recipe repository.

Installation

composer require symfinity/font-manager
Enter fullscreen mode Exit fullscreen mode

That’s it. Symfony Flex does the rest.

Quick Start

{{ font_manager('Ubuntu', '400 700') }}
Enter fullscreen mode Exit fullscreen mode

Dev: CDN
Prod: Self-hosted (after fonts:lock)

Add exports:

symfinity_font_manager:
    export:
        formats: [scss_bootstrap, tailwind_config]
Enter fullscreen mode Exit fullscreen mode

Lock:

php bin/console fonts:lock
Enter fullscreen mode Exit fullscreen mode

Use:

@import './fonts-bootstrap';
@import 'bootstrap/scss/bootstrap';
Enter fullscreen mode Exit fullscreen mode

Done.

Conclusion

Typography shouldn’t waste your time or violate privacy law.
With font-manager, you can design freely in development, ship safely in production, and forget about fonts altogether.

One Twig function. Multiple providers. Twelve export formats. Zero manual mapping.

That’s Font Manager.

Try it now: symfinity/font-manager

If you find it useful, star the repository and share it with your Symfony community.


What's next

Don't miss the introduction series to Symfinity:

Another package-level deep dive:

Articles on further Symfinity package tiers are planned, this is just the beginning.

Explore packages and source at github.com/symfinity.

This article was previously published on medium.com.

Top comments (0)