profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialΠ‘Π»ΠΎΠ³Philosophy
DocsTutorialΠ‘Π»ΠΎΠ³Philosophy

Tutorials

Π‘ΠΏΡ€Π°Π²ΠΎΡ‡Π½ΠΈΠΊ аэропортовDeploymentsBuild & Ship a Stripe Storefront

ВозмоТности CMS

Documentation Site TemplateFeature Template BuilderTranslation ServiceOrganizations & 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 Checkout, Ρ€Π°Π·ΠΌΠ΅Ρ‰Ρ‘Π½Π½Ρ‹ΠΉ Π½Π° Stripe: ΠΏΠΎΠΊΡƒΠΏΠ°Ρ‚Π΅Π»ΡŒ ΠΏΠ»Π°Ρ‚ΠΈΡ‚ Π½Π° страницС Stripe, Π° Π½Π΅ Π½Π° вашСй. Π’Π°ΡˆΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ выполняСт всСго Π΄Π²Π΅ сСрвСрныС Π·Π°Π΄Π°Ρ‡ΠΈ β€” создаёт сСанс Checkout ΠΈ провСряСт ΠΎΠ΄ΠΈΠ½ Π²Π΅Π±Ρ…ΡƒΠΊ. Никаких ΠΊΠ°Ρ€Ρ‚ΠΎΡ‡Π½Ρ‹Ρ… ΠΏΠΎΠ»Π΅ΠΉ, Π½ΠΈΠΊΠ°ΠΊΠΈΡ… Stripe Elements, Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ PCI.

Π§Ρ‚ΠΎ Π²Ρ‹ построитС

  • НСбольшой ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ Π² CMS β€” Ρ‚Ρ€ΠΈ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ ΠΈ восСмь Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ² (Π΄Π΅ΠΌΠΎ Β«Π˜Π·ΠΎΠ±Ρ€Π΅Ρ‚Π΅Π½ΠΈΡ Эдисона») β€” ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΡ€Π³ΠΎΠ²Ρ†Ρƒ Π±Π΅Π· ΠΊΠΎΠ΄Π°.
  • Π”Π²Π° парамСтричСских ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° (/products/{item_code}, /categories/{category_code}) плюс статичСский /cart, всС ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡ€Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ².
  • Π‘Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΡƒΡŽ ΠΊΠΎΡ€Π·ΠΈΠ½Ρƒ (useCart) ΠΈ Stripe Checkout, Ρ€Π°Π·ΠΌΠ΅Ρ‰Ρ‘Π½Π½Ρ‹ΠΉ Π½Π° Stripe, ΠΏΡ€ΠΈ этом Ρ†Π΅Π½Π° всСгда вычисляСтся Π½Π° сСрвСрС ΠΏΠΎ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρƒ Stripe Price.
  • Магазин, Ρ€Π°Π·Π²Π΅Ρ€Π½ΡƒΡ‚Ρ‹ΠΉ Π½Π° Vercel, с ΠΆΠΈΠ²Ρ‹ΠΌ прСдпросмотром ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π½Π° мСстС для ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹.

ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ трСбования

  • Bun β‰₯ 1.3 β€” curl -fsSL https://bun.sh/install | bash
  • Claude Code с Profound MCP (устанавливаСтся Π² части 1).
  • Аккаунт Profound CMS.
  • Учётная запись Stripe. Π’ ΡƒΡ‡Π΅Π±Π½ΠΈΠΊΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ тСстовый Ρ€Π΅ΠΆΠΈΠΌ, поэтому ΠΏΡ€ΠΈ сборкС Π½Π΅ ΡΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ дСньги β€” Π½ΠΎ ΠΏΠΎΡ‚ΠΎΠΊ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π΅Π½ с Π±ΠΎΠ΅Π²Ρ‹ΠΌΠΈ ΠΊΠ»ΡŽΡ‡Π°ΠΌΠΈ, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΈ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Π°. (Π’ тСстовом Ρ€Π΅ΠΆΠΈΠΌΠ΅ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹ свСдСния ΠΎ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈΠ»ΠΈ Π±Π°Π½ΠΊΠ΅.)
  • Stripe CLI (stripe login) для Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ².
  • Для дСплоя: 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.

