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

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

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

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

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

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

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

Часті запитання

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1288
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    984
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    987
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    1001

Ми стикнулися з типовою задачею: інтеграція 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 прямо зараз — отримайте консультацію та оцінку проєкту. Зв'яжіться з нами через форму на сайті.