Інтеграція Vendure GraphQL API з фронтендом

Інтеграція фронтенду з Vendure GraphQL API часто впирається в налаштування аутентифікації, кошика та SSR — і без готових рішень це перетворюється на довгі пошуки. Ми розробляємо headless-рішення на React і Next.js, налаштовуючи Shop API під ваш проєкт. Наша команда реалізує інтеграцію під ключ — від конфігурації до підтримки, забезпечуючи надійну роботу та масштабування разом із бізнесом.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Інтеграція Vendure GraphQL API з фронтендом
Середній
~5 днів
Часті запитання

Ми стикнулися з типовою задачею: інтеграція headless e-commerce на React з бекендом Vendure. Найчастіші проблеми — налаштування аутентифікації, робота з кошиком через GraphQL та SSR з Next.js. У цій статті — готове рішення з кодом, конфігами та поясненнями. Наш досвід — понад 5 років роботи з Vendure та 50+ успішних інтеграцій. Гарантуємо стабільність і продуктивність. Зв'яжіться з нами для оцінки вашого проєкту — отримайте консультацію та комерційну пропозицію.

Vendure надає два окремі GraphQL endpoint: Shop API (/shop-api) для покупців та Admin API (/admin-api) для адміністраторів. Фронтенд використовує лише Shop API. Аутентифікація — через cookie-based сесії або Bearer token, вибір робиться на рівні конфігу сервера. У цій статті ми покажемо, як підключити Vendure до кастомного фронтенду на React/Next.js, налаштувати генерацію типів, роботу з кошиком та checkout. Також розберемо типові помилки та патерни їх обробки. Наприкінці — що входить в інтеграцію під ключ.

API Призначення Ендпоінт Аутентифікація
Shop API Покупецькі запити /shop-api Cookie/Bearer
Admin API Адмінка /admin-api Bearer token

Як працює аутентифікація в Shop API?

Аутентифікація в Shop API реалізована через сесії на основі токенів. При cookie-аутентифікації токен сесії створюється при вході та зберігається на сервері, клієнт отримує куку. Цей метод оптимальний для SSR — Next.js де-факто стандарт. Bearer token підходить для SPA, але вимагає зберігання токена в localStorage та уважного управління часом життя. У наших проєктах за 50+ інтеграцій ми виробили чіткі рекомендації: для магазинів з високою часткою SEO трафіку — cookie, для внутрішніх панелей — Bearer.

Налаштування клієнта Vendure

Для підключення до Shop API використовуємо urql. Він легший за Apollo та краще підходить для роботи з cookie-сесіями. Нижче — приклад клієнта для SSR (з cookie) та для SPA (з Bearer token).

// lib/vendureClient.ts
import { createClient, fetchExchange, dedupExchange, cacheExchange } from "urql";

// Для SSR з cookie
export const shopClient = createClient({
  url: `${process.env.NEXT_PUBLIC_VENDURE_API_URL}/shop-api`,
  exchanges: [dedupExchange, cacheExchange, fetchExchange],
  fetchOptions: {
    credentials: "include",
    headers: {
      "vendure-token": process.env.NEXT_PUBLIC_CHANNEL_TOKEN!,
    },
  },
});

// Для SPA з Bearer token
export const spaClient = createClient({
  url: `${process.env.NEXT_PUBLIC_VENDURE_API_URL}/shop-api`,
  exchanges: [dedupExchange, cacheExchange, fetchExchange],
  fetchOptions: () => ({
    headers: {
      authorization: localStorage.getItem("authToken")
        ? `Bearer ${localStorage.getItem("authToken")}`
        : "",
    },
  }),
});
Метод Зберігання токена Підходить для
Cookie Сесія на сервері SSR (Next.js, Nuxt)
Bearer localStorage SPA без SSR

Генерація типів TypeScript

Для типізації GraphQL-запитів використовуємо GraphQL Code Generator. Налаштування описане в codegen.yml:

---
# codegen.yml schema: - ${VENDURE_API_URL}/shop-api: headers: vendure-token: ${CHANNEL_TOKEN} documents: "src/**/*.graphql" generates: src/generated/shop-types.ts: plugins: - typescript - typescript-operations - typescript-urql config: withHooks: true scalars: DateTime: "string" JSON: "Record<string, unknown>" Money: "number" 
---

Запуск генерації: VENDURE_API_URL=http://localhost:3000 CHANNEL_TOKEN=my-token npx graphql-codegen. Отримані типи автоматично інтегруються з urql через хуки.

Запити до Shop API

Усі основні операції — отримання товарів, кошика, аутентифікація — виконуються через Shop API. Нижче наведено ключові GraphQL-запити та мутації.

# Каталог: список товарів
query GetProductList($options: ProductListOptions) {
  products(options: $options) {
    totalItems
    items {
      id
      name
      slug
      featuredAsset {
        preview
      }
      variants {
        id
        name
        priceWithTax
        currencyCode
        stockLevel
      }
    }
  }
}

# Каталог: детальна картка
query GetProduct($slug: String!) {
  product(slug: $slug) {
    id
    name
    slug
    description
    featuredAsset {
      preview
      source
    }
    assets {
      preview
      source
    }
    variants {
      id
      name
      sku
      priceWithTax
      currencyCode
      stockLevel
      options {
        code
        name
        group {
          code
          name
        }
      }
    }
    facetValues {
      code
      name
      facet {
        code
        name
      }
    }
  }
}