Π§Π°ΡΡ‚ΡŒ 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 (cms-renderer SDK, ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚-ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‡ΠΈΠΊ, скрипт generate-schemas, <Refresher>). Бтилизация Π½Π΅ поставляСтся. bun add stripe подтягиваСт сСрвСрный SDK β€” Π΅Π΄ΠΈΠ½ΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ‚ΡŒ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡƒΡŽ для хостингового оформлСния Π·Π°ΠΊΠ°Π·Π°.

Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ваши значСния Π² .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_...            # здСсь тСстовый ΠΊΠ»ΡŽΡ‡; Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° Π±ΠΎΠ΅Π²ΠΎΠΉ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ΠΉΠ΄Π΅Ρ‚Π΅ Π² ΠΏΡ€ΠΎΠ΄
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 β€” стартовый ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ рСндСрится.

Π₯остинговоС ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π° пСрСнаправляСт Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ Π½Π° URL Stripe, поэтому сСрвСрного сСкрСтного ΠΊΠ»ΡŽΡ‡Π° достаточно β€” Π½ΠΈ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°, Π½ΠΈ клиСнтского SDK Stripe Π½Π΅ трСбуСтся.

3. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ category, product_image ΠΈ item

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ‚Ρ€ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° (Components β†’ Create new component) β€” это источник Π΄Π°Π½Π½Ρ‹Ρ…, поэтому Π±Π΅Π· Ρ‚Π΅Π³Π° UI Element. Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ (Active).

