profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Навчальні матеріали

Build & Ship an Airport DirectoryDeploymentsBuild & Ship a Stripe Storefront

Feature

Documentation Site TemplateКонструктор шаблонів функціоналаПерекладач можливостейOrganizations & Website HeirarchyConnect Profound CMS to your AI clientSettings IntegrationsSettings API KeysSettings UsageSettings Websites
All Systems Operational
Powered Byprofound-logo
Theme

Build & Ship a Stripe Storefront

Практичний посібник: створіть контентно-орієнтований Stripe-магазин у Profound CMS — каталог, що мерчант редагує без коду, два параметричні маршрути, безголовий кошик і оформлення Stripe на хостингу.

Готовий магазин у дії — перегляньте категорію, відкрийте товар, додайте до кошика, оформіть оплату.

Практичний посібник, що створює контентно-орієнтований магазин у Profound CMS: каталог товарів (категорії + позиції), змодельований у CMS, сторінки списку й деталей з одного набору маршрутів та оформлення Stripe на хостингу, яке постачається як безголовий компонент.

Основу складають написаний вручну Next.js і адмінка Profound. Claude Code (через Profound MCP) бере на себе основну роботу у трьох завданнях — наповнення каталогу, під’єднання системи дизайну та написання компонентів вітрини (включно з безголовим кошиком). Три частини: Налаштування, Створення, Продакшн.

Платежі в один рядок. Ми використовуємо Stripe-hosted Checkout: покупець платить на сторінці Stripe, а не вашій. Ваш застосунок робить лише дві серверні дії — створює Checkout Session і перевіряє один webhook. Жодних полів картки, Stripe Elements чи тягаря PCI.

Що ви створите

  • Невеличкий опублікований каталог у CMS — три категорії та вісім товарів (демо "Edison's Inventions") — кожен можна редагувати без коду.
  • Два параметричні маршрути (/products/{item_code}, /categories/{category_code}) плюс статичний /cart, усі з одного набору компонентів.
  • Безголовий кошик (useCart) і оформлення Stripe на хостингу, з ціною, що завжди визначається на сервері за Stripe Price ID.
  • Магазин, розгорнутий на Vercel із живим прев’ю та редагуванням безпосередньо на сторінці для команди.

Передумови

  • Bun ≥ 1.3 — curl -fsSL https://bun.sh/install | bash
  • Claude Code з Profound MCP (у частині 1 встановлюється).
  • Обліковий запис Profound CMS.
  • Обліковий запис Stripe. Цей посібник працює в тестовому режимі, тож під час розробки не списує реальні кошти — але потік ідентичний із бойовими ключами, тож можете використовувати ключі реального облікового запису, якщо хочете. (Тестовий режим не потребує даних про бізнес чи банк.)
  • Stripe CLI (stripe login) для локальних webhook’ів.
  • Для деплою: GitHub CLI (gh) і обліковий запис Vercel, під’єднаний до GitHub.

Як все поєднується

Profound розділяє контент і рендеринг:

  • Компоненти визначають структуру контенту. Кастомний компонент із полем Route Slug маршрутизується (category, item); компонент із тегом UI Element можна розмістити на сторінці (nav, product_grid, …).
  • Документи — це сам контент (товар, категорія).
  • UI-елементи — секції сторінки; кожне скалярне поле приймає статичне значення або CEL-вираз, що обчислюється під час рендеру.
  • Параметричні маршрути зіставляють URL із документом + UI-елементами, передаючи параметри маршруту (meta.params.* у CEL, routeParams у React).
  • Ваш застосунок Next.js читає їх через cms-renderer; Stripe додається як звичайні API-маршрути.

Єдине правило, що формує збірку: CEL прив’язує лише поля string/number. Тож скалярна «оболонка» (бренд у навігації, футер, заголовки) прив’язується через CEL, тоді як все багатше або колекції (сітка товарів, галерея зображень, rich text) отримуються всередині React-компонента за параметром маршруту. І Stripe — джерело істини для ціноутворення — поле price у CMS лише для відображення; списання завжди визначається на сервері за Stripe Price ID.

Частина 1 — Налаштування

Результат: невеликий опублікований каталог, застосунок, під’єднаний для його читання, Stripe встановлено, дизайн на місці — але ще нічого не рендериться.

1. Зареєструйтесь та створіть сайт

