Pro vývojáře / Headless

Váš vlastní obchod. Náš commerce. Jakýkoli framework.

Jeden typovaný klient k API a dvě sady komponent — Vue a React — nesou celý obchod: katalog, košík, pokladnu, dárkové karty, trhy, recenze, vyhledávání i účet zákazníka. Website builder je jeden ze způsobů, jak je použít, ne ten jediný.

Klient1

@storefront/client — jediné dveře k API, ve všech sadách i aplikacích, které dodáváme.

Sady2

storefront-vue a storefront-react, držené v paritě neúspěšným buildem.

Komponenty29

Dnes exportované z kořene obou sad — seznam níže se kontroluje proti barrelům.

Builder je volitelný

Vše na této stránce běží bez publikovaného webu z builderu. Hostovaný web i export kódu jsou postavené ze stejných sad a stejného klienta jako headless aplikace — sekce builderu jsou tenké adaptéry nad komponentami sady, takže funkce, která vyjde pro builder, vyjde i pro vás, se stejnými testovacími id a stejnými voláními API.

To není slib: stejné end-to-end scénáře — dárkové karty, trhy, pravidla pokladny, recenze, vyhledávání — běží proti publikovanému webu z builderu i proti obyčejné Nuxt aplikaci na Vue sadě, při každém commitu.

Instalace

Vue / Nuxt

npm install @storefront/client storefront-vue pinia

React / Next

npm install @storefront/client storefront-react zustand

Sady mají minimum závislostí: Vue potřebuje Pinia, React jednu knihovnu pro stav — zustand hned, Redux Toolkit přes storefront-react/rtk. JavaScript Stripe se načítá jen tam, kde je pokladna.

Klient

CustomerClient mluví zákaznickou polovinou API: veřejná čtení, košík, pokladna, objednávky, recenze a dárkové karty. Každá cesta, kterou sady volají, jde přes něj, takže rozhraní, které tu vidíte, je to, které používají.

import { CustomerClient } from '@storefront/client';

const client = new CustomerClient({ baseUrl: 'https://api.your-platform.example' });

// The store's public data (settings, categories, markets) and its live catalogue.
const store = await client.store.getPublicData(STORE_ID);
const products = await client.store.getAvailableProducts(STORE_ID, { market: 'eu' });

// Everything else a shopper does goes through the same client:
// client.cart.*, client.checkout.*, client.orders.*, client.reviews.*, client.giftCards.*

Anonymní zákazníky identifikuje cookie, kterou API nastaví při prvním kontaktu; přihlášení povýší stejný košík. Nic tady nepotřebuje API klíč — to je administrátorská polovina, popsaná pod API.

Vue a Nuxt

Jeden objekt pluginu naplní Pinia úložiště před prvním vykreslením — nastavení obchodu, relaci zákazníka, aktivní košík, trh, na který požadavek ukazuje — a každá komponenta sady z nich čte, pokud jí nepředáte props.

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@pinia/nuxt'],
  runtimeConfig: {
    // Server-side reads (SSR) — private, may point at an internal address.
    storefrontPlugin: { baseUrl: 'http://127.0.0.1:9147' },
    public: {
      storefrontPlugin: {
        baseUrl: 'https://api.your-platform.example',
        storeOptions: { storeId: 42, autoGetActiveCart: true },
      },
    },
  },
});

// plugins/storefront.ts — fetches the store, restores the shopper's session and cart,
// resolves ?market= / the wb_market cookie, and fills the Pinia stores before first paint.
import { nuxtClientPluginObject } from 'storefront-vue';
export default defineNuxtPlugin(nuxtClientPluginObject);

Stránka je pak skládání: katalog, souhrn, který tiskne čísla, jež API naúčtuje, a pokladna, která dokončí objednávku. Takhle běží v produkci apps/noop.shop, náš referenční obchod.

<script setup lang="ts">
import { ProductList, BasicShopProduct, Checkout, CheckoutOrderSummary, useCartStore, useClient } from 'storefront-vue';
const cart = useCartStore();
const client = useClient();
// The store is the page's state; the client is the one door to the API.
const onAdd = async (line) => { cart.addProduct(line); await client.cart.update(cart.cartDTO!); };
const onPlaced = (order) => navigateTo(`/order/${order.id}`);
</script>

