Public API surface
The curated map of @wocart/storefront 3.1.0. The
generated reference has every signature; this
page groups the surface by entry point and says what runs where.
Code
| Import | Runs in | Holds |
|---|---|---|
@wocart/storefront | Browser and server | Types, Zod schemas, money and image helpers, routes, languages, basket, OTP, geography, phone, coupon and Meta helpers |
@wocart/storefront/server | Server only | createStoreClient, the error type, preview and revalidation |
@wocart/storefront/astro | Server only | The request's store and language, same-origin routes, the proxy endpoint, the place-order engine, the form-action middleware |
@wocart/storefront/review-media | Browser only | Photo resizing and voice recording for a review form |
One boundary, enforced by review
The root entry builds no schema at import in the modules a browser uses, but it
does export schemas — importing ProductSchema in a page script ships Zod to
every shopper. Browser code imports helpers and types; validation stays on the
server, where data enters.
Money, images and presentation
| Export | What it does |
|---|---|
formatMoney(amount, { symbol, locale, decimals? }) | The amount in the locale's digits, the symbol after it; zero decimals by default |
mediaUrl(key, delivery) | A media key → its URL in the store's media, or null (no delivery, or not a key) |
mediaImageUrl(url, params, delivery) | The photo at a size, from the delivery's resizer (ImageKit or Cloudflare); null for a direct delivery or a URL it does not serve |
mediaImageSrcset(src, widths, { delivery, ratio?, quality? }) | A srcset by width; null when the photo cannot be resized |
pictureOf(image, delivery) | A merchant-picked image → { src, alt, width, height, position }, the focal point as object-position |
isMediaKey(value) | Whether a value is a media key (products/…, landing/…, reviews/…) |
productImageSource(product) | The product's representative image URL: its cover, else its first gallery image, else null |
getProductView(product), getProductListView(product) | Price, default variant, discount percentage, stock state, for a product or a listed product |
productMeta(product), SEO_TEXT_LIMITS | A product's title and description for search engines: what the merchant wrote, else its name and plain description |
productStructuredData(product, { url, storeName? }), jsonLd(value) | Its schema.org Product, and the text of a JSON-LD script that can never end the script |
canonicalUrl(origin, { pathname, locale, routing }, search?) | A page's canonical address: its path in its language and its listing page, nothing else |
getOfferTierView(offer, basePrice, comparePrice), getQuantityTierViews(pricing, unitPrice) | An offer's tile, and the quantity-price tiers, for display |
initialVariant(product), optionStates(product, selection), pickOption(product, selection, option, value), variantFor(variants, selection) | Variant selection as a state machine |
countdownTarget(mode, endsOn, endsAt), countdownEnd(ends, now?), timeLeft(end, now?) | An offer countdown's end (every midnight, or a day the merchant names), in Algiers time, the same on the server and in the browser |
whatsAppContact(config, page, words) | The store's WhatsApp on one page: the wa.me link with the page's message, every text resolved; null when the store has none |
MAX_RESOLVED_PREFILL_LENGTH, PREFILL_TOKENS | The message's 900-character cap and its tokens (product, url, order, store) |
META_CURRENCY, buildMetaViewContentPayload, buildMetaProductPayload, buildMetaAddToCartPayload, buildMetaInitiateCheckoutPayload, createMetaPixelTracker | Meta browser events with the platform's currency and content ids |
The store, its pages and its languages
| Export | What it does |
|---|---|
unavailableStoreConfig({ serverUrl, locale? }) | The config a page renders when the store cannot be read: empty id, nothing to buy, one language |
STOREFRONT_PAGE_PATHS | Every page type's path: home /, catalog /products, category /category/:slug, collection /collections/:handle, product /products/:handle, page /pages/:slug, landing /lp/:slug, checkout /checkout, thankYou /thank-you, trackOrder /track-order, search /search, contact /contact |
storefrontPath(type, params?) | Build one; throws when a required parameter is missing |
matchStorefrontPath(pathname) | Which page type a pathname is, with its decoded parameter, or null |
showsWidgetOn(surfaces, pathname) | Whether the floating WhatsApp launcher belongs on this path |
SINGLE_LANGUAGE_PAGE_TYPES, isSingleLanguagePage(pathname) | The page types that exist in the primary language only (["landing"]), and whether a path is one |
STOREFRONT_API_PATHS, storefrontApiPath(name, params?) | Where each of createStorefrontRoutes' routes is mounted (/api/communes/:wilayaId …), and one path with its parameter filled |
thankYouHref(order, language?), readThankYou(url) | The thank-you page's address for a placed order (?order=&total=&oid=), in the shopper's language, and its reading back |
servedLanguage(config, code?), localeRouting(config), resolveLocalePath(pathname, routing), localizeHref(href, locale, routing), alternateLinks(pathname, routing, origin) | Language-prefixed URLs: the primary language unprefixed, every other published language under its code |
Basket and checkout
| Export | What it does |
|---|---|
createBasketStore(options) | The browser basket: storage adapter, listeners, line caps |
createLocalStorageAdapter(), createMemoryStorageAdapter() | Persist in localStorage, or in memory for tests and private modes |
DEFAULT_BASKET_STORAGE_KEY, MAX_BASKET_LINES, MAX_BASKET_LINE_QUANTITY, basketLineKey(productId, variantId) | The storage key, the caps, and how two lines are told apart |
toOrderItems(lines) | Basket lines as the server's items[] |
addedLines(before, after) | What an add put in the basket — for AddToCart; empty when the basket had no room |
createOtpMachine(...), createOtpTransport(...), mapOtpResponse(...), otpTransportFailure(...) | Phone verification: states, transport, response mapping, a transport-level failure |
createAbandonedCheckoutTracker(ports) | Report an unfinished checkout, then its conversion |
createBrowserAbandonedCheckoutTracker({ endpoint }), convertAbandonedCheckout(...), ABANDONED_CHECKOUT_SESSION_KEY | The same tracker wired to a browser page, and the thank-you page's conversion |
bindCheckoutKey(form) | One checkout attempt, one order: the key a checkout form's submissions carry |
readShippingRates(value), readCouponOutcome(value) | Read a page's embedded rates or a quote's coupon outcome in the browser, without Zod |
createQuoter({ endpoint }), readCartQuote(value) | Ask the quote from the browser, keeping only the latest answer; read one without Zod |
couponRefusalTone(reason), COUPON_REFUSAL_REASONS, COUPON_HINT_REASONS | Whether a code's refusal is a hint about the basket or a refusal of the code |
isOrderNumber(value), ORDER_NUMBER_PATTERN | The shape of an order number (ORD-20261023-0042) |
REVIEW_REFUSAL_CODES, REVIEW_TEXT_LIMITS | Every refusal a review can meet, and its title and body lengths |
PRODUCT_SORTS, SHOPPER_ORDER_STAGES, SHOPPER_ORDER_JOURNEY, DEFAULT_COLLECTION_HANDLES | A listing's orders; an order's stages and the journey a progress bar shows; the collections every store starts with |
isWilayaId(value), WILAYAS, ALGERIA_COMMUNES, communesForWilaya(id), normalizeAlgerianPhone(phone), toLocalAlgerianMobile(phone) | Geography and phone helpers, no network: safe in a browser script |
couponFromUrl(url), couponRefusalOf(result), COUPON_URL_PARAM, COUPON_NOT_APPLICABLE | A coupon code carried in a URL object, and the refusal a write result carries |
STOREFRONT_OPERATIONS, STOREFRONT_RETRY_POLICIES | The operation names every error carries, and each one's retry policy |
The client, namespace by namespace
createStoreClient(scope) returns these; it is server-only and takes
{ serverUrl, apiKey, theme?, locale?, onError?, readTimeoutMs? }. Every read
is bounded by readTimeoutMs (10 seconds unless set).
| Namespace | Methods | A failed call returns |
|---|---|---|
config | get() | null |
products | get(handle), list(filters?), page(filters?), search(text, filters?) | null / [] / { items: [], hasNext: false, total: 0 } |
products.reviews | list(productId, pagination?), eligibility(input), upload(input), submit(input) | { rows: [], total: 0 } for the read; a ClientResult for the writes |
collections | get(handle) | null |
categories | list() | [] |
pages | get(slug), landing(slug, { preview? }) | null |
menus | get(handle) | null |
pageData | get(surface) | null |
shipping | rates(), rate(wilayaId) | {} / null |
geo | wilayas() (built-in data, never fails), communes(wilayaId) | [] |
cart | validate(items, options?), quote(lines, options?) | a ClientResult |
orders | create(input), tracking(orderId), status(proof), abandoned.upsert(input), abandoned.convert(input), otp.send(input), otp.verify(input) | a ClientResult (tracking: null) |
The read contract is the SDK's most important promise: a failed read degrades to
an empty value and reports through onError; it never throws. A write returns
ClientResult — { success: true, data } or { success: false, domainError } —
because a refusal is an expected answer, not an exception.
Schemas and types
The root entry exports the Zod schemas the client validates with, for a script or a route that needs the same shape:
- Catalog:
ProductSchema,ProductListSchema,ProductImageSchema,ProductVariantSchema,OfferSchema,QuantityPricingSchema,CategorySchema,StoreCollectionSchema,StoreMenuSchema,StoreMenuItemSchema. - Store:
StoreConfigSchema,StorefrontLanguageSchema,StorePagePublicSchema,StorePageLinkSchema,StoreContactSchema,CheckoutFormPolicySchema,CheckoutFormCustomFieldSchema,StoreWhatsAppWidgetSchema,LandingPageSchema,LandingPageImageSchema,PageDocumentPayloadSchema,MediaImageSchema,MediaDeliverySchema. - Commerce:
ShippingRatesSchema,WilayaRatesSchema,CommuneSchema,CartValidationSchema,CartValidationLineSchema,CartRewardSchema,CouponOutcomeSchema,CreatedOrderSchema,OrderTrackingSchema,ReviewSchema,ReviewMediaSchema,ReviewEligibilitySchema,ReviewUploadSchema,ReviewSubmitResultSchema,ReviewListEnvelopeSchema,OtpSendResultSchema,OtpVerifyResultSchema,IdResponseSchema,ProductPageEnvelopeSchema,ShopperOrderStatusSchema. - Input:
BasketSchema,BasketLineSchema,BasketLineInputSchema,AbandonedCheckoutInputSchema,AbandonedBasketLineSchema,ProductQuoteInputSchema,CartQuoteLinesSchema,DeliveryDestinationSchema,DeliverySelectionSchema,OtpProofSchema,OrderSchema,TrackingDecisionSchema,WilayaIdSchema.
The types a theme names most: StoreConfig, StorefrontLanguage, Product,
ProductList, ProductDetail, Category, StoreCollection, StoreMenu,
StorePagePublic, LandingPage, CartValidation, CartQuoteOptions,
CreatedOrder, OrderTracking, Review, ReviewEligibility, Wilaya,
Commune, DomainError, ClientResult, StoreScope, ProductPage,
ProductView, BasketStore, OtpMachine, MetaPixelTracker, MediaImage,
MediaDelivery, StoreContact, WhatsAppContact, WhatsAppPage,
WhatsAppWords.
@wocart/storefront/server
| Export | What it does |
|---|---|
createStoreClient(scope) | The one client factory; throws at construction on an empty serverUrl or apiKey |
StoreClient, ClientResult | Its type, and the write result type |
PreviewClaims, PreviewDraft, PreviewRequest, RevalidateClaims, RevalidateRequest | What the preview and revalidation readers answer |
StorefrontError, isStorefrontError(error) | The error type, and the narrow check |
readPreviewRequest(request, { publicKey, theme }), verifyPreviewToken(token, options), previewConfig(config, draft), previewResponseHeaders(claims) | An editor's preview request: verified claims, the draft's config, and the headers that keep it out of a cache |
REVALIDATE_PATH, readRevalidateRequest(request, options), PAGES_CACHE_TAG | The publish hook's path (/wocart-revalidate), its verified request, and the cache tag ("pages") every cached page carries |
catalogPaths(client, config), sitemapXml(paths, routing, origin) | Every page a sitemap lists, and the sitemap in every published language |
@wocart/storefront/astro
| Export | What it does |
|---|---|
createStorefrontMiddleware(options) | A theme's whole middleware: store and language, redirects, a 404 that keeps the language, the editor's preview, the form action |
revalidateEndpoint({ publicKey, theme }) | The /wocart-revalidate route, { POST, ALL }: drops every page under PAGES_CACHE_TAG for a verified token |
createStorefrontRoutes({ client }) | The same-origin routes: otpSend, otpVerify, cartValidate, abandonedUpsert, abandonedConvert, communes, reviewsList, reviewEligibility, reviewUpload, reviewSubmit, orderStatus |
REVIEWS_PAGE_DEFAULT, REVIEWS_PAGE_MAX | 20 and 50 — the reviews route's page bounds |
createProxyEndpoint(config) | A generic same-origin proxy for what the routes above do not cover |
placeOrderInput | The order form's input whitelist (a Zod object) |
executePlaceOrder(input, request, client) | The order engine: basket-or-product rule, attribution, the wire body |
collectForwardedHeaders(request) | The headers a route forwards to the server |
runFormAction(deps) | The form-action middleware step: runs a form-posted action so the page renders its result in place |
resolveStoreRequest(request, options), resolvePreviewStore(draft, options) | Which store and language a request renders, and the redirects; an editor's draft's store |
notFound(context, page?) | A missing resource: the 404 page, status 404, never cached |
lookupOrder(input, request, client), orderLookupInput | A shopper's order lookup for a track-order form, its outcome worded in a few cases |
PlaceOrderInput, PlaceOrderResult, OrderLookup, OrderLookupInput, ResolvedStore, StoreRequestOptions, StoreRequestResolution, NotFoundContext, ActionDescriptor, ActionMiddlewareDeps, ProxyEndpointConfig, ProxyClientFn, AstroAPIContext, AstroAPIRoute, StorefrontApiRoute, StorefrontRoutes, StorefrontRoutesOptions, PreviewLocals, StorefrontMiddleware, StorefrontMiddlewareContext, StorefrontMiddlewareOptions, StorefrontActionContext, RevalidateEndpointContext, RevalidateEndpointOptions | The types those take and return |
@wocart/storefront/review-media
| Export | What it does |
|---|---|
prepareReviewPhoto(photo, options?, deps?) | Shrink a photo to 1600 px at most and re-encode it (WebP, else JPEG); the re-encode drops EXIF |
createReviewSession({ routes, attempts? }, deps?) | The review form's whole conversation: find the order, send each file with progress and retries, submit |
photoTargetSize(width, height, maxEdge) | The size the photo is drawn at |
createVoiceRecorder(options, deps?), canRecordVoice(deps?) | Record a voice note at a low bitrate, stopping at the store's limit |
pickVoiceMimeType(isTypeSupported), VOICE_MIME_TYPES | The container/codec the browser supports, in preference order |
PhotoOptions, PhotoDeps, RecordedVoice, VoiceRecorderOptions, VoiceRecorder, VoiceDeps, ReviewSession, ReviewSessionOptions, ReviewSessionRoutes, ReviewSessionDeps, ReviewDraft, ReviewFindResult, ReviewRefusal, ReviewSubmission, ReviewUpload, ReviewUploadOptions, ReviewUploadRequest, ReviewUploadResult | The option, session and injection types |
Each takes its browser dependencies as an optional last argument, so it can run in a test with a stub canvas or recorder.
What is not public
dist/… and src/… deep paths may move in any release. The client's internal
core, its caches and its transport are not part of the contract; if the public
surface is missing something a storefront needs, that is an SDK change, not a
deep import.
Version
This guide follows @wocart/storefront 3.1.0 with zod 4.x (a peer), which
reads platform v7. Pin exact versions and read the package's CHANGELOG.md
before upgrading; see Testing a storefront.