Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@ All notable changes to the Nynaeve theme will be documented in this file.

For project-wide changes (infrastructure, tooling, cross-cutting concerns), see the [project root CHANGELOG.md](../../../../../CHANGELOG.md).

## [2.0.17] - 2025-11-24

### Fixed
- **Speed Optimization: Hero Image Eager Loading** ([HeroBlock.php:181-198](app/Blocks/HeroBlock.php#L181-L198))
- Changed hero desktop image from `loading="lazy"` to `loading="eager"`
- Added `fetchpriority="high"` attribute to prioritize LCP image download
- **Root cause**: Lazy loading the LCP (Largest Contentful Paint) image caused 2,360ms "Resource load delay"
- Browser was waiting to determine if image was in viewport before loading
- **Impact**: ~2+ seconds LCP improvement expected

### Added
- **Speed Optimization: Font Preloading** ([setup.php:400-436](app/setup.php#L400-L436))
- Added preload hints for Open Sans regular (400) and semibold (600) fonts
- Fonts are preloaded early in `<head>` before CSS parsing begins
- Uses Vite manifest to resolve hashed font filenames
- **Root cause**: CLS (Cumulative Layout Shift) of 0.602 caused by late font loading
- When Open Sans loaded after initial render, text reflowed and shifted layout
- **Impact**: CLS reduction expected (target < 0.1)

### Documentation
- Updated `docs/nynaeve/SPEED-TWEAKS.md` with new optimizations 8, 9, and 10

## [2.0.16] - 2025-11-24

### Added
Expand Down
4 changes: 3 additions & 1 deletion app/Blocks/HeroBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ public function with(): array

// Generate responsive image HTML for desktop
// Uses 'hero-desktop' size (600x348) with srcset for retina (1200x696)
// IMPORTANT: Hero image is the LCP element - must use eager loading, not lazy
$desktop_image_html = '';
$desktop_image_alt_value = $desktop_image['alt'] ?? ($desktop_image['title'] ?? 'Desktop image');
if (! empty($desktop_image['ID'])) {
Expand All @@ -189,7 +190,8 @@ public function with(): array
false,
[
'class' => 'desktop-only-img object-cover w-full h-full',
'loading' => 'lazy',
'loading' => 'eager',
'fetchpriority' => 'high',
'sizes' => '(min-width: 1024px) 576px, 50vw',
]
);
Expand Down
38 changes: 38 additions & 0 deletions app/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,41 @@ class="text-center w-full px-4 py-3 bg-indigo-600 flex items-center
],
]);
}, 10, 2);

/**
* Preload critical fonts to reduce CLS (Cumulative Layout Shift).
*
* Open Sans is the primary body font and causes significant layout shift (CLS 0.602)
* when it loads late. Preloading tells the browser to fetch it early, before CSS parsing.
*
* @link https://web.dev/preload-critical-assets/
* @link https://web.dev/optimize-cls/#web-fonts-causing-foit/fout
*/
add_action('wp_head', function () {
// Get the Vite manifest to find the hashed font filename
$manifest_path = get_theme_file_path('public/build/manifest.json');

if (! file_exists($manifest_path)) {
return;
}

$manifest = json_decode(file_get_contents($manifest_path), true);

if (! is_array($manifest)) {
return;
}

// Preload Open Sans regular (400) - most commonly used weight
$font_key = 'resources/fonts/open-sans-v40-latin-regular.woff2';
if (isset($manifest[$font_key]['file'])) {
$font_url = get_theme_file_uri('public/build/'.$manifest[$font_key]['file']);
echo '<link rel="preload" as="font" type="font/woff2" href="'.esc_url($font_url).'" crossorigin="anonymous">'."\n";
}

// Preload Open Sans semibold (600) - used for headings and emphasis
$font_key_600 = 'resources/fonts/open-sans-v40-latin-600.woff2';
if (isset($manifest[$font_key_600]['file'])) {
$font_url_600 = get_theme_file_uri('public/build/'.$manifest[$font_key_600]['file']);
echo '<link rel="preload" as="font" type="font/woff2" href="'.esc_url($font_url_600).'" crossorigin="anonymous">'."\n";
}
}, 1); // Priority 1 to run very early in <head>
2 changes: 1 addition & 1 deletion style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Theme Name: Nynaeve
Theme URI: https://imagewize.com
Description: Modern WordPress theme built on Sage 11 with reusable custom blocks using WordPress native tools and the Roots.io stack.
Version: 2.0.16
Version: 2.0.17
Author: Jasper Frumau
Author URI: https://magewize.com
Text Domain: nynaeve
Expand Down