Skip to content
Twilight React Playground
ثيم رائدaren

store

objectBeginnerserverbrowserlive demo

Loads the store, its theme, languages and currencies in one call: the same call the root loader makes before every page.

import { store, StoreContext } from '@salla.sa/twilight-theme-engine/api/store';

In plain words

Before any page can render, the engine needs to know which store it is drawing: its name and logo, the merchant's theme colors, the languages it sells in. store.settings() fetches all of that in one request.

You rarely call it yourself. The engine calls it for every page and shares the result through useStore, useTheme and useTwilight. Reach for this module when you need a part those hooks do not expose, such as the list of currencies.

Signature

store.settings(storeIdentifier?: string): Promise<StoreContext | null>
store.queries.settings(storeIdentifier?: string)
  // key ['store', 'settings', storeIdentifier, locale, scope, requestedVersionId]

interface StoreContext {
  store?: Store;
  theme?: Theme;
  languages?: Language[];     // an array here; the API sends an object
  currencies?: Record<string, { code: string; name: string; symbol: string; amount: number; country_code: string }>;
  external_services?: Record<string, unknown>;
  headers?: Record<string, unknown>;
  login?: { url: string; turnstile_site_key: string };
  affiliate?: { utm_url: string; cta_enabled: boolean };
  policy_url?: string;
  debug?: boolean;            // declared, never filled
  trace_console?: boolean;    // declared, never filled
}

Try it live

The store settings the root loader fetched for this very page, read back from the query cache.Try this: notice "fetched in this browser" stays false: the data came with the HTML. Then open languages and theme.
Storefront canvas · ar · RTL
queryKey
["store","settings",null,"ar",null,null]
fetchStatus
idle
fetched in this browser
false
settings.store: {…} 24 keys
id: 1510890315
ray: 50
logo: "https://cdn.salla.network/salla.com/logo-wide-1.svg"
icon: "https://cdn.salla.network/salla.com/logo-wide-1.svg"
name: "ثيم رائد"
username: "dev-vgckq3fssfhjewwi"
store_country: "SA"
country: "SA"
url: "https://demostore.salla.sa/ar/dev-vgckq3fssfhjewwi/"
settings: {…} 26 keys
meta: {…} 3 keys
scope: null
template: null
contacts: {…} 4 keys
social: {…} 4 keys
description: "<p class="ql-direction-rtl">هذا المتجر التجريبي يتيح لك استكشاف شكل وتصميم المتاجر على منصة <strong>سلة</strong>. تصفّح الأقسام، جرّب تجربة الشراء، واستعرض الم…"
apps: {…} 2 keys
features: Array(18)
is_merchant: false
support_pickup: true
order_instruction: {…} 4 keys
shipping: {…} 3 keys
rating: {…} 2 keys
ratings: Array(2)
Controls
What a theme writes
import { useQuery } from '@tanstack/react-query';
import { store } from '@salla.sa/twilight-theme-engine/api/store';

export function SettingsPanel() {
  // Already cached: the root loader fetched these settings before the page rendered.
  const { data } = useQuery(store.queries.settings());
  const value = data?.store;

  return <pre dir="ltr">{JSON.stringify(value, null, 2)}</pre>;
}

Example

app/components/CurrencyList.tsx
import { useQuery } from '@tanstack/react-query';
import { store } from '@salla.sa/twilight-theme-engine/api/store';

export function CurrencyList() {
  // Already cached: the root loader fetched these settings for this request.
  const { data } = useQuery(store.queries.settings());
  const currencies = Object.values(data?.currencies ?? {});

  return (
    <ul className="currency-list">
      {currencies.map((currency) => (
        <li key={currency.code}>
          {currency.name} ({currency.symbol})
        </li>
      ))}
    </ul>
  );
}

How it behaves

  • Endpoint: GET store/settings with include[]= store, settings, theme, theme_settings, external_services, currencies, languages, payments, product_widgets, rating and ratings, plus scope=<id> when a branch is selected. Its timeout is 5 s, shorter than the client default of 8 s.

  • The identifier it resolved is sent explicitly in the store-identifier header, so the store it checked is the store that answers.

  • It never throws. With no identifier it logs a warning and returns null; any HTTP or network error is logged and also returns null. The root loader turns null into the "Store Unavailable" page (SettingsError).

  • languages arrives as an object keyed by code ({ AR: {…}, EN: {…} }) and becomes an array; each entry also gets iso_code, which the Salla SDK's language switcher reads.

  • rootBeforeLoad runs ensureQueryData(store.queries.settings()) on every navigation, so a component reading the same options answers from the cache. The version in the key is the version the request asked for, not the one the settings report, so the server and browser keys match.

Gotchas

  • store.queries.settings('1510890315') and store.queries.settings() are two cache entries even when they name the same store: the argument is part of the key. Call it with no argument to reuse what the root loader fetched.

  • debug and trace_console are declared on StoreContext but never copied from the response, so they are always undefined.

  • docs/07-data-types.md imports StoreContext from @salla.sa/twilight-theme-engine, which does not export it. Import the type from @salla.sa/twilight-theme-engine/api/store.

  • docs/11-internationalization.md shows storeQueries.settings(locale) and storeQueries.keys.all. Neither exists: the export is store, settings takes an optional store identifier, and there is no keys factory.

Related

Source and docs