# Subbly E-commerce Integration This document explains how to integrate with the Subbly platform to retrieve product information and manage the shopping cart in your Next.js application. ## General Information - By default you are using `addToCart` method from a `useSubblyCart` hook from the `@subbly/react` package, but users sometimes can ask to add a direct link to check. In that case use `buyLink` from `useBuyLink` hook from the `@subbly/react` package. For server side you can use `createBuyLink` from `@subbly/kit/cart` with the same input properties as `useBuyLink` - All prices are defined in integers(cents), not decimals. - When creating cart icon or cart counter, use these CSS classes to connect them with Subbly cart: `subbly-cart-product-count`, `subbly-cart`. - These classes will automatically toggle cart widget and update cart counter when items are added or removed from the cart. - If you see that in the existing code the cart icon or cart counter is not working, check if these classes are used and propose to add them. - In VERY RARE CASES, you can update these classes inside `src/lib/subbly/subbly-script.tsx` file with the `cartToggleEl` and `cartCountEl` properties. ## Subbly integration tools ### `@subbly/react` package `@subbly/react` provides tools to: - conveniently fetch data from Subbly storefront API; - use premade forms for specific product types; - re-shape the data using hooks and helper functions; - render formatted data in components; ## Currency Formatting The application uses a custom `useFormatAmount` hook from `@/hooks/use-format-amount` for currency formatting. - `formatAmount(amountInCents: number): string` - Formats an integer amount (in cents) to a localized currency string ## Component Usage Guidelines 1. **ProductInfoSection**: Displays product name, description, and product form (variants, plans, quantity selector) - **Required for**: Product detail pages - **Props**: `product: Product` - **Customization**: You can style the container and typography, but the component logic must remain intact 2. **ProductGallerySection**: Displays product images in a carousel with thumbnails - **Required for**: Product and bundle detail pages - **Props**: `images: ProductImage[]`, `productName: string` - **Customization**: You can style the gallery appearance, but the carousel functionality must remain intact 3. **CustomizeBundleSection**: Unified bundle component that handles ALL bundle types with automatic mode detection - **Location**: `src/components/subbly/bundle/customize-bundle-section.tsx` - **Required for**: All bundle detail pages - **Automatic Mode Detection**: Component automatically detects bundle type and renders appropriate UI: - **Fixed Mode** (`bundle.selectionType === null`): Non-customizable bundles with direct add to cart and optional plan selection - **Single-Product Mode** (`bundle.selectionType === 'single_product'`): Group-based selection with one variant per product group, uses VariantSelector for better UX - **Multi-Product Mode** (`bundle.selectionType === 'variant' or 'product'`): Full customization with item selection, quantity controls, preferences, receipt, and validation - **Props**: - `bundle: Bundle` (required) - The bundle data object from Subbly API - `groupItemsByProduct?: boolean` - Only applies to Multi-Product mode. Groups items by their parent product instead of showing a flat list - `allowMultipleItemsInGroup?: boolean` - Only applies to Multi-Product mode and when `groupItemsByProduct` enabled. Controls whether users can select multiple variants from the same product. - **Mode Behaviors**: - **Fixed Mode**: Shows plan selector (if multiple plans exist) and add to cart button. Uses `useBundleForm` hook - **Single-Product Mode**: Shows group selection with VariantSelector (radio or dropdown), preferences, plan selector, and add to cart. Uses `useBundleForm` + `useBundleProductGroupedItemsForm` hooks. Renders single-column layout similar to product detail pages - **Multi-Product Mode**: Full customization interface with size selection, preferences, item selection, selected items sidebar, receipt, and validation. Uses `useBundleForm` + `useBundleReceipt` + `useBundleValidation` hooks. Renders one-step or two-step layout based on `bundle.appearanceType` - **Appearance Type Support** (Multi-Product mode only): - `one_step`: All options visible in two-column layout (items left, summary right) - `two_step`: Progressive disclosure (Step 1: preferences/size/plan, Step 2: item selection) - `after_checkout`: Items selected after checkout - `without_ruleset`: No size selection, auto-match ruleset - **Customization**: The component uses internal layouts (FixedLayout, SingleProductLayout, OneStepLayout, TwoStepLayout) that can be styled, but core logic must remain intact - **ProductGallerySection Rendering**: On bundle detail pages, render `ProductGallerySection` alongside `CustomizeBundleSection` only when: - `bundle.selectionType === null` (Fixed Mode) - shows bundle images in gallery format - `bundle.selectionType === 'single_product'` (Single-Product Mode) - shows bundle images in gallery format - Do NOT render `ProductGallerySection` for Multi-Product mode (`selectionType === 'variant'` or `'product'`) as items have their own images in the selection UI 4. **AddToCartButton**: Handles adding products or bundles to the cart - **Required for**: Any page with add-to-cart functionality - **Props**: `payload: ConfigureItemPayload` - **Customization**: You can style the button appearance and provide custom children, but the cart logic must remain intact 5. **TestpaketOfferSection**: Promotional offer section for the Quetschbeutel test package - **Location**: `src/components/awake-quetschbeutel/testpaket-offer-section.tsx` - **Required for**: Standalone offer pages and the home hero Quetschbeutel modal - **Props**: `flow: AwakeFlowContext`, `sectionId?: string`, `headingLead?: string`, `headingHighlight?: string`, `variant?: "default" | "modal"` - **Variants**: - `default`: Two-column layout (pricing/testimonial on the left, product image and included list on the right) - `modal`: Single-column, stacked layout intended for use inside a dialog; removes horizontal overflow and centers the image - **Customization**: Keep the checkout handler (`useQuetschbeutelCheckout`) and pricing logic intact; only adjust layout/styling ## Recent Changes - Updated home hero translations across all locales (`de`, `en`, `es`, `it`): - New badge: "EUROPE'S NO. 1 · UP TO 11 PPM H₂" (localized variants) - New H1: "Pure hydrogen water from Germany" (localized variants) - New subline: "Up to 11 ppm molecular hydrogen – 100% pure, no additives, ready to drink. Made in Germany." (localized variants) - Drinks-consumed count increased from 300,000 to 450,000 (localized variants, e.g. "450,000+ AWAKE consumed", "450.000+ AWAKE getrunken", "Más de 450.000 AWAKE consumidos", "450.000+ AWAKE bevute") - Fixed the Quetschbeutel popup/modal in the home hero: - `TestpaketOfferSection` now supports a `variant` prop (`"default"` | `"modal"`) - The home hero modal uses `variant="modal"` with a single-column, stacked layout - Reduced the `DialogContent` width to `sm:max-w-[680px]` to remove the horizontal scrollbar and improve visual appearance - Added a new navigation item for the Quetschbeutel product across all locales (`de`, `en`, `es`, `it`): - New nav key: `nav.quetschbeutel` ("Quetschbeutel" / "Squeeze Pouch" / "Bolsa" / "Bustina") - New mega-menu keys: `megaMenu.quetschbeutelTitle` and `megaMenu.quetschbeutelDescription` - New footer key: `footer.quetschbeutel` - Updated the desktop mega menu (`src/components/layout/mega-menu.tsx`) to include a third product card linking to `/awake-quetschbeutel` - Updated the mobile menu (`src/components/layout/mobile-nav.tsx`) to include the Quetschbeutel link under the shop section - Updated the footer (`src/components/layout/footer.tsx`) to include the Quetschbeutel link under the shop column