spatie/laravel-google-fonts
Self-host Google Fonts in Laravel with minimal setup. Register Google Fonts CSS URLs in config and load them via the @googlefonts Blade directive. On first request it downloads CSS/assets, caches locally, inlines CSS, and falls back to Google if needed.
Installation
composer require spatie/laravel-google-fonts
php artisan vendor:publish --provider="Spatie\GoogleFonts\GoogleFontsServiceProvider" --tag="google-fonts-config"
config/google-fonts.php file with default settings.Configure Fonts
Add your Google Font embed URLs to the fonts array in config/google-fonts.php:
'fonts' => [
'default' => 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
'secondary' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400&display=swap',
],
First Use Case
Load fonts in a Blade view using the @googlefonts directive:
<head>
@googlefonts <!-- Loads 'default' font -->
@googlefonts('secondary') <!-- Loads 'secondary' font -->
</head>
Prefetch Fonts (Optional) Run the Artisan command to pre-download fonts for immediate availability:
php artisan google-fonts:fetch
Font Registration & Usage
config/google-fonts.php with descriptive keys (e.g., default, code).@googlefonts('key') in Blade templates to load specific fonts.@googlefonts (no argument).Dynamic Font Loading
@googlefonts for advanced options (e.g., CSP nonces):
@googlefonts(['font' => 'secondary', 'nonce' => csp_nonce()])
Prefetching Strategy
php artisan google-fonts:fetch during deployment to pre-download all fonts.lazy mode (v1.6+) by modifying the GoogleFontsManager service provider to defer fetching until first request:
// In a service provider or config
$this->app->singleton(GoogleFontsManager::class, function ($app) {
return new GoogleFontsManager($app['config'], $app['files'], $app['cache'], true); // true = lazy
});
Integration with CSP
nonce option to comply with Content Security Policy (CSP):
@googlefonts(['nonce' => csp_nonce()])
Multi-Environment Setup
config/google-fonts.php):
'fonts' => [
env('APP_ENV') === 'production'
? 'production_url_here'
: 'development_url_here',
],
Custom Disk/Path Configuration
'disk' => 's3',
'path' => 'custom-fonts-path',
Fallback Behavior
config/google-fonts.php:
'fallback' => false, // Throws exceptions on failure (debug mode only)
Conditional Font Loading
@if(auth()->check())
@googlefonts('premium-font')
@endif
Local Development Optimization
'inline' => env('APP_ENV') === 'local' ? false : true,
Font Preloading
'preload' => true,
preload: true.Storage Link Requirement
php artisan storage:link to symlink storage/app/public to public/storage.User Agent Limitations
user_agent in config to target older formats:
'user_agent' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
Caching Quirks
php artisan cache:clear
php artisan view:clear
php artisan google-fonts:fetch --force to re-fetch fonts.Duplicate Font URLs
Nonce Mismatches
@googlefonts(['nonce' => csp_nonce()])
// In CSP middleware
$directive->addStyleSources(['nonce' => csp_nonce()]);
Git Ignore Conflicts
storage/app/public/fonts is ignored by .gitignore..gitignore if you want to version-control fonts:
!/storage/app/public/fonts/
Check Fetch Logs
'fallback' => true, // Logs errors to Laravel logs
storage/logs/laravel.log.Verify Font Files
storage/app/public/fonts after running google-fonts:fetch.php artisan storage:link if files are missing in public/storage/fonts.Test Fallback Behavior
// In AppServiceProvider
$this->app->bind(GoogleFontsManager::class, function () {
return new class {
public function render($font = null) { return '<link href="https://fonts.googleapis.com/..." rel="stylesheet">'; }
};
});
Inspect Blade Output
@dd to debug the directive’s output:
@googlefonts(['font' => 'test'])
@dd($__env->yieldContent('googlefonts'))
Custom Fetch Logic
GoogleFontsManager to implement custom fetching (e.g., proxy requests):
$manager->setFontFetcher(new CustomFontFetcher());
Dynamic Font Registration
$config = config('google-fonts.fonts');
$config['dynamic-font'] = 'https://fonts.googleapis.com/...';
config(['google-fonts.fonts' => $config]);
Post-Fetch Processing
FontFetcher to modify downloaded files (e.g., optimize WOFF2):
use Spatie\GoogleFonts\FontFetcher;
class CustomFontFetcher extends FontFetcher {
protected function processFontFile($contents, $url) {
// Custom logic (e.g., compression)
return parent::processFontFile($contents, $url);
}
}
Event Listeners
use Spatie\GoogleFonts\Events\FontsFetched;
FontsFetched::listen(function (FontsFetched $event) {
Log::info('Fetched fonts:', $event->fonts);
});
Conditional Inlining
'inline' => function () {
return !request()->isMobile();
},
How can I help you explore Laravel packages today?