Π’ CMS Π½Π΅Ρ‚ поля «массив ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉΒ», поэтому галСрСя β€” это массив ссылок Π½Π° ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ product_image. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ category ΠΈ product_image (ΠΈ ΠΏΠΎΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΠΈΠΌ Active) Π΄ΠΎ item β€” ΠΏΠΎΠ»Π΅-ссылка ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹.

  • 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 (array of references β†’ 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:

Π‘Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠΉ нСбольшой ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ для ΠΌΠ°Π³Π°Π·ΠΈΠ½Π° Β«Π˜Π·ΠΎΠ±Ρ€Π΅Ρ‚Π΅Π½ΠΈΡ Эдисона» β€” Ρ‚Ρ€ΠΈ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Ρ‚ΠΎΠ²Π°Ρ€Ρ‹ с ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΌ описаниСм, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ эпохС, price Π² Ρ†Π΅Π½Ρ‚Π°Ρ…, currency: "usd" ΠΈ active: true:

  • ΠžΡΠ²Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΈ энСргия (code: lighting): Incandescent Lightbulb (incandescent-lightbulb, $24), Electric Dynamo (electric-dynamo, $890), Electric Pen (electric-pen, $49)
  • Π—Π²ΡƒΠΊΠΎΠ·Π°ΠΏΠΈΡΡŒ (code: sound): Tinfoil Phonograph (tinfoil-phonograph, $249), Carbon Microphone (carbon-microphone, $59), Dictaphone (dictaphone, $179)
  • ΠšΠΈΠ½Π΅ΠΌΠ°Ρ‚ΠΎΠ³Ρ€Π°Ρ„ (code: motion): Kinetoscope (kinetoscope, $399), Kinetograph Camera (kinetograph, $549)

КаТдой ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ Π½ΡƒΠΆΠ½Ρ‹ name ΠΈ этот ΠΊΠΎΠ΄ Π² Π½ΠΈΠΆΠ½Π΅ΠΌ рСгистрС; ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ Ρ‚ΠΎΠ²Π°Ρ€Ρƒ Π½ΡƒΠΆΠ½Ρ‹ name, Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΊΠΎΠ΄ Π² Π½ΠΈΠΆΠ½Π΅ΠΌ рСгистрС, description, price (Π² Ρ†Π΅Π½Ρ‚Π°Ρ…), currency ΠΈ active. Π‘ΠΎΡ…Ρ€Π°Π½ΠΈ Π² data/catalog.json ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒ Π½Π° соотвСтствиС нашим ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌ category ΠΈ item. Π—Π°Ρ‚Π΅ΠΌ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Profound MCP создай ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ ΠΊΠ°ΠΊ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹ΠΉ: сначала ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ, запиши ΠΈΡ… ID, Π·Π°Ρ‚Π΅ΠΌ создавай Ρ‚ΠΎΠ²Π°Ρ€Ρ‹ со ссылкой category Π²ΠΈΠ΄Π° { "_type": "reference", "_ref": "<category-id>", "_schema": "category" }. Π’ΠΎΠ²Π°Ρ€Ρ‹ создай ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ.

Claude создаёт data/catalog.json, Π²Π°Π»ΠΈΠ΄ΠΈΡ€ΡƒΠ΅Ρ‚ Π΅Π³ΠΎ ΠΈ отправляСт ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Π΅ Π²Ρ‹Π·ΠΎΠ²Ρ‹ create_document (status: "published"). НаполняйтС сначала ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ, ΠΏΠΎΡ‚ΠΎΠΌ Ρ‚ΠΎΠ²Π°Ρ€Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ссылки ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π»ΠΈ Π½Π° ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ID.

Π’Ρ€ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹Π΅ ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ, ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Ρ‹ ΠΈ Live.

Π’ΠΎΡΠ΅ΠΌΡŒ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ², ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ связан с ΠΊΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠ΅ΠΉ.

6. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ†Π΅Π½Ρ‹ Π² Stripe ΠΈ привяТитС нСсколько Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ²

ΠšΠ°Ρ‚Π°Π»ΠΎΠ³ находится Π² CMS; Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π΄Π°ΠΉΡ‚Π΅ нСскольким Ρ‚ΠΎΠ²Π°Ρ€Π°ΠΌ Ρ€Π΅Π°Π»ΡŒΠ½ΡƒΡŽ Ρ†Π΅Π½Ρƒ Π² Stripe β€” Π·Π°Π΄Π°Ρ‡Π° для Ρ‚ΠΎΡ€Π³ΠΎΠ²Ρ†Π°, выполняСтся Π² Π΄Π²ΡƒΡ… Π°Π΄ΠΌΠΈΠ½ΠΊΠ°Ρ…, Π±Π΅Π· ΠΊΠΎΠ΄Π°:

  1. Stripe Dashboard β†’ Products β†’ + Add product, Π·Π°Π΄Π°ΠΉΡ‚Π΅ Π΅Π΄ΠΈΠ½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ†Π΅Π½Ρƒ, скопируйтС Price ID (price_...).
  2. Π‘Π΄Π΅Π»Π°ΠΉΡ‚Π΅ это для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Ρ€Ρ‘Ρ… ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ² (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π»Π°ΠΌΠΏΠ°, Ρ„ΠΎΠ½ΠΎΠ³Ρ€Π°Ρ„, кинСтоскоп).
  3. Админка Profound β†’ item β†’ Documents β†’ Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Price Π² stripePriceId, сохранитС.

CMS Ρ…Ρ€Π°Π½ΠΈΡ‚ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³; Stripe β€” источник истины для Ρ†Π΅Π½Ρ‹; связь β€” ΠΎΠ΄Π½Π° строка, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Ρ‚ΠΎΡ€Π³ΠΎΠ²Π΅Ρ† вставляСт. (Π₯ΠΎΡ‚ΠΈΡ‚Π΅ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ? ΠžΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ Stripe MCP ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Products/Prices Π·Π° вас β€” Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ ID Ρ‚Π΅ΠΌ ΠΆΠ΅ способом.)

7. ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ Π΄ΠΈΠ·Π°ΠΉΠ½-систСму ΠΈ настройтС Π΅Ρ‘ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ИИ

ΠšΠ°Ρ€ΠΊΠ°Ρ поставляСтся Π±Π΅Π· стилСй. ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ DESIGN.md (Π±Π»ΠΎΠΊ @theme Tailwind v4 + Ρ‚ΠΎΠΊΠ΅Π½Ρ‹) Π² ΠΊΠΎΡ€Π΅Π½ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° β€” свой собствСнный ΠΈΠ»ΠΈ скачанный с refero.design. Π—Π°Ρ‚Π΅ΠΌ Π΄Π°ΠΉΡ‚Π΅ Claude запрос Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΎ стили:

ΠŸΡ€ΠΎΡ‡ΠΈΡ‚Π°ΠΉ Π΄ΠΈΠ·Π°ΠΉΠ½-Ρ„Π°ΠΉΠ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ я Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠ». Настрой Tailwind ΠΏΡ€ΠΈ нСобходимости, Π·Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈ Ρ‚Π΅ΠΌΡƒ ΠΈ ΡˆΡ€ΠΈΡ„Ρ‚Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ стили Π·Π°Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ next/font для ΡˆΡ€ΠΈΡ„Ρ‚ΠΎΠ² β€” Π½Π΅ Π·Π°Π³Ρ€ΡƒΠΆΠ°ΠΉ ΠΈΡ… ΠΈΠ· Google Π²ΠΎ врСмя выполнСния. Волько стили β€” Π½Π΅ создавай страницы ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹.

Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ Π² src/app/globals.css Π΅ΡΡ‚ΡŒ @import "tailwindcss"; + Π±Π»ΠΎΠΊ @theme, ΠΈ Ρ‡Ρ‚ΠΎ localhost:3000 дСмонстрируСт Ρ‚ΠΎΠΊΠ΅Π½Ρ‹. Π”Π΅Ρ€ΠΆΠΈΡ‚Π΅ запрос Ρ‡Ρ‘Ρ‚ΠΊΠΈΠΌ (Ссли ΠΎΠ½ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚, Π°Π³Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ†Π΅Π»ΡƒΡŽ Π³Π»Π°Π²Π½ΡƒΡŽ страницу) ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°ΠΉΡ‚Π΅ ΡˆΡ€ΠΈΡ„Ρ‚Ρ‹ Ρ‡Π΅Ρ€Π΅Π· next/font, Π½ΠΈΠΊΠΎΠ³Π΄Π° β€” Ρ‡Π΅Ρ€Π΅Π· ΠΈΠΌΠΏΠΎΡ€Ρ‚ Google Π²ΠΎ врСмя выполнСния.

8. Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ изобраТСния Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ² (ΠΏΠΎ ТСланию)

ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ β€” Ρ€Π°Π±ΠΎΡ‡Π΅Π΅ ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π±Π΅Π· ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΡ… Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ: создайтС ΠΏΠΎ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρƒ 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 β€” Π‘Π±ΠΎΡ€ΠΊΠ°

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ слой отобраТСния ΠΈ ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π°, Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ² всё Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ ΠΏΠΎΠΊΡƒΠΏΠΊΠΎΠΉ Π² тСстовом Ρ€Π΅ΠΆΠΈΠΌΠ΅.

1. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΠΏΡΡ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² UI-элСмСнтов

ΠŸΡΡ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ 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/, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Profound SDK 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-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², зарСгистрированных Π² рССстрС ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°-ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‡ΠΈΠΊΠ° ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°, 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 с ΠΊΠ½ΠΎΠΏΠΊΠΎΠΉ Β«ΠžΠΏΠ»Π°Ρ‚ΠΈΡ‚ΡŒΒ». Π₯Ρ€Π°Π½ΠΈ formatPrice Π² чистом Ρ„Π°ΠΉΠ»Π΅ src/lib/format.ts, Ρ‡Ρ‚ΠΎΠ±Ρ‹ клиСнтскиС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π»ΠΈ сСрвСрный catalog.ts.

src/components/AddToCartButton.tsx β€” ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ c Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²ΠΎΠΉ "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 для Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ²:

stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhook
# Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ whsec_... Π² STRIPE_WEBHOOK_SECRET, пСрСзапуститС bun dev

whsec_... дСйствуСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ сСссии. Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ Π΄Π²Π° ΠΏΡ€Π°Π²ΠΈΠ»Π°: checkout Π·Π°Π½ΠΎΠ²ΠΎ вычисляСт Ρ†Π΅Π½Ρ‹ ΠΏΠΎ ΠΊΠΎΠ΄Ρƒ Ρ‚ΠΎΠ²Π°Ρ€Π° ΠΈΠ· CMS (поддСльная ΠΊΠΎΡ€Π·ΠΈΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡ… ΠΏΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ), Π° Π²Π΅Π±Ρ…ΡƒΠΊ провСряСт подпись ΠΏΠΎ сырому Ρ‚Π΅Π»Ρƒ запроса.

5. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹

Админка β†’ 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 β†’ ΠΊΠ½ΠΎΠΏΠΊΠ° Β«ΠžΠΏΠ»Π°Ρ‚ΠΈΡ‚ΡŒΒ».
  • ΠžΠΏΠ»Π°Ρ‚Π° пСрСнаправляСт ΠΊ Stripe Checkout. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ‚Π΅ΡΡ‚ΠΎΠ²ΡƒΡŽ ΠΊΠ°Ρ€Ρ‚Ρƒ 4242 4242 4242 4242, Π»ΡŽΠ±ΡƒΡŽ Π±ΡƒΠ΄ΡƒΡ‰ΡƒΡŽ Π΄Π°Ρ‚Ρƒ ΠΈ CVC. Π’Ρ‹ Π²Π΅Ρ€Π½Ρ‘Ρ‚Π΅ΡΡŒ Π½Π° /cart?status=success, Π° stripe listen ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ checkout.session.completed.

Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° Ρ‚ΠΎΠ²Π°Ρ€Π° β€” галСрСя, Ρ†Π΅Π½Π° ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠ° Β«Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π² ΠΊΠΎΡ€Π·ΠΈΠ½ΡƒΒ».

ΠšΠΎΡ€Π·ΠΈΠ½Π° β€” ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΈ ΠΎΠ΄Π½Π° ΠΊΠ½ΠΎΠΏΠΊΠ° Β«ΠžΠΏΠ»Π°Ρ‚ΠΈΡ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· StripeΒ».

ΠžΠΏΠ»Π°Ρ‚ΠΈΡ‚ΡŒ ΠΌΠΎΠΆΠ½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎΠ²Π°Ρ€Ρ‹ с прописанной Ρ†Π΅Π½ΠΎΠΉ β€” Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ~3, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ настроили Π½Π° шагС 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). Π Π°Π·Π²Π΅Ρ€Π½ΠΈΡ‚Π΅.

