SHOPIFY
PROJECT ARCHITECTURE & RECENT FIXES RECAP
Core Tech Stack:
- Frontend Framework:
Astro v6 (configured for full SSR via output: ‘server’) - Routing:
Astro View Transitions () enabled globally inside BaseLayout.astro. - Backend Integration:
Headless Shopify Storefront API (@shopify/storefront-api-client). - Styling Framework:
Tailwind CSS v4 / Vite. - Component Paradigm:
Vanilla JavaScript, Event Delegation, and Custom Browser Events (No heavy frontend framework runtimes like React/Svelte on the client side).
1. API Route Optimization (src/pages/api/add-to-cart.ts)
The Problem:
The route was missing session persistence for live Shopify stores and didn’t flatten quantities for simple frontend reading.
What We Did:
- Fixed TypeScript error TS2345 by importing and applying Astro’s native AstroCookies type rather than using inline type assertions.
- Added code to read and update the live shopify_cart_id cookie (path: ’/’, maxAge: 30 days) so the shopping session persists seamlessly across page refreshes and server-side navigation.
- Map-reduced Shopify’s GraphQL nested nodes array (cart.lines.nodes) into a flat totalQuantity integer and returned it directly inside the final successful 200 JSON response.
2. View Transitions & Router Lifecycle Fixes
The Problem:
When navigating between pages via
What We Did:
- Wrapped event listeners and element selection queries inside local bootstrap functions (initHeader, initProductPage, setupCartDrawer) and bound them to Astro’s custom lifecycle hook: document.addEventListener(‘astro:page-load’, initFunction).
- This guarantees selectors find the fresh DOM elements after every page swap.
3. Frontend State & Event Unification
The Problem:
Adding an item to the cart caused a race condition where CartDrawer.astro instantly called GET /api/cart and finished in 1ms, displaying empty markup before Shopify’s server completed the POST request (which takes 600ms–1000ms).
What We Did:
- Unified the custom event payload. The add-to-cart button now waits for Shopify to finish, then dispatches a single custom browser event:
document.dispatchEvent(new CustomEvent(‘cart-updated’, { detail: { …data.cart, totalQuantity } })). - Header.astro listens for this event to instantly update the visual badge counter without layout flashes.
- CartDrawer.astro intercepts the exact same event and passes the layout object directly into its renderCart() method, drawing the visual item list instantly without needing a secondary background network request.
4. Tailwind CSS v4 IntelliSense Conflict Resolution
The Problem:
Elements like the cart badge and the product page’s scroll-based sticky bar (#sticky-atc) were throwing linting cssConflict warnings because flex and hidden utilities both try to manipulate the CSS display property.
What We Did:
- Replaced the standard class toggling with a clean, attribute-driven approach. The HTML element tracks its visibility state natively via data-visible=“false”.
- Removed hidden and leveraged Tailwind v4 modifier styling:
data-[visible=false]:invisible
data-[visible=true]:visible - Connected this to an IntersectionObserver that alters .setAttribute(‘data-visible’, ‘true’/‘false’).
- This cleared all linting errors and allowed smooth entrance transitions (transition-all duration-300 transform data-[visible=false]:translate-y-full data-[visible=false]:opacity-0) to play perfectly.
NEXT STEPS ON THE ROADMAP
- Live Data Integration: Populate real products with descriptive data, assets, and multiple variant options (size/color) inside the Shopify Admin panel to test path handling for /collections/[handle] and /products/[handle].
- Variant Option Selection: Ensure client-side interactions with option dropdowns successfully swap the primary data-variant-id attached to the add-to-cart firing function.
- Composed Content Tiers: Integrate Sanity CMS via @sanity/astro to render marketing pages and blocks natively using Astro structures, while using Sanity Connect to bridge Shopify IDs seamlessly into the content workspace.
- Localization: Activate Shopify Markets to configure multi-currency data payloads based on locale routing parameters.