Automated Font Conversion
Build CI/CD pipelines for automatic font conversion, optimization, and deployment. Learn GitHub Actions workflows, build scripts, and automation best practices.
TL;DR - Key Takeaways
- • Use fonttools/pyftsubset for command-line font conversion and subsetting
- • GitHub Actions can automatically convert fonts when source files change
- • Automate subsetting, format conversion, and CSS generation in one pipeline
- • Version artifacts with content hashes for cache-busting
In this article
Manual font conversion is error-prone and time-consuming. Each time a font updates, you need to re-convert, re-subset, regenerate CSS, and redeploy. Automated pipelines eliminate human error, ensure consistency, and free up developer time for more valuable work.
This guide covers building complete font automation pipelines using GitHub Actions, fonttools, and modern CI/CD practices. You'll learn to automatically convert source fonts to web formats, generate optimized subsets, create CSS files, and deploy to CDNs or NPM—all triggered by a simple git push.
The key benefits include reproducible builds, automated quality checks, instant deployment on font updates, and documented conversion processes that any team member can understand and modify.
Font Automation Tools
These command-line tools form the foundation of font automation pipelines.
fonttools / pyftsubset
Python library for font manipulation. Subset fonts, convert formats, and modify font tables.
woff2
Google's WOFF2 compression tool. Creates the smallest possible WOFF2 files.
glyphhanger
Analyze web pages to find used characters, then subset fonts to include only those glyphs.
fontforge
Open-source font editor with Python scripting. Complex transformations and format conversions.
Basic Conversion Script
Start with a simple shell script that converts TTF fonts to WOFF2 with Latin subsetting.
scripts/convert.sh
#!/bin/bash
# Convert all TTF files in sources/ to WOFF2 in fonts/
mkdir -p fonts
for ttf in sources/*.ttf; do
filename=$(basename "$ttf" .ttf)
# Subset to Latin characters and convert to WOFF2
pyftsubset "$ttf" \
--output-file="fonts/$filename.woff2" \
--flavor=woff2 \
--layout-features='*' \
--unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD"
echo "Converted $filename to WOFF2"
done
echo "Done! Converted $(ls fonts/*.woff2 | wc -l) files"Unicode Ranges Explained
The unicode range above covers Basic Latin, Latin Extended, common symbols, and typographic characters. Customize based on your language support needs.
GitHub Actions Workflow
Automate font conversion whenever source files change in your repository.
.github/workflows/fonts.yml
name: Build Fonts
on:
push:
paths:
- 'sources/**'
- 'scripts/**'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install fonttools brotli
sudo apt-get install -y woff2
- name: Convert fonts
run: |
chmod +x scripts/convert.sh
./scripts/convert.sh
- name: Generate CSS
run: |
chmod +x scripts/generate-css.sh
./scripts/generate-css.sh
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: web-fonts
path: |
fonts/
css/
- name: Commit changes
run: |
git config user.name github-actions
git config user.email [email protected]
git add fonts/ css/
git diff --staged --quiet || git commit -m "Build: Update web fonts"
git pushAutomated CSS Generation
Generate @font-face declarations automatically from converted font files.
scripts/generate-css.sh
#!/bin/bash
mkdir -p css
CSS_FILE="css/fonts.css"
# Clear existing CSS
> "$CSS_FILE"
# Map filename patterns to weights
declare -A weights=(
["thin"]=100
["light"]=300
["regular"]=400
["medium"]=500
["semibold"]=600
["bold"]=700
["black"]=900
)
for woff2 in fonts/*.woff2; do
filename=$(basename "$woff2" .woff2)
family=$(echo "$filename" | cut -d'-' -f1)
# Determine weight from filename
weight=400
for pattern in "${!weights[@]}"; do
if [[ "$filename" == *"$pattern"* ]]; then
weight=${weights[$pattern]}
break
fi
done
# Determine style
style="normal"
[[ "$filename" == *"italic"* ]] && style="italic"
cat >> "$CSS_FILE" << EOF
@font-face {
font-family: '$family';
src: url('../fonts/$filename.woff2') format('woff2');
font-weight: $weight;
font-style: $style;
font-display: swap;
}
EOF
done
echo "Generated CSS with $(grep -c '@font-face' "$CSS_FILE") font faces"Advanced Pipeline Features
Enhance your pipeline with these advanced automation features.
Content Hashing
Add content hashes to filenames for cache-busting.
# Generate hash from file content hash=$(sha256sum "fonts/$filename.woff2" | cut -c1-8) mv "fonts/$filename.woff2" "fonts/$filename.$hash.woff2"
Multi-Language Subsets
Generate separate files for different character sets.
# Latin pyftsubset font.ttf --unicodes="U+0000-00FF" --output-file=font-latin.woff2 # Cyrillic pyftsubset font.ttf --unicodes="U+0400-04FF" --output-file=font-cyrillic.woff2 # CJK (if supported) pyftsubset font.ttf --unicodes="U+4E00-9FFF" --output-file=font-cjk.woff2
NPM Publishing
Automatically publish to NPM when a release is tagged.
- name: Publish to NPM
if: startsWith(github.ref, 'refs/tags/v')
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Start Automating Font Conversion
Try our converter to understand font conversion before building your automated pipeline.
Start Converting FontsWritten & Verified by
Sarah Mitchell
Product Designer, Font Specialist
Automated Font Conversion FAQs
Common questions about CI/CD font pipelines
