projects/StrivEvo
Mobile-first Shopify landing page theme built on Skeleton: dependency-free product form, sticky buy bar, and a section-rendered AJAX cart drawer.

A mobile-first Shopify Online Store 2.0 theme for strivevo.com, built on Shopify's Skeleton theme and designed as a single high-converting landing page for one compression knee support product. Everything is hand-written Liquid and vanilla JavaScript using native Web Components, with no slider, cart, or UI libraries. The product form resolves variants client-side from inline JSON and syncs price, availability, gallery, and URL without a reload, a sticky buy bar appears on mobile only when the main add-to-cart button leaves the viewport, and the cart drawer re-renders from Shopify's Section Rendering API so the server stays the source of truth for cart markup. Sections, snippets, and blocks are documented with LiquidDoc, all copy is translatable through locale files, and colours, type, and radii are driven by CSS variables generated from theme settings.
Key architectural decisions, concrete code implementations, and performance wins behind this project.
A knee support ships in many size and colour combinations. Reloading the page on every option change is slow on mobile and loses the buyer's place in the gallery.
Inlined the product as JSON and built a <product-form> custom element that matches the checked radio values against product.variants, then updates the hidden variant id, add-to-cart label and price, the gallery slide bound to the variant's featured media, and the ?variant= query string via history.replaceState.
On a long mobile landing page the buy button scrolls out of reach, but an always-on fixed bar covers content and duplicates the button while it is already on screen.
Observed the main add-to-cart button with an IntersectionObserver and revealed the fixed bar only when that button leaves the viewport on screens under 990px. The bar toggles aria-hidden with its visibility and forwards clicks to the main button, so validation and AJAX logic live in one place.
Rebuilding cart markup in JavaScript duplicates the Liquid template, drifts out of sync with it, and gets currency, discounts, and line properties wrong.
Requested the cart-drawer section in the same /cart/add.js call, so the response carries server-rendered HTML that replaces the drawer contents and opens it. Any failure falls back to native form submission, so the buyer can always check out.
The drawer's innerHTML is replaced after every cart change, which destroys per-button listeners, and a modal cart must still be keyboard and screen-reader friendly.
Built a <cart-drawer> custom element that binds one delegated click handler on itself, so quantity and remove buttons keep working after each re-render. It updates lines through /cart/change.js with the section id, handles Escape, locks body scroll, and moves focus into the dialog on open.
Wrong-size purchases are the main return risk for a fitted product, so the size guide has to be one tap away without a modal library or a focus-trap script.
Used the browser's native <dialog> with showModal() for focus trapping, Escape handling, and the ::backdrop, and closed it on backdrop click by comparing event.target to the dialog element. A LiquidDoc header documents the snippet, and CSS presents it as a bottom sheet on phones.
// community_discussion
Have thoughts, questions, or ideas regarding this system's architecture? Leave a comment below with your GitHub account.