<template>
  <ProductList>
    <template #product="attrs">
      <BasicShopProduct v-bind="attrs" @add="onAdd" />
    </template>
  </ProductList>

  <CheckoutOrderSummary />
  <Checkout :provider="{ name: 'stripe' }" currency="usd" @payment-success="onPlaced" />
</template>

React a Next

Dva providery — klient a úložiště — a jedno volání, které úložiště naplní. Komponenty jsou tytéž, se stejnými props a stejnými testovacími id, takže scénář napsaný proti Vue sadě se čte stejně i proti této.

import { CustomerClient } from '@storefront/client';
import { createZustandStores } from 'storefront-react/zustand';
import {
  StorefrontClientProvider, StorefrontStoreProvider, initializeStores,
  ProductList, CheckoutOrderSummary, Checkout,
} from 'storefront-react';

const client = new CustomerClient({ baseUrl: 'https://api.your-platform.example' });
const stores = createZustandStores();
await initializeStores({ client, stores, storeOptions: { storeId: 42, autoGetActiveCart: true } });

export function Shop() {
  return (
    <StorefrontClientProvider client={client}>
      <StorefrontStoreProvider stores={stores}>
        <ProductList columns={3} />
        <CheckoutOrderSummary />
        <Checkout provider={{ name: 'stripe' }} currency="usd" onPaymentSuccess={(order) => location.assign(`/order/${order.id}`)} />
      </StorefrontStoreProvider>
    </StorefrontClientProvider>
  );
}

Úložiště jsou rozhraní: zustand je výchozí adaptér, Redux Toolkit se dodává vedle něj a oba lze nahradit vlastním implementací StorefrontStores.

Návrhové tokeny

Obchod vykresluje podle vlastních vlastností CSS: pozadí stránky, text, písma, formulářová pole a sloupec obsahu. Publikovaný web z editoru vypisuje svůj motiv pod těmito názvy a čte je ve svém základním stylu; stejné názvy čtou i sady komponent, takže jejich nastavením na :root nastylujete obojí.

  • --wb-color-* — background, surface, text, muted, border, primary, on-primary, field, field-border, error, success
  • --wb-font-* — body, heading, mono, size, line-height
  • --wb-spacing-* — container, medium, narrow, gutter
  • --wb-radius-* — sm, md, lg, full

Každý název má výchozí hodnotu a každá komponenta si jako záložní hodnotu ponechává tu, kterou měla vždy — obchod, který nenastaví žádný, se zobrazí přesně jako dnes.

Publikovaný web z editoru navíc servíruje tato písma z vlastní domény, každé s metricky odpovídajícím záložním řezem, takže text po načtení nikdy nezmění velikost: Outfit, Manrope, Space Grotesk

Co obě sady exportují

Seskupeno podle práce, kterou obchod musí zvládnout. Každé jméno zde je exportované z kořene obou sad — stránka je postavená ze stejného seznamu, který test kontroluje proti balíčkům.

Katalog

Výpis, karta produktu s výběrem variant, detail, obrázky a peníze.

  • ProductList
  • BasicShopProduct
  • ProductDetail
  • ImageViewer
  • MoneyDisplay

Košík

Stránka košíku, jeho položky, rozbalovací panel a zásuvka v hlavičce, předplatné na položce.

  • CartViewer
  • CartItem
  • CartDropdown
  • CartDrawer
  • QuickCartView
  • CartSubscribeButton

Pokladna

Pokladna nezávislá na poskytovateli, souhrn s pravidly, daní a dárkovými kartami, hlavička kroků a cesta bez platby, když objednávku pokryjí dárkové karty.

  • Checkout
  • CheckoutOrderSummary
  • CheckoutSteps
  • OrderSummary
  • GiftCardInput
  • GiftCardCoveredOrder

Commerce

Trhy, recenze, vyhledávání, dárkové karty zákazníka, pravidla uplatněná na objednávce a průběh i stav dopravy.

  • MarketSwitcher
  • ProductReviews
  • SearchBox
  • SearchResults
  • MyGiftCards
  • OrderRulesApplied
  • ShippingProgress
  • ShippingUpdate

Zapojení