Π—Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ Π±ΠΎΠ΅Π²ΠΎΠΉ Π²Π΅Π±Ρ…ΡƒΠΊ (сСкрСт локального stripe listen дСйствовал Ρ‚ΠΎΠ»ΡŒΠΊΠΎ локально): Stripe β†’ Developers β†’ Webhooks β†’ + Add endpoint β†’ https://<prod>/api/stripe/webhook, событиС checkout.session.completed. Π’ΡΡ‚Π°Π²ΡŒΡ‚Π΅ Π΅Π³ΠΎ whsec_... Π² Vercel ΠΈ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠΉΡ‚Π΅.

ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния = Β«Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ локально, пусто Π² ΠΏΡ€ΠΎΠ΄Π΅Β» β€” Π³Π»Π°Π²Π½Ρ‹ΠΉ источник ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΏΡ€ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠ΅. Π’ ΡƒΡ‡Π΅Π±Π½ΠΈΠΊΠ΅ ΠΌΡ‹ выкатываСмся с тСстовыми ΠΊΠ»ΡŽΡ‡Π°ΠΌΠΈ; ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅ STRIPE_SECRET_KEY ΠΈ сСкрСт Π²Π΅Π±Ρ…ΡƒΠΊΠ° Π½Π° Π±ΠΎΠ΅Π²Ρ‹Π΅, ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚Π΅ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ»Π°Ρ‚Π΅ΠΆΠΈ.

