@lime-bundles/react
v4.0.0
Published
React components and hooks for the Lime Bundles Shopify app. Use on Hydrogen, Next.js, Vite, or any React-based headless storefront.
Maintainers
Readme
@lime-bundles/react
React components and hooks for the Lime Bundles Shopify app. Use on Hydrogen, Next.js, Vite, Remix, or any React renderer. If you're not a merchant using Lime Bundles, this package probably isn't what you're looking for.
Bring your own cart via an onAddToCart callback; the SDK handles data fetching, rendering, and analytics.
Install
npm install @lime-bundles/react @lime-bundles/corePeer dependencies: react >=18, react-dom >=18.
Drop-in components
import { FixedBundle } from "@lime-bundles/react";
<FixedBundle
shopDomain="my-shop.myshopify.com"
storefrontAccessToken={process.env.NEXT_PUBLIC_LIME_BUNDLES_TOKEN!}
bundleGid="gid://shopify/Metaobject/42"
onAddToCart={async (lines) => {
await fetch("/api/cart/add", { method: "POST", body: JSON.stringify(lines) });
}}
onError={(err) => console.error(err)}
/>Same props for <VolumeBundle> and <MixMatchBundle>.
Props: BundleComponentProps
| Prop | Type | Required | Notes |
|---|---|:-:|---|
| shopDomain | string | ✓ | Your *.myshopify.com domain. |
| storefrontAccessToken | string | ✓ | Generated in /app/settings/headless. |
| bundleGid | string | ✓ | Bundle metaobject GID. |
| onAddToCart | (lines: CartLineInput[]) => Promise<void> | ✓ | Must return a Promise; components await it for loading states. |
| appUrl | string | | Required only if analytics are enabled. |
| analyticsEnabled | boolean | | Default true. false suppresses impression + add-to-cart POSTs. |
| onError | (error: Error) => void | | Fires on fetch, parse, or cart failure. |
| locale | string | | BCP-47 tag forwarded to the Storefront API. |
| className | string | | Applied to the outer wrapper. |
CartLineInput matches Shopify Hydrogen's shape. A structural-compat test guards the contract across versions. Always preserve attributes[] so _lime_bundle_gid reaches Shopify; the orders/create webhook keys off it for purchase attribution.
Hooks
useBundleData({ shopDomain, storefrontAccessToken, bundleGid })
Fetches a single bundle by GID. Discriminated-union result.
import { useBundleData } from "@lime-bundles/react";
function MyBundle({ bundleGid }: { bundleGid: string }) {
const result = useBundleData({ shopDomain, storefrontAccessToken, bundleGid });
if (result.status === "loading") return <Skeleton />;
if (result.status === "error") return <Error message={result.error.message} />;
return <pre>{JSON.stringify(result.bundle, null, 2)}</pre>;
}useBundlesForProduct({ shopDomain, storefrontAccessToken, productHandle })
Fetches every active bundle configured against a product. Equivalent to the web component's auto-detect mode. Inactive and out-of-schedule bundles are filtered out.
import { useBundlesForProduct } from "@lime-bundles/react";
const result = useBundlesForProduct({ shopDomain, storefrontAccessToken, productHandle });
if (result.status === "success") {
return result.bundles.map((b) => <FixedBundle key={b.id} bundleGid={b.id} {...cartProps} />);
}Both hooks auto-fetch merchant custom CSS and inject it as a scoped <style> tag. Unmount / dependency change cancels the in-flight request.
Async fetchers for SSR / RSC
For Hydrogen loaders, Next.js Server Components, or getServerSideProps: skip the hook and use the async helpers directly.
import { fetchBundleData, fetchBundlesForProduct } from "@lime-bundles/react";
const bundle = await fetchBundleData({
shopDomain,
storefrontAccessToken,
bundleGid,
buyerIp: request.headers.get("x-forwarded-for")?.split(",")[0].trim(),
});buyerIp is mandatory on SSR. Shopify returns 430 Security Rejection for server-originated traffic without it.
Build your own UI
Everything the built-in components use is re-exported for DIY consumers: pricing math, CSS-variable flatteners, image CDN transforms, countdown formatter, A/B merge, etc. See the Build your own UI doc for the full primitives list.
Styling
Merchant widget styling is applied automatically when you use <FixedBundle> / <VolumeBundle> / <MixMatchBundle>. For DIY UI, apply the config yourself:
import { applyWidgetConfigVars } from "@lime-bundles/react";
useEffect(() => {
if (ref.current) applyWidgetConfigVars(ref.current, bundle.widgetConfig);
}, [bundle.widgetConfig]);Full CSS variable reference: css-variables.md.
Version policy
BundleComponentProps, UseBundleDataResult, and UseBundlesForProductResult are locked at v2.0.0. All three packages (core, react, widget) bump majors together.
License
MIT.
Support
Merchant support and bug reports: email via the Lime Bundles listing on the Shopify App Store.