Upozornění na naskladnění, kontaktní formulář, potvrzovací dialogy.

  • RestockNotify
  • ContactForm
  • ConfirmationDialogue

Rozšíření

Bezpečně vykreslí UI napsané rozšířením uvnitř vašich vlastních stránek.

  • ExtensionUIRenderer

Co za vás platforma dělá pod povrchem

  • Pokladna: dnes Stripe za rozhraním poskytovatele, s daní odhadnutou API pro adresu, kterou zákazník napíše, a celkovou částkou, která je slovy, ne číslem, dokud se nerovná tomu, co bude naúčtováno.
  • Pravidla pokladny: vlastní kód obchodníka pro slevy, dopravu a ověření — TypeScript zadaný přes administrátorské API (POST /store/:storeId/checkout-rules) nebo administraci, zkompilovaný platformou a spouštěný na API při odhadu i při objednávce, s builderem webu i bez něj. Váš souhrn ukáže slova pravidla, vaše stránka objednávky vytiskne, co bylo uplatněno. Ověřovací pravidlo lze uložit s failClosed: true, aby zablokovalo pokladnu, když ho nelze spustit — výpadek pak odmítne to, co má pravidlo odmítat (odhad i 400 pokladny nesou u každé chyby kód CHECKOUT_RULE_UNAVAILABLE), místo aby se prodalo; každé jiné pravidlo nemá při výpadku žádný účinek.
  • Dárkové karty: kontrola zůstatku, částečná úhrada, plně pokrytá objednávka bez formuláře karty a karty zákazníka na stránce účtu.
  • Trhy: trh se určí z ?market= nebo cookie a nese se každým veřejným čtením, takže ceny, měna a zaokrouhlení sledují zákazníka.
  • Recenze: odeslání hostem, moderace na straně obchodníka a souhrnné hodnocení ve vašem JSON-LD produktu.
  • Vyhledávání: vlastní engine obchodu za GET /store/:storeId/search — odstranění diakritiky, tolerance překlepů, skupiny synonym obchodníka a produkty, kolekce, stránky i články seřazené společně, s odkazy na VAŠE cesty. Chcete našeptávač bez požadavku na každý stisk klávesy? GET /store/:storeId/search/index vrátí celý korpus s verzí odvozenou z obsahu a `createSearchCache` v @storefront/client drží manifest v localStorage a dokumenty v IndexedDB — druhé načtení stránky se pak nezeptá vůbec. Korpusová route je pro katalogy, které se VEJDOU — dokument má zhruba 310 bajtů plus 400 znaků textu, takže pár tisíc produktů jsou jeden až dva megabajty a API odmítne poslat víc než 8 MB; nad tuto hranici zůstane `createSearchCache` sám od sebe u dotazovací route. Způsob shody volíte pro každý obchod — tolerantní (předpony a překlepy), předpona, podřetězec nebo přesná — a API, uložený korpus i obě sady komponent uplatní totéž pravidlo. Cache degraduje viditelně: úložiště, které vyhodí chybu (kvóta, anonymní okno, zavřená databáze), je pro danou stránku odepsáno a pojmenováno v `status().degraded`, neúspěšné stažení korpusu se 30 s neopakuje a odpovídá dotazovací route, zastaralý korpus odpoví hned a obnoví se na pozadí, a požadavek předběhnutý dalším stiskem klávesy se zruší, ne jen ignoruje.
  • Navigace: nabídky a přesměrování URL obchodníka jsou veřejně čitelné (GET /store/:storeId/menus, GET /store/:storeId/redirects), takže headless web vykreslí navigaci, kterou obchodník spravuje, a respektuje stejná přesměrování jako web z builderu.
  • Účet: objednávky, předplatná, dárkové karty a adresy přes stejného klienta, s přihlášením přes vlastní zákaznickou autentizaci obchodu.

Za hranicemi webových sad

Stejné zákaznické rozhraní se dodává jako nativní klienti pro herní enginy a mobil — jeden balíček na jazyk, každý psaný ručně proti API a udržovaný v souladu bránou v buildu nad servírovaným OpenAPI rozhraním.

  • C++
  • Go
  • .NET
  • Java
  • Python
  • Swift
  • Godot

Každá cesta s publikem, kterému slouží, je v referenci API ; co se děje po objednávce, je pod Webhooky .