# Кошик: додавання товару
mutation AddItemToOrder($variantId: ID!, $quantity: Int!) {
  addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
    ... on Order {
      id
      code
      state
      totalWithTax
      currencyCode
      lines {
        id
        quantity
        linePriceWithTax
        productVariant {
          id
          name
          sku
          featuredAsset {
            preview
          }
        }
      }
    }
    ... on OrderModificationError {
      errorCode
      message
    }
    ... on OrderLimitError {
      errorCode
      message
      maxItems
    }
    ... on NegativeQuantityError {
      errorCode
      message
    }
    ... on InsufficientStockError {
      errorCode
      message
      quantityAvailable
    }
  }
}

# Кошик: отримання активного замовлення
query GetActiveOrder {
  activeOrder {
    id
    code
    state
    totalWithTax
    subTotalWithTax
    shippingWithTax
    lines {
      id
      quantity
      linePriceWithTax
      productVariant {
        id
        name
      }
    }
    shippingLines {
      shippingMethod {
        name
        description
      }
      priceWithTax
    }
    discounts {
      description
      amountWithTax
    }
  }
}

# Аутентифікація
mutation Login($email: String!, $password: String!, $rememberMe: Boolean) {
  login(username: $email, password: $password, rememberMe: $rememberMe) {
    ... on CurrentUser {
      id
      identifier
    }
    ... on InvalidCredentialsError {
      errorCode
      message
    }
    ... on NotVerifiedError {
      errorCode
      message
    }
  }
}

Реалізація checkout

Процес оформлення замовлення включає встановлення адреси доставки, вибір методу доставки, перехід до оплати та виконання платежу. Приклад хука:

// hooks/useCheckout.ts
import { useMutation } from "urql";
import {
  SetShippingAddressDocument,
  SetShippingMethodDocument,
  AddPaymentToOrderDocument,
  TransitionOrderToStateDocument,
} from "@/generated/shop-types";

export function useCheckout() {
  const [, setAddress] = useMutation(SetShippingAddressDocument);
  const [, setShipping] = useMutation(SetShippingMethodDocument);
  const [, addPayment] = useMutation(AddPaymentToOrderDocument);
  const [, transition] = useMutation(TransitionOrderToStateDocument);

  async function completeCheckout(params: CheckoutParams) {
    const addr = await setAddress({ input: params.address });
    if (addr.data?.setOrderShippingAddress.__typename !== "Order")
      throw new Error(addr.data?.setOrderShippingAddress.message);

    await setShipping({ id: [params.shippingMethodId] });
    await transition({ state: "ArrangingPayment" });

    const payment = await addPayment({
      input: {
        method: "yookassa",
        metadata: {
          returnUrl: `${window.location.origin}/checkout/confirm`,
        },
      },
    });

    if (payment.data?.addPaymentToOrder.__typename === "Order")
      return payment.data.addPaymentToOrder;

    throw new Error(payment.data?.addPaymentToOrder.message);
  }

  return { completeCheckout };
}

// Обробка помилок Vendure
function assertIsOrder(result: AddItemToOrderResult): asserts result is Order {
  if (result.__typename !== "Order")
    throw new VendureError(result.errorCode, result.message);
}

Vendure використовує union types для помилок — кожна мутація повертає Result | ErrorType1 | ErrorType2. Патерн assertIsOrder спрощує роботу з TypeScript.

SSR з Next.js App Router

Для серверного рендерингу необхідний окремий клієнт, який передає токен сесії через заголовок cookie, а не через credentials: "include".

// app/shop/page.tsx
import { createServerClient } from "@/lib/vendureServerClient";

export default async function ShopPage() {
  const client = createServerClient(); // клієнт з credentials для SSR
  const result = await client.query(GetProductListDocument, { options: { take: 24 } }).toPromise();
  return <ProductGrid initialData={result.data} />;
}

Це дозволяє уникнути проблем з гідратацією та покращити SEO.

Чому варто обрати headless Vendure?

Headless-підхід з Vendure дає гнучкість у виборі фронтенд-технологій та масштабуванні. Ви отримуєте ізольований бекенд з GraphQL API, готовий до інтеграції з будь-якими сервісами — CMS, PIM, пошуком. У наших проєктах це скоротило time-to-market та дозволило обробляти високі навантаження на стандартному VPS. Стек: Node.js + PostgreSQL + Redis — забезпечує 99.9% uptime.

Що входить в інтеграцію під ключ?

  • Налаштування Vendure (розгортання, конфігурація API, налаштування каналів)
  • Розробка кастомного фронтенду на React/Next.js
  • Інтеграція Shop API (каталог, кошик, checkout, аутентифікація)
  • Генерація TypeScript-типів та підключення urql
  • SSR з Next.js App Router
  • Обробка помилок та unit-тести
  • Документація по API та коду
  • Передача доступів та навчання команди
  • Підтримка протягом 1 місяця після запуску

Терміни: від 14 робочих днів залежно від складності. Вартість інтеграції визначається після аналізу.

Наш досвід та гарантії

Ми спеціалізуємося на headless e-commerce з використанням Vendure більше 5 років. Реалізували понад 50 проєктів — від інтернет-магазинів до складних маркетплейсів. Гарантуємо стабільну роботу API, продуктивність та дотримання термінів. Замовте інтеграцію Vendure прямо зараз — отримайте консультацію та оцінку проєкту. Зв'яжіться з нами через форму на сайті.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060