Зареєструйтеся в Profound (аутентифікація WorkOS). Створіть сайт із назвою store, потім скопіюйте його ID сайту (UUID в URL адмінки) та API-ключ рівня читання (Deployments → Create API key). Застосунок лише читає; сидування каталогу пізніше відбуватиметься через MCP, який автентифікується окремо.

2. Створіть каркас застосунку, під’єднайте його та додайте Stripe

bunx create-profound-next store
cd store
bun add stripe

Каркас — це проєкт Next.js App Router із попереднім підключенням до Profound (SDK cms-renderer, маршрут із перехопленням усіх запитів, скрипт generate-schemas, компонент <Refresher>). Стилів немає. bun add stripe додає серверний SDK — єдину залежність, яку потребує hosted checkout.

Додайте свої значення до .env.local:

# CMS
PROFOUND_API_KEY=<ваш ключ читання>
NEXT_PUBLIC_PROFOUND_WEBSITE_ID=<id вашого сайту>
NEXT_PUBLIC_CMS_API_URL=https://cms.dev.tryprofound.com
NEXT_PUBLIC_BUNNY_CDN_URL=https://cms-profound.b-cdn.net   # подає зображення, що лежать у CMS

# Stripe
STRIPE_SECRET_KEY=sk_test_...            # тестовий ключ; замініть на бойовий для production
STRIPE_WEBHOOK_SECRET=whsec_...          # заповните на кроці 4 у частині Створення
NEXT_PUBLIC_SITE_URL=http://localhost:3000

Отримайте STRIPE_SECRET_KEY у Stripe → Developers → API keys. Ми використовуємо тестовий ключ (sk_test_…), щоб під час збірки гроші не рухались; коли будете готові приймати справжні платежі, перейдіть на бойовий ключ. Запустіть bun dev і відкрийте localhost:3000 — стартовий проект рендериться.

Hosted checkout перенаправляє браузер на URL Stripe, тож серверного секретного ключа достатньо — жодного публічного ключа чи клієнтського SDK Stripe не потрібно.

3. Визначте компоненти category, product_image та item

Створіть три Custom Components (Components → Create new component) — джерела даних, тож без тегу UI Element. Увімкніть Active для кожного.

У CMS немає поля «масив зображень», тож галерея — це масив посилань на невеликий компонент product_image. Створіть category та product_image (і активуйте їх) перед item — поле Reference може посилатися лише на активні компоненти.

  • category — name (Text), code (Text, Route Slug), description (Rich text), heroImage (Image)
  • product_image — image (Image)
  • item — name (Text), code (Text, Route Slug), description (Rich text), images (масив посилань → product_image), price (Number, у центах — лише для відображення), currency (Select, usd), stripePriceId (Text), category (Reference → category), active (Boolean)

Залиште всі поля необов’язковими. Адмінка перетворює назви полів на snake_case ("Stripe Price Id" → stripe_price_id) — за цими назвами працюватиме ваш код, тож прочитайте реальні назви через generate-schemas. Ми називаємо маршрутний ідентифікатор code (а не slug): це Route Slug і ключ для чистого пошуку documents.getByCode пізніше.

Компонент item — code як Route Slug, images як посилання на product_image, плюс stripePriceId і референс category.

4. Завантажте компоненти у локальні типи

bun run generate-schemas

Записує Zod-схеми та типи у generated/cms-schemas.ts (categorySchema/Category, itemSchema/Item). Також перевіряє підключення — неправильні облікові дані спричинять помилку.

5. Заповніть каталог через Profound MCP

Встановіть та автентифікуйте MCP один раз:

claude mcp add --transport http Profound http://107.21.107.99:8081/mcp

Запустіть mcp__Profound__authenticate, пройдіть WorkOS, потім запитайте Claude:

Згенеруй невеликий e-commerce-каталог для магазину Edison's Inventions — три категорії та такі товари з коротким достовірним описом епохи (description), price у центах, currency: "usd" і active: true:

  • Lighting & Power (code: lighting): Incandescent Lightbulb (incandescent-lightbulb, $24), Electric Dynamo (electric-dynamo, $890), Electric Pen (electric-pen, $49)
  • Sound Recording (code: sound): Tinfoil Phonograph (tinfoil-phonograph, $249), Carbon Microphone (carbon-microphone, $59), Dictaphone (dictaphone, $179)
  • Motion Pictures (code: motion): Kinetoscope (kinetoscope, $399), Kinetograph Camera (kinetograph, $549)