2. Π–ΠΈΠ²ΠΎΠΉ прСдпросмотр ΠΈ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° мСстС

Оба инструмСнта ΠΈΠ΄ΡƒΡ‚ Π² ΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡ‚Π΅ с каркасом.

  • Π–ΠΈΠ²ΠΎΠΉ прСдпросмотр: <Refresher> обновляСт страницу, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ просматриваСт Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€, ΠΊΠΎΠ³Π΄Π° Π² Π°Π΄ΠΌΠΈΠ½ΠΊΠ΅ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ измСнСния β€” Π±Π΅Π· ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ³ΠΎ дСплоя. (Π­Ρ‚ΠΎ прСдпросмотр для Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π°; посСтитСли видят ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ послС ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ Ρ€Π΅Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ.)
  • Π Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° мСстС: Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ?edit_mode=true ΠΊ Π»ΡŽΠ±ΠΎΠΌΡƒ URL, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎΠ²Π΅Ρ€Π»Π΅ΠΈ рСдактирования. ΠŸΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹Π΅ посСтитСли видят Ρ‡ΠΈΡΡ‚ΡƒΡŽ страницу.

Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ прСдпросмотра, ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π² каркасС. Админка Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ iframe прСдпросмотра ΠΏΠΎ адрСсу /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; // асинхронный 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, страницы списка ΠΈ Π΄Π΅Ρ‚Π°Π»Π΅ΠΉ ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡ€Π° ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΎΠ² ΠΈ Ρ€Π°Π±ΠΎΡ‡Π΅Π΅ хостинговоС ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π°. ИИ Π½Π°ΠΏΠΎΠ»Π½ΠΈΠ» ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠ» Π΄ΠΈΠ·Π°ΠΉΠ½ ΠΈ написал Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΡŒ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π° + ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ + Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΡƒΡŽ ΠΊΠΎΡ€Π·ΠΈΠ½Ρƒ; Π²Ρ‹ создали ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, связали Ρ†Π΅Π½Ρ‹ Stripe, настроили Ρ‚Ρ€ΠΈ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°, привязали CEL-Ρ…Ρ€ΠΎΠΌ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ Ρ‚Ρ€ΠΈ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… Ρ„Π°ΠΉΠ»Π° Stripe. CEL привязываСт Β«Ρ…Ρ€ΠΎΠΌΒ»; ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽΡ‚ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³. А Stripe остался ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½Ρ‹ΠΌ β€” ΠΎΠ΄ΠΈΠ½ Π²Ρ‹Π·ΠΎΠ² sessions.create ΠΈ ΠΎΠ΄ΠΈΠ½ подписанный Π²Π΅Π±Ρ…ΡƒΠΊ, ΠΏΡ€ΠΈΡ‡Ρ‘ΠΌ ΠΏΠΎΠΊΡƒΠΏΠ°Ρ‚Π΅Π»ΡŒ ΠΏΠ»Π°Ρ‚ΠΈΡ‚ Π½Π° собствСнном сайтС Stripe.

Continue Reading
Previousβ€ΉDeployments