Skip to main content

Vue Themes

You can build a Shoppex theme with Vue. The platform contract stays the same:
  • bun install
  • bun run build
  • build output in dist/index.html

Minimal Scripts

Your package.json must have scripts like:
  • dev
  • build
Example (conceptual):
{
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  }
}

Minimal SDK Wiring (Framework-Agnostic)

This is the important part: initialize the SDK, then fetch storefront data.
// @validate
import shoppex from '@shoppex/sdk';

shoppex.init('my-shop', { apiBaseUrl: 'https://api.shoppex.io' });

const res = await shoppex.getStorefront();
if (res.success && res.data) {
  console.log(res.data.shop.name);
}
Then in Vue you render the shop, products, and groups in your components.

Initial Data Injection (Optional)

If you want Shoppex to inject window.__SHOPPEX_INITIAL__, add the placeholder:
<!--initial-data-->
This works regardless of framework.

useStore() Composable (Composition API)

A reusable composable for loading storefront data:
// composables/useStore.ts
// In a real Vue app:
// import { ref, onMounted } from 'vue'

type Ref<T> = { value: T };
declare function ref<T>(value: T): Ref<T>;
declare function onMounted(fn: () => void | Promise<void>): void;

// assumes shoppex is available (via SDK import in your app entry)
declare const shoppex: any

export function useStore() {
  const store = ref(null)
  const products = ref([])
  const isLoading = ref(true)
  const error = ref(null)

  onMounted(async () => {
    const res = await shoppex.getStorefront()
    if (res.success && res.data) {
      store.value = res.data.shop
      products.value = res.data.products
    } else {
      error.value = res.message
    }
    isLoading.value = false
  })

  return { store, products, isLoading, error }
}

Cart Reactivity

Use the shoppex:cart-changed custom event to keep cart state in sync across components:
// composables/useCart.ts
// In a real Vue app:
// import { ref, onMounted, onUnmounted } from 'vue'

type Ref<T> = { value: T };
declare function ref<T>(value: T): Ref<T>;
declare function onMounted(fn: () => void | Promise<void>): void;
declare function onUnmounted(fn: () => void): void;

// assumes shoppex is available (via SDK import in your app entry)
declare const shoppex: any

export function useCart() {
  const items = ref(shoppex.getCart())
  const itemCount = ref(shoppex.getCartItemCount())

  function refresh() {
    items.value = shoppex.getCart()
    itemCount.value = shoppex.getCartItemCount()
  }

  onMounted(() => {
    window.addEventListener('shoppex:cart-changed', refresh)
    window.addEventListener('storage', refresh)
  })
  onUnmounted(() => {
    window.removeEventListener('shoppex:cart-changed', refresh)
    window.removeEventListener('storage', refresh)
  })

  return { items, itemCount }
}

// After modifying cart:
function addItem(productId: string, variantId: string) {
  shoppex.addToCart(productId, variantId)
  window.dispatchEvent(new CustomEvent('shoppex:cart-changed'))
}