@cobrastyle/storefront-core
v1.4.3
Published
Cobrastyle headless commerce engine — adapter routing, server actions, hooks and cookie helpers shared across storefronts.
Readme
@cobrastyle/storefront-core
The Cobrastyle headless commerce engine — adapter routing, server actions, React hooks, and cookie helpers shared across all customer storefronts.
This package is a workspace dependency of the storefront reference app and should be the direct dependency of any new customer storefront built on the Cobrastyle platform.
Installation
pnpm add @cobrastyle/storefront-core @cobrastyle/shared-types
# plus the adapter(s) you need:
pnpm add @cobrastyle/adapter-magento2 @cobrastyle/adapter-enad @cobrastyle/adapter-dummy-dataSubpath entry points
The package exposes five subpath entry points. They must not be mixed freely across RSC boundaries — see the boundary column.
| Import | Boundary | Exports |
|--------|----------|---------|
| @cobrastyle/storefront-core | neutral (no server-only) | configureStorefront, ConfigureStorefrontOptions, AdapterLoaderFn, AdapterLoaderConfig, AnalyticsConfig |
| @cobrastyle/storefront-core/adapter | server-only | getAdapter, adapter, getCached* functions, registerAdapter, hasAdapter, getRegisteredAdapters, validateAdapterConfig, clearAdapterCache (also re-exports configureStorefront + the loader types so the @/lib/adapter barrel-init pattern works — but apps should import configureStorefront from the root entry) |
| @cobrastyle/storefront-core/actions | 'use server' | cart, checkout, customer, search, and wishlist server actions |
| @cobrastyle/storefront-core/cookies | server-only | getCartIdFromCookies, setCartIdCookie, clearCartCookie, getCustomerTokenFromCookies, setCustomerTokenCookie, clearCustomerTokenCookie, getCustomerRefreshTokenFromCookies, setCustomerRefreshTokenCookie |
| @cobrastyle/storefront-core/hooks | 'use client' | CartProvider, CustomerProvider, WishlistProvider, AnalyticsInit, useCart, useCustomer, useWishlist, useAnalytics, configureAnalytics, trackViewItem, trackViewItemList, trackAddToCart, trackRemoveFromCart, trackViewCart, trackBeginCheckout, trackAddShippingInfo, trackAddPaymentInfo, trackPurchase |
Required startup: configureStorefront
Before any call to getAdapter() (or any code that imports @cobrastyle/storefront-core/adapter), you must call configureStorefront once with the app's StorefrontConfig and the list of adapter loaders.
Create a dedicated init module in your app:
// src/lib/storefront-init.ts
import { configureStorefront } from '@cobrastyle/storefront-core';
import storefrontConfig from '@/storefront.config';
import { adapterLoaders } from '@/lib/adapter/adapters.config';
configureStorefront({ config: storefrontConfig, adapterLoaders });Wiring the init module
The init module is a side-effect import — it must run before any adapter access. There are two patterns:
Pattern 1 — adapter barrel (recommended for App Router apps)
Re-export the engine adapter subpath from a local barrel and import the init module at the top:
// src/lib/adapter/index.ts (your app's back-compat barrel)
import '@/lib/storefront-init'; // side-effect: runs configureStorefront
export * from '@cobrastyle/storefront-core/adapter';Every server component and server action that imports @/lib/adapter will trigger the init automatically.
Pattern 2 — instrumentation.ts (for non-route entry points)
For worker processes, cron jobs, or any entry point that does not go through the adapter barrel, add a Next.js instrumentation file:
// instrumentation.ts (project root, next to next.config.ts)
export async function register() {
await import('./src/lib/storefront-init');
}configureStorefront must be called before any getAdapter use. If the engine is called before it is configured, it will throw:
Error: Storefront not configured. Call configureStorefront({ config, adapterLoaders }) at startup (see @cobrastyle/storefront-core README / app lib/storefront-init.ts).Analytics wiring
Analytics is configured on the client side via the <AnalyticsInit config={...} /> component. Mount it once in your root layout:
// src/app/layout.tsx
import { AnalyticsInit } from '@cobrastyle/storefront-core/hooks';
import { analyticsConfig } from '@/lib/analytics.config'; // your app's env-reader
export default function RootLayout({ children }) {
return (
<html>
<body>
<AnalyticsInit config={analyticsConfig} />
{children}
</body>
</html>
);
}AnalyticsInit calls configureAnalytics(config) synchronously during render so the singleton is set before any user-triggered tracking fires. Tracking functions (trackAddToCart, trackPurchase, etc.) are no-ops until AnalyticsInit has mounted with a real config.
Your app's analytics.config.ts should read credentials from environment variables and return an AnalyticsConfig (the type is exported from the package root):
// src/lib/analytics.config.ts
import type { AnalyticsConfig } from '@cobrastyle/storefront-core';
export const analyticsConfig: AnalyticsConfig = {
gtm: {
enabled: Boolean(process.env.NEXT_PUBLIC_GTM_ID),
containerId: process.env.NEXT_PUBLIC_GTM_ID,
},
facebookPixel: {
enabled: Boolean(process.env.NEXT_PUBLIC_FB_PIXEL_ID),
pixelId: process.env.NEXT_PUBLIC_FB_PIXEL_ID,
},
debug: process.env.NODE_ENV !== 'production',
};Adapter loaders
The app controls which adapters are available by providing an AdapterLoaderConfig[] to configureStorefront. Each entry maps an adapter type name to a dynamic import:
// src/lib/adapter/adapters.config.ts
import type { AdapterLoaderConfig } from '@cobrastyle/storefront-core';
export const adapterLoaders: AdapterLoaderConfig[] = [
{
type: 'dummy-data',
loader: async () => {
const { dummyDataAdapter } = await import('@cobrastyle/adapter-dummy-data');
return dummyDataAdapter;
},
},
{
type: 'magento2',
loader: async () => {
const { magento2Adapter } = await import('@cobrastyle/adapter-magento2');
return magento2Adapter;
},
},
];The storefront.config.ts then routes features and methods to those registered types using the standard 4-layer config (defaultAdapter, features, methods, overrides).
What stays in the app
The engine package contains the reusable mechanics. The following app-specific glue stays in your storefront and is not part of this package:
| File | Reason |
|------|--------|
| storefront.config.ts | Customer-specific adapter routing |
| lib/adapter/adapters.config.ts | Loader list (imports specific adapter packages) |
| lib/cart-stores.ts | Adapter-specific cookie cart stores (Enad, Brink, etc.) |
| lib/analytics.config.ts | Reads credentials from environment variables |
| actions/locale.ts | Uses @/i18n — app-specific i18n wiring |
| All UI / pages / components | Customer-specific look and feel |
