Google Fonts Multi-Format API Usage Guide
This guide explains how to use the new multi-format Google Fonts API integration in Fontist, which provides access to TTF, Variable Fonts (VF), and WOFF2 formats.
Overview
The Google Fonts API integration now fetches data from three endpoints and merges them into a unified database:
-
TTF Endpoint - Standard TrueType fonts
-
VF Endpoint - Variable fonts with axes information
-
WOFF2 Endpoint - WOFF2 format files
Quick Start
require 'fontist' require 'fontist/import/google/api' # Get all font families (includes TTF, VF, and WOFF2 data) families = Fontist::Import::Google::Api.items puts "Total families: #{families.count}" # Access unified database db = Fontist::Import::Google::Api.database
Basic Operations
Get All Fonts
# Returns array of FontFamily objects all_fonts = Fontist::Import::Google::Api.items # Iterate through fonts all_fonts.each do |font| puts "#{font.family} (#{font.category})" end
Find Specific Font
# Find by familia name roboto = Fontist::Import::Google::Api.font_by_name("Roboto") if roboto puts "Family: #{roboto.family}" puts "Category: #{roboto.category}" puts "Variants: #{roboto.variants.join(', ')}" puts "Version: #{roboto.version}" puts "Last Modified: #{roboto.last_modified}" end
Filter by Category
# Get all sans-serif fonts sans_serif = Fontist::Import::Google::Api.by_category("sans-serif") puts "Sans-serif fonts: #{sans_serif.count}" # Get all monospace fonts monospace = Fontist::Import::Google::Api.by_category("monospace")
Variable Fonts
Get Variable Fonts Only
# Returns only fonts with variable font axes variable_fonts = Fontist::Import::Google::Api.variable_fonts_only puts "Variable fonts: #{variable_fonts.count}" variable_fonts.each do |font| puts "\n#{font.family}" font.axes.each do |axis| puts " #{axis.tag}: #{axis.start} to #{axis.end}" end end
Check if Font is Variable
font = Fontist::Import::Google::Api.font_by_name("Roboto Flex") if font&.variable_font? puts "#{font.family} is a variable font with #{font.axes.count} axes" # Access specific axes weight_axes = font.weight_axes width_axes = font.width_axes slant_axes = font.slant_axes custom_axes = font.custom_axes end
Working with Axes
font = Fontist::Import::Google::Api.font_by_name("Advent Pro") if font&.variable_font? font.axes.each do |axis| puts "Axis: #{axis.tag}" puts " Range: #{axis.start} - #{axis.end}" puts " Type: #{axis.description}" # Check axis type puts " Weight axis" if axis.weight_axis? puts " Width axis" if axis.width_axis? puts " Slant axis" if axis.slant_axis? puts " Custom axis" if axis.custom_axis? end # Find specific axis weight_axis = font.axis_by_tag("wght") if weight_axis puts "Weight range: #{weight_axis.range.inspect}" end end
Multiple Formats (TTF and WOFF2)
Check Available Formats
db = Fontist::Import::Google::Api.database # Fonts with TTF format ttf_fonts = db.fonts_with_ttf puts "Fonts with TTF: #{ttf_fonts.count}" # Fonts with WOFF2 format woff2_fonts = db.fonts_with_woff2 puts "Fonts with WOFF2: #{woff2_fonts.count}" # Fonts with both formats both_formats = db.fonts_with_both_formats puts "Fonts with both: #{both_formats.count}"
Access Format-Specific URLs
db = Fontist::Import::Google::Api.database # Get TTF URLs for a font ttf_files = db.ttf_files_for("Roboto") ttf_files.each do |variant, url| puts "#{variant}: #{url}" end # Get WOFF2 URLs for a font woff2_files = db.woff2_files_for("Roboto") woff2_files.each do |variant, url| puts "#{variant}: #{url}" end
Font Files Structure
font = Fontist::Import::Google::Api.font_by_name("Roboto") # The files hash contains TTF URLs by default font.files.each do |variant, url| puts "#{variant} (TTF): #{url}" end # Access both formats via database db = Fontist::Import::Google::Api.database ttf = db.ttf_files_for("Roboto") woff2 = db.woff2_files_for("Roboto")
Advanced Queries
Get Statistics
# Overall statistics stats = Fontist::Import::Google::Api.fonts_count puts "Total fonts: #{stats[:total]}" puts "Variable fonts: #{stats[:variable]}" puts "Static fonts: #{stats[:static]}" # Database-level statistics db = Fontist::Import::Google::Api.database puts "Categories: #{db.categories.join(', ')}"
Filter Static Fonts
# Get only static (non-variable) fonts static_fonts = Fontist::Import::Google::Api.static_fonts_only puts "Static fonts: #{static_fonts.count}"
Access Raw Endpoint Data
# For debugging or advanced use cases ttf_data = Fontist::Import::Google::Api.ttf_data vf_data = Fontist::Import::Google::Api.vf_data woff2_data = Fontist::Import::Google::Api.woff2_data puts "TTF endpoint: #{ttf_data.count} fonts" puts "VF endpoint: #{vf_data.count} fonts" puts "WOFF2 endpoint: #{woff2_data.count} fonts"
Caching
Clear Cache
# Clear all caches (database and client caches) Fontist::Import::Google::Api.clear_cache # Data will be re-fetched on next access families = Fontist::Import::Google::Api.items
Cache Behavior
-
API responses are cached at the client level
-
Database is built once and cached
-
Call
clear_cacheto force refresh from API
FontFamily Model
The FontFamily model provides:
font = Fontist::Import::Google::Api.font_by_name("Roboto") # Basic attributes font.family # "Roboto" font.category # "sans-serif" font.version # "v30" font.last_modified # "2022-09-22" # Variants and subsets font.variants # ["regular", "italic", "700", ...] font.subsets # ["latin", "latin-ext", ...] # Files (TTF URLs by default) font.files # {"regular" => "url", ...} # Variable font support font.variable_font? # true/false font.axes # Array of Axis objects (if VF) # Helper methods font.variant_names # Array of variant names font.file_urls # Array of file URLs font.variant_exists?("700") # Check if variant exists font.variant_url("regular") # Get URL for variant
Axis Model
The Axis model for variable fonts:
axis = font.axes.first # Attributes axis.tag # "wght", "wdth", "slnt", etc. axis.start # Minimum value (e.g., 100) axis.end # Maximum value (e.g., 900) # Helper methods axis.weight_axis? # Check if weight axis axis.width_axis? # Check if width axis axis.slant_axis? # Check if slant axis axis.custom_axis? # Check if custom axis axis.range # [start, end] axis.description # Human-readable description
Error Handling
begin families = Fontist::Import::Google::Api.items rescue StandardError => e puts "Error fetching fonts: #{e.message}" end # Check if font exists font = Fontist::Import::Google::Api.font_by_name("NonExistent") if font.nil? puts "Font not found" end
Example: List Variable Fonts with Axes
require 'fontist/import/google/api' puts "Variable Fonts with Axes\n" puts "=" * 60 Fontist::Import::Google::Api.variable_fonts_only.each do |font| puts "\n#{font.family}" puts " Category: #{font.category}" puts " Variants: #{font.variants.count}" puts " Axes:" font.axes.each do |axis| type = if axis.weight_axis? "Weight" elsif axis.width_axis? "Width" elsif axis.slant_axis? "Slant" else "Custom (#{axis.tag})" end puts " - #{type}: #{axis.start} to #{axis.end}" end end
Example: Download Fonts by Category
require 'fontist/import/google/api' require 'net/http' require 'fileutils' # Get all monospace fonts monospace_fonts = Fontist::Import::Google::Api.by_category("monospace") # Create download directory download_dir = "fonts/monospace" FileUtils.mkdir_p(download_dir) monospace_fonts.each do |font| puts "Downloading #{font.family}..." font.files.each do |variant, url| filename = "#{font.family.gsub(' ', '_')}-#{variant}.ttf" filepath = File.join(download_dir, filename) # Download file uri = URI(url) response = Net::HTTP.get_response(uri) if response.is_a?(Net::HTTPSuccess) File.binwrite(filepath, response.body) puts " ✓ #{filename}" else puts " ✗ Failed to download #{filename}" end end end puts "\nDownload complete!"
Architecture
The implementation consists of four layers:
1. Models Layer
-
FontFamily- Represents font families -
FontVariant- Represents font variants -
Axis- Represents variable font axes
2. Clients Layer
-
TtfClient- Fetches TTF data -
VfClient- Fetches VF data with axes -
Woff2Client- Fetches WOFF2 data
3. Database Layer
-
FontDatabase- Merges data from all endpoints
4. API Layer
-
Api- Public facade for accessing fonts
Configuration
Set your Google Fonts API key:
# Via environment variable ENV['GOOGLE_FONTS_KEY'] = 'your-api-key' # Or configure Fontist Fontist.google_fonts_key = 'your-api-key'
Testing
See spec/fontist/import/google/ for comprehensive test examples.
Run tests:
bundle exec rspec spec/fontist/import/google/
All 188 tests pass successfully! ✅