Dev Log: Modernizing the Oatopia Shopify Experience

Weekly Sprint Report: February 4 – February 6, 2026

This week, we executed a comprehensive technical overhaul of the Oatopia Shopify theme. Our focus shifted from foundational modernization of legacy assets to high-level performance tuning and UX polishing.

:high_voltage: Performance & Core Web Vitals

Speed is a feature. We spent significant time reducing page weight and optimizing how the browser handles our most important assets.

  • Image Modernization: Conducted a project-wide audit to replace legacy filters (img_url, file_img_url, asset_img_url) with the modern image_url standard.

  • Next-Gen Delivery: Enabled automatic WebP/AVIF delivery via Shopify CDN and implemented loading="lazy" for off-screen images.

  • LCP Optimization: Updated the collection banner to use fetchpriority="high", signaling the browser to prioritize the hero image immediately.

  • HTML Bloat Reduction: Refactored the QuickBuy feature to use a minimal manual JSON object instead of injecting massive data for every product card, drastically reducing page weight.

  • Asset Loading: Moved global.bundle.js to the end of the body to unblock rendering and implemented a “print” media trick for non-blocking Adobe Typekit fonts.

:world_map: Navigation & Header Architecture

We addressed several layout shifts and usability hurdles within the site’s navigation.

  • Smart Hover Logic: Added a 150ms grace period to dropdowns and implemented auto-close logic for adjacent menus to prevent overlapping during mouse sweeps.

  • Desktop-to-Mobile Parity: Fixed an issue where secondary links like “Account” were missing from the mobile drawer by updating snippets/sidebar-nav.liquid.

  • Mega Menu Styling: Updated the layout to support a 3-column categorical structure (e.g., Shop > Oat Bakes, Flapjacks, Giftboxes).

  • Flexibility: Removed hardcoded CSS constraints to restore dynamic logo sizing based on theme settings.

:paintbrush: UI/UX & Visual Consistency

Refining the “feel” of the store to match the Oatopia brand identity.

  • Grid Stability: Optimized product grids to ensure rows are fully filled (no empty slots).

  • Mobile “Gap” Fix: Forced mobile 2-column grids to always be divisible by 2 to prevent “hanging” items at the end of a page.

  • Interactive Polish: Added a “Zoom + Bold” effect for dropdown items and increased horizontal padding on “View All” buttons for better prominence.

  • Brand Styling: Customized the footer “Subscribe” button with a Blueberry background and Demarara text.

  • Layout Fixes: Applied flex-nowrap to the header to prevent the Search and Cart icons from “squishing” on smaller desktop screens.

:hammer_and_wrench: Technical Fixes & SEO

Behind-the-scenes improvements for long-term site health.

  • Scroll Locking: Implemented JavaScript handlers for full body-scroll locking when menus are open to prevent secondary page scrolling.

  • SEO Hardening: Applied rel="nofollow" to all raw image thumbnail links to prioritize high-value page indexing.

  • Enhanced Product Blocks: Updated the product template schema to support multiple independent, per-product FAQ/Collapsible blocks.

  • Alpine.js Integration: Enhanced the menu state management using Alpine.js to handle hover delays and click-outside events effectively.

:chequered_flag: Conclusion

By the end of this sprint, all core modernization, performance optimization, and layout stabilization tasks have been completed and verified on the development theme. The site now boasts a significantly more robust navigation system and a leaner code architecture, particularly regarding image handling and HTML delivery

How you have managed the other LCP issues, related to Application scripts?

Beyond the image optimization itself, I focused on reducing script-related delays affecting LCP.

I moved global.bundle.js to the end of the body and deferred non-critical scripts so they don’t block initial rendering. I also refactored the QuickBuy feature to remove large inline JSON from product cards, which reduced DOM size and script parsing time.

Interactive scripts (dropdowns, Alpine.js logic, etc.) now initialize after the hero content is rendered, and third-party assets like Typekit load non-blocking.

Overall, this ensured the browser could prioritize painting the LCP element immediately, without being delayed by heavy script execution or main-thread work.

@highcenburg ,

Thanks for the detailed explanation. Few follow-up question:

  1. how did you determine which scripts were safe to defer or move without affecting functionality (especially QuickBuy and interactive components), and did you validate LCP improvements using field data (CrUX) or only lab data like PageSpeed/Lighthouse?
  • How did you identify and measure long tasks caused by global.bundle.js (e.g. via Performance panel / Long Tasks API), and did you split or tree-shake the bundle after deferring?
  • For QuickBuy, was the inline JSON removal paired with lazy hydration or conditional data fetching to avoid delaying user interaction?
  • How did you coordinate deferred script execution with LCP stability (avoiding late layout shifts or delayed font swaps)?

Thanks for the follow-up — great questions.

Script Deferring Decisions
I identified safe-to-defer scripts by mapping what was required for first paint vs. post-render interactivity. Anything not required to render the hero, header layout, or above-the-fold content was deferred. QuickBuy and Alpine-driven components were tested both with throttling and JS disabled to confirm no critical rendering dependency existed before moving execution.

LCP Validation
Initial improvements were validated via Lighthouse and Chrome DevTools (Performance panel). After implementation, I cross-checked in PageSpeed Insights to compare lab and field (CrUX) trends to ensure improvements aligned with real-user metrics.

Long Task Identification
I used Chrome DevTools’ Performance panel to analyze main-thread activity and isolate long tasks tied to global.bundle.js parsing and execution. The biggest issue wasn’t just execution time but DOM weight from inline JSON. After reducing that payload, parsing cost dropped significantly. Full bundle splitting wasn’t required at this stage because deferring and DOM reduction resolved the main LCP bottleneck.

QuickBuy Optimization Approach
Inline JSON removal was paired with lightweight conditional initialization. Instead of hydrating every product card upfront, the QuickBuy logic now activates only on user interaction, preventing unnecessary upfront processing.

LCP Stability Coordination
Deferred scripts were sequenced to run after initial layout stabilization. Header/grid layout constraints were enforced in CSS to prevent JS-triggered reflows, and the Typekit swap was implemented in a non-blocking way to avoid font-induced layout shifts affecting LCP.