Кожна категорія має мати name і відповідний code; кожен товар — name, відповідний code, description, price (у центах), currency і active. Збережи у data/catalog.json і провалідй за нашими компонентами category та item. Потім за допомогою Profound MCP створи кожен документ у статусі published: спочатку створюй категорії, збережи їхні IDs, потім створи товари з полем category, що вказує на посилання — { "_type": "reference", "_ref": "<category-id>", "_schema": "category" }. Залиш stripePriceId порожнім. Товари можна створювати паралельно.

Claude створює data/catalog.json, валідуючи його, і паралельно викликає create_document (status: "published"). Спершу сидируйте категорії, щоб посилання в товарах вказували на вже наявні ID.

Три посіяні категорії, опубліковані та Live.

Вісім посіяних товарів, кожен прив’язаний до категорії.

6. Створіть Stripe Prices і під’єднайте кілька товарів

Каталог уже в CMS; тепер додайте реальну ціну Stripe для кількох товарів — робота мерчанта в двох адмінках, без коду:

  1. Stripe Dashboard → Products → + Add product, задайте одноразову ціну, скопіюйте Price ID (price_…).
  2. Повторіть для приблизно трьох основних позицій (наприклад, Lightbulb, Phonograph, Kinetoscope).
  3. Адмінка Profound → item → Documents → вставте кожен Price ID у stripePriceId, збережіть.

CMS зберігає каталог; Stripe — ціну; зв’язок — один рядок, який мерчант вставляє. (Хочете автоматизувати? Офіційний Stripe MCP може створити Products/Prices за вас — вставляєте отримані IDs так само.)

7. Додайте дизайн-систему та під’єднайте її за допомогою ШІ

Каркас без стилів. Додайте DESIGN.md (блок @theme Tailwind v4 + токени) у корінь проєкту — власний або завантажений із refero.design. Після цього зверніться до Claude, обмеживши запит лише стилями:

Прочитай дизайн-файл, який я щойно додав. Налаштуй Tailwind за потреби, потім під’єднай тему та шрифти, щоб стилі працювали. Використовуй next/font для шрифтів — не завантажуй їх із Google під час виконання. Лише стилі — не створюй сторінки чи компоненти.

Переконайтеся, що у src/app/globals.css є @import "tailwindcss"; + блок @theme, і що localhost:3000 показує токени. Тримайте запит вузьким (інакше агент може згенерувати цілу головну сторінку) і завжди завантажуйте шрифти через next/font, не через runtime-запити.

8. Додайте зображення товарів (необов’язково)

Необов’язково — без зображень теж можна дійти до робочого checkout’у. Щоб їх додати: створіть по одному документу product_image на кожне зображення (завантажте файл у поле image), потім додайте ці посилання до масиву images у товарі. Можете використати власні фото або згенерувати однорідний набір за допомогою моделі зображень (попросіть Claude вивести промпти під бренд із DESIGN.md і зафіксуйте один --sref у Midjourney для узгодженості).

Окремий cms-renderer не має хелпера для URL зображень, тож додайте buildAssetUrl у src/lib/image.ts (~40 рядків) — він додає префікс NEXT_PUBLIC_BUNNY_CDN_URL і розширення. Компоненти у кроці 3 частини «Створення» його використовують.

Частина 2 — Створення

Створіть шар рендерингу та checkout, завершіть реальною купівлею в тестовому режимі.

1. Визначте п’ять компонентів UI element

П’ять компонентів, кожен Active і з тегом UI Element (Settings → Tags), без Route Slug:

  • nav → brand
  • product_grid → heading
  • product_detail → heading
  • cart_summary → heading
  • footer → text

Усі поля — Text. Тег UI Element показує компонент у списку Add UI Element Page Builder — Active недостатньо. Кожне поле — скаляр (тип, який може прив’язати CEL); фактичні дані каталогу не є полем тут — ProductGrid/ProductDetail отримують їх за параметром маршруту (крок 3).

2. Перегенеруйте типи

bun run generate-schemas

3. Згенеруйте читач каталогу, компоненти та безголовий кошик

Один запит створює хелпер для читання, п’ять компонентів, кошик і реєстр:

Створи нашу вітрину в src/, використовуючи SDK Profound cms-renderer.

src/lib/catalog.ts — серверний читач CMS. Створи клієнт за допомогою getCmsClient({ cmsUrl: process.env.NEXT_PUBLIC_CMS_API_URL!, apiKey: process.env.PROFOUND_API_KEY, websiteId: process.env.NEXT_PUBLIC_PROFOUND_WEBSITE_ID! }) із cms-renderer/lib/cms-api. Експортуй getItemByCode(code) → cms.documents.getByCode.query({ websiteId, schemaName: "item", code }), повертаючи res.document.published_content. Експортуй listItems(categoryCode?) → cms.documents.list.query({ websiteId, schemaName: "item", status: "published", limit: 100 }), перетворюй res.documents на .published_content, відфільтровуй active !== false, а якщо задано categoryCode, залишай товари, у яких category._ref дорівнює document.id цієї категорії. Експортуй resolveImages(refs), який дістає кожне посилання item.images через cms.documents.get.query({ websiteId, id: ref._ref }) і перетворює поле зображення на URL, використовуючи доданий buildAssetUrl (частина 1, крок 8).

src/components/ — п’ять компонентів UI, зареєстрованих у реєстрі catch-all маршруту за іменем компонента, snake_case як в адмінці: { nav, product_grid, product_detail, cart_summary, footer }. Nav і Footer читають свої скалярні поля з пропса content (BlockComponentProps<T> із cms-renderer/lib/types). ProductGrid і ProductDetail — асинхронні серверні компоненти, які читають routeParams і витягують дані з catalog.ts: routeParams.<param> має вигляд { value, … } — беріть .value, тож ProductGrid викликає listItems(routeParams.category_code?.value) (картки ведуть на /products/{code}), а ProductDetail — getItemByCode(routeParams.item_code?.value) (галерея через resolveImages, rich text опис, ціна, кнопка «Додати в кошик»). CartSummary показує кошик із useCart і кнопкою Pay. Тримайте formatPrice у чистому src/lib/format.ts, щоб клієнтські компоненти не імпортували серверний catalog.ts.

src/components/AddToCartButton.tsx — кнопка "use client", що приймає { code, name, priceLabel } і викликає useCart().addItem({ code, name, priceLabel, quantity: 1 }). Використовуйте її в ProductDetail.

src/lib/useCart.ts — безголовий кошик: рядки { code, name, priceLabel, quantity } у стані, збережені в localStorage, із методами addItem/removeItem/updateQty/subtotal та checkout(), який надсилає POST { lines: [{ code, quantity }] } (лише коди й кількості — жодних цін) на /api/stripe/checkout, потім перенаправляє на повернений url.

Стилізуй усе нашою дизайн-системою, власними компонентами — не копіюй макет оригінального сайту.

Три речі, які варто пам’ятати після генерації:

  • Скалярна оболонка приходить у content ({ content }: BlockComponentProps<T>) — якщо розпаковувати поля як верхньорівневі пропси, блок нічого не відобразить. Дані каталогу надходять із routeParams + запиту в catalog.ts, бо CEL не прив’язує списки чи галереї. Кошик несе коди товарів, ніколи ціни.
  • routeParams.<param> — це { value, schemaName, document } — використовуйте .value. Читання повертають published_content, а не .content. Ключі реєстру — snake_case, як в адмінці.
  • Поновіть @types/react/@types/react-dom до v19 — каркас постачається з v18, що ламає асинхронні серверні компоненти на React 19.

4. Напишіть серверний код Stripe (хребет)

Три короткі серверні файли — єдиний платіжний код у застосунку. Вони перевикористовують getItemByCode, тож списання визначається на сервері.

src/lib/stripe.ts:

import Stripe from "stripe";
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

src/app/api/stripe/checkout/route.ts — отримує кожен товар із CMS, списує Stripe-ціну:

import { NextResponse } from "next/server";
import { stripe } from "@/lib/stripe";
import { getItemByCode } from "@/lib/catalog"; // серверне читання, ключ лише на читання

export async function POST(req: Request) {
  const { lines } = await req.json();                // [{ code, quantity }] — без цін від клієнта
  const line_items = await Promise.all(
    lines.map(async ({ code, quantity }: { code: string; quantity: number }) => {
      const item = await getItemByCode(code);          // сервер визначає за CMS
      return { price: item!.stripe_price_id, quantity }; // ціна з CMS, ніколи з клієнта
    })
  );
  const session = await stripe.checkout.sessions.create({
    mode: "payment",
    line_items,
    success_url: `${process.env.NEXT_PUBLIC_SITE_URL}/cart?status=success`,
    cancel_url: `${process.env.NEXT_PUBLIC_SITE_URL}/cart?status=cancelled`,
  });
  return NextResponse.json({ url: session.url });     // клієнт редиректиться сюди
}

src/app/api/stripe/webhook/route.ts — надійний сигнал виконання замовлення:

import { stripe } from "@/lib/stripe";

export async function POST(req: Request) {
  const body = await req.text();                      // СИРИЙ body — потрібен для перевірки підпису
  const sig = req.headers.get("stripe-signature")!;
  let event;
  try {
    event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch {
    return new Response("Bad signature", { status: 400 });
  }
  if (event.type === "checkout.session.completed") {
    // виконати: записати замовлення / надіслати квитанцію.
  }
  return new Response(null, { status: 200 });
}

Потрібне виправлення каркасу: файл src/proxy.ts переспрямовує кожен /api/* до CMS, тож ваші Stripe-маршрути не працюватимуть. Спершу пропустіть їх локально:

import { createCmsProxy } from "cms-renderer/lib/proxy";
import { NextResponse, type NextRequest } from "next/server";
import { cmsConfig } from "@/lib/cms-config";

const cmsProxy = createCmsProxy({ upstream: cmsConfig.cmsUrl });
const LOCAL_API_PREFIXES = ["/api/stripe"];

export const proxy = async (request: NextRequest) => {
  if (LOCAL_API_PREFIXES.some((p) => request.nextUrl.pathname.startsWith(p))) {
    return NextResponse.next();                       // обробити локально
  }
  return cmsProxy(request as unknown as Parameters<typeof cmsProxy>[0]);
};
// залиште незмінним `export const config = { matcher: [...] }` з каркасу

Перевірка: curl -X POST localhost:3000/api/stripe/webhook -d x повертає Bad signature.

Запустіть Stripe CLI для локальних webhook’ів:

stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhook
# скопіюйте whsec_... у STRIPE_WEBHOOK_SECRET, перезапустіть bun dev

whsec_… діє лише в межах сесії. Два правила забезпечують безпеку: checkout заново визначає ціну за CMS по code (підроблений кошик не може змінити її), а webhook перевіряє підпис на сирому тілі.

5. Створіть маршрути

Admin → Pages → Create page, тричі. Зіставте кожен параметр із компонентом (поле slug code):

  1. /products/{item_code} → item
  2. /categories/{category_code} → category
  3. /cart — статична сторінка (введіть буквально /cart, не /{cart})

6. Додайте UI-елементи, підключіть CEL, опублікуйте

Для кожного маршруту: Page Builder → Add UI Element → Custom → додайте компоненти в потрібному порядку, заповніть скалярні поля (статичне значення або CEL), Publish.

  • /products/{item_code}: nav, product_detail, footer
  • /categories/{category_code}: nav, product_grid, footer
  • /cart: nav, cart_summary, footer

Задайте nav.brand і footer.text як статичні рядки; заголовки — як статичні підписи.

Page Builder на маршруті категорії — вибрано product_grid, його заголовок прив’язано через CEL.

Page Builder на товарному маршруті — product_detail з прив’язкою до конкретного товару.

Особливість Page Builder для параметричних маршрутів: на двох параметричних маршрутах додані UI-елементи не зберігаються (блоки «осиротіють», і сторінка рендериться порожньою). Поки це не виправлено, прив’язуйте block_ids для цих сторінок безпосередньо через Profound MCP update_page, потім публікуйте. (Статичний /cart приєднується як слід.) Із тієї ж причини ProductGrid отримує заголовок із категорії, яку він завантажує, а не через CEL.

7. Відрендерте та здійсніть покупку

  • /categories/lighting → сітка. Натисність на товар → сторінка деталей + «Додати в кошик». /cart → Pay.
  • Оплата перенаправляє на Stripe-hosted checkout. Використайте тестову картку 4242 4242 4242 4242, будь-який майбутній термін/CSV. Ви повертаєтеся на /cart?status=success, а в stripe listen з’являється checkout.session.completed.

Рендер сторінки товару — галерея, ціна та кнопка «Додати в кошик».

Кошик — позиції та єдина кнопка «Pay with Stripe».

Лише товари з цінами можна купити — придбайте один із ~3, яким ви додали Stripe Price на кроці 6.

Необов’язково — інтернаціоналізуйте. Перекладіть кожен компонент (усі 35 мов за раз), додайте сегмент /{language}/…, зіставлений із вбудованим системним компонентом language, і переключіть поля, прив’язані CEL, на documents.translated. Див. частину 2, крок 7, у посібнику з довідника аеропорту.

Частина 3 — Продакшн

1. Випустіть: GitHub, потім Vercel

git init && git add -A && git commit -m "Stripe storefront"
gh repo create store --private --source=. --push   # можете використати --public

Команда збірки: generated/cms-schemas.ts у .gitignore, тож зафіксуйте збірку для регенерації — додайте vercel.json:

{ "$schema": "https://openapi.vercel.sh/vercel.json", "buildCommand": "bun run generate-schemas && next build" }

У Vercel: Add New → Project, імпортуйте store та додайте змінні середовища — PROFOUND_API_KEY, NEXT_PUBLIC_PROFOUND_WEBSITE_ID, NEXT_PUBLIC_CMS_API_URL, NEXT_PUBLIC_BUNNY_CDN_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (значення для розгорнутого середовища, див. нижче) і NEXT_PUBLIC_SITE_URL (ваш продакшн URL). Деплойте.

Далі під’єднайте webhook на продакшні (локальний stripe listen мав свій секрет): Stripe → Developers → Webhooks → + Add endpoint → https://<prod>/api/stripe/webhook, подія checkout.session.completed. Скопіюйте отриманий whsec_… у Vercel і перезапустіть деплой.

Відсутні змінні середовища = «працює локально, порожньо в проді» — головна пастка деплою. У цьому посібнику використовуємо тестові ключі; коли будете готові приймати реальні платежі, замініть STRIPE_SECRET_KEY і секрет webhook на live значення.

2. Live preview та редагування на місці

Обидві можливості входять до каркасу.

  • Live preview: <Refresher> оновлює сторінку, яку переглядає редактор, щойно він зберігає зміни в адмінці — без деплою. (Це прев’ю для редактора; відвідувачі бачать опублікований контент із нормальною ревалідацією.)
  • Редагування на місці: додайте ?edit_mode=true до будь-якого URL для появи оверлеїв редагування. Публічні відвідувачі бачать чисту сторінку.

Додайте маршрут прев’ю, якого бракує в каркасі. Адмінка завантажує фрейм попереднього перегляду за адресою /cms-preview_<path>; без цього маршруту кожне прев’ю повертає 404. Додайте:

// src/app/cms-preview_/[...slug]/page.tsx
import { ParametricRoutePreviewPage } from "cms-renderer/lib/renderer";
import { registry } from "../../registry";   // винесіть реєстр у спільний модуль
export default async function Page({ params, searchParams }) {
  const { slug } = await params;
  const PreviewPage = ParametricRoutePreviewPage as any; // async RSC; типи React 19
  return <PreviewPage registry={registry} apiKey={process.env.PROFOUND_API_KEY ?? ""}
    websiteId={process.env.NEXT_PUBLIC_PROFOUND_WEBSITE_ID ?? ""}
    cmsUrl={process.env.NEXT_PUBLIC_CMS_API_URL ?? "https://cms.dev.tryprofound.com"}
    params={Promise.resolve({ slug })} searchParams={searchParams} />;
}

Додайте також src/app/cms-preview_/page.tsx (аналогічно, slug: []) для кореневого сегмента.

Ось і вся збірка

Контентно-орієнтований Stripe-магазин: каталог у CMS, сторінки списку й деталей з одного набору маршрутів і робочий hosted checkout. ШІ посіяв каталог, під’єднав дизайн і написав читач каталогу + компоненти + безголовий кошик; ви створили компоненти, пов’язали ціни Stripe, налаштували три маршрути, CEL-хром і три невеличкі файли Stripe. CEL прив’язує оболонку; компоненти отримують каталог. І Stripe залишився мінімальним — один виклик sessions.create і один підписаний webhook, із покупцем, який платить на сторінці самого Stripe.

Continue Reading
Previous‹Deployments