ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΠΏΠΎΡΠ°Π³ΠΎΠ²ΠΎΠ΅ ΡΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ: ΡΠΎΠ·Π΄Π°ΠΉΡΠ΅ Π²ΠΈΡΡΠΈΠ½Ρ Stripe Π½Π° Profound CMS β ΠΊΠ°ΡΠ°Π»ΠΎΠ³, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΡΠ³ΠΎΠ²Π΅Ρ ΡΠ΅Π΄Π°ΠΊΡΠΈΡΡΠ΅Ρ Π±Π΅Π· ΠΊΠΎΠ΄Π°, Π΄Π²Π° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΡΠ΅ΡΠΊΠΈΡ ΠΌΠ°ΡΡΡΡΡΠ°, Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΡΡ ΠΊΠΎΡΠ·ΠΈΠ½Ρ ΠΈ ΠΎΡΠΎΡΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π°, ΡΠ°Π·ΠΌΠ΅ΡΡΠ½Π½ΠΎΠ΅ Π½Π° Stripe.
ΠΠΎΡΠΎΠ²ΡΠΉ ΠΌΠ°Π³Π°Π·ΠΈΠ½ Π² Π΄Π΅ΠΉΡΡΠ²ΠΈΠΈ β ΠΏΡΠΎΡΠΌΠΎΡΡΠΈΡΠ΅ ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΡ, ΠΎΡΠΊΡΠΎΠΉΡΠ΅ ΡΠΎΠ²Π°Ρ, Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ Π² ΠΊΠΎΡΠ·ΠΈΠ½Ρ ΠΈ ΠΎΡΠΎΡΠΌΠΈΡΠ΅ Π·Π°ΠΊΠ°Π·.
ΠΠΎΡΠ°Π³ΠΎΠ²ΠΎΠ΅ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ ΠΏΠΎ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΌΠ°Π³Π°Π·ΠΈΠ½Π°, ΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΠ΅Π½ΡΠΎΠΌ, Π½Π° Profound CMS: ΠΊΠ°ΡΠ°Π»ΠΎΠ³ ΡΠΎΠ²Π°ΡΠΎΠ² (ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΠΈ + ΠΏΠΎΠ·ΠΈΡΠΈΠΈ), ΡΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ Π² CMS, ΡΡΡΠ°Π½ΠΈΡΡ ΡΠΏΠΈΡΠΊΠ° ΠΈ Π΄Π΅ΡΠ°Π»Π΅ΠΉ ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡΠ° ΠΌΠ°ΡΡΡΡΡΠΎΠ² ΠΈ ΠΎΡΠΎΡΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π° Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ Stripe, ΠΏΠΎΡΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ΅ Π² Π²ΠΈΠ΄Π΅ Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²Π½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°.
ΠΡΠ½ΠΎΠ²ΠΎΠΉ ΡΠ»ΡΠΆΠ°Ρ Π½Π°ΠΏΠΈΡΠ°Π½Π½ΡΠΉ Π²ΡΡΡΠ½ΡΡ Next.js ΠΈ Π°Π΄ΠΌΠΈΠ½ΠΊΠ° Profound. Claude Code (ΡΠ΅ΡΠ΅Π· Profound MCP) Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΡΠ½ΠΎΠ²Π½ΡΡ ΡΠ°Π±ΠΎΡΡ Π² ΡΡΡΡ Π·Π°Π΄Π°ΡΠ°Ρ β Π½Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π°, ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π΄ΠΈΠ·Π°ΠΉΠ½-ΡΠΈΡΡΠ΅ΠΌΡ ΠΈ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ² Π²ΠΈΡΡΠΈΠ½Ρ (Π²ΠΊΠ»ΡΡΠ°Ρ Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΡΡ ΠΊΠΎΡΠ·ΠΈΠ½Ρ). Π’ΡΠΈ ΡΠ°ΡΡΠΈ: ΠΠ°ΡΡΡΠΎΠΉΠΊΠ°, Π‘Π±ΠΎΡΠΊΠ°, ΠΡΠΎΠ΄Π°ΠΊΡΠ½.
ΠΠ»Π°ΡΡΠΆ Π² ΠΎΠ΄Π½Ρ ΡΡΡΠΎΠΊΡ. ΠΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Stripe Checkout, ΡΠ°Π·ΠΌΠ΅ΡΡΠ½Π½ΡΠΉ Π½Π° Stripe: ΠΏΠΎΠΊΡΠΏΠ°ΡΠ΅Π»Ρ ΠΏΠ»Π°ΡΠΈΡ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ΅ Stripe, Π° Π½Π΅ Π½Π° Π²Π°ΡΠ΅ΠΉ. ΠΠ°ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π²ΡΠ΅Π³ΠΎ Π΄Π²Π΅ ΡΠ΅ΡΠ²Π΅ΡΠ½ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ β ΡΠΎΠ·Π΄Π°ΡΡ ΡΠ΅Π°Π½Ρ Checkout ΠΈ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ ΠΎΠ΄ΠΈΠ½ Π²Π΅Π±Ρ ΡΠΊ. ΠΠΈΠΊΠ°ΠΊΠΈΡ ΠΊΠ°ΡΡΠΎΡΠ½ΡΡ ΠΏΠΎΠ»Π΅ΠΉ, Π½ΠΈΠΊΠ°ΠΊΠΈΡ Stripe Elements, Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Π½Π°Π³ΡΡΠ·ΠΊΠΈ PCI.
/products/{item_code}, /categories/{category_code}) ΠΏΠ»ΡΡ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ /cart, Π²ΡΠ΅ ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡΠ° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ².useCart) ΠΈ Stripe Checkout, ΡΠ°Π·ΠΌΠ΅ΡΡΠ½Π½ΡΠΉ Π½Π° Stripe, ΠΏΡΠΈ ΡΡΠΎΠΌ ΡΠ΅Π½Π° Π²ΡΠ΅Π³Π΄Π° Π²ΡΡΠΈΡΠ»ΡΠ΅ΡΡΡ Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ ΠΏΠΎ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ Stripe Price.curl -fsSL https://bun.sh/install | bashstripe login) Π΄Π»Ρ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΡ
Π²Π΅Π±Ρ
ΡΠΊΠΎΠ².gh) ΠΈ Π°ΠΊΠΊΠ°ΡΠ½Ρ Vercel, ΠΏΠΎΠ΄ΠΊΠ»ΡΡΡΠ½Π½ΡΠΉ ΠΊ GitHub.Profound ΡΠ°Π·Π΄Π΅Π»ΡΠ΅Ρ ΠΊΠΎΠ½ΡΠ΅Π½Ρ ΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³:
category, item); ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ, ΠΏΠΎΠΌΠ΅ΡΠ΅Π½Π½ΡΠΉ ΡΠ΅Π³ΠΎΠΌ UI Element, ΡΠ°Π·ΠΌΠ΅ΡΠ°Π΅ΡΡΡ Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ΅ (nav, product_grid, ...).meta.params.* Π² CEL, routeParams Π² React).cms-renderer; Stripe Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΡΡΡ ΠΊΠ°ΠΊ ΠΎΠ±ΡΡΠ½ΡΠ΅ API-ΠΌΠ°ΡΡΡΡΡΡ.ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΠΎΠ΅ ΠΏΡΠ°Π²ΠΈΠ»ΠΎ, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡΠ΅Π΅ ΡΠ±ΠΎΡΠΊΡ: CEL ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠ»Ρ string/number. ΠΠΎΡΡΠΎΠΌΡ ΡΠΊΠ°Π»ΡΡΠ½ΡΠΉ Β«Ρ
ΡΠΎΠΌΒ» (Π±ΡΠ΅Π½Π΄ Π² Π½Π°Π²ΠΈΠ³Π°ΡΠΈΠΈ, ΠΏΠΎΠ΄Π²Π°Π», Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ) ΠΏΡΠΈΠ²ΡΠ·Π°Π½ ΡΠ΅ΡΠ΅Π· CEL, Π° Π²ΡΡ, ΡΡΠΎ Π±ΠΎΠ³Π°ΡΠ΅ ΠΈΠ»ΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ (ΡΠ΅ΡΠΊΡ ΡΠΎΠ²Π°ΡΠΎΠ², Π³Π°Π»Π΅ΡΠ΅Ρ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ, rich-text), Π·Π°Π³ΡΡΠΆΠ°Π΅ΡΡΡ Π²Π½ΡΡΡΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° ΠΏΠΎ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΌΠ°ΡΡΡΡΡΠ°. Π Stripe β ΠΈΡΡΠΎΡΠ½ΠΈΠΊ ΠΈΡΡΠΈΠ½Ρ Π΄Π»Ρ ΡΠ΅Π½: ΠΏΠΎΠ»Π΅ price Π² CMS ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ; ΡΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π²ΡΠ΅Π³Π΄Π° Π²ΡΡΠΈΡΠ»ΡΠ΅ΡΡΡ Π½Π° ΡΠ΅ΡΠ²Π΅ΡΠ΅ ΠΏΠΎ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ Stripe Price.
ΠΠΎΠ½Π΅ΡΠ½ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅: Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΎΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½ΡΠΉ ΠΊΠ°ΡΠ°Π»ΠΎΠ³, ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΎ Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡ, Stripe ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½, Π΄ΠΈΠ·Π°ΠΉΠ½ Π½Π° ΠΌΠ΅ΡΡΠ΅ β ΠΏΠΎΠΊΠ° Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ ΠΎΡΡΠΈΡΠΎΠ²ΡΠ²Π°Π΅ΡΡΡ.
ΠΠ°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΡΠΉΡΠ΅ΡΡ Π² Profound (WorkOS). Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ°ΠΉΡ Ρ ΠΈΠΌΠ΅Π½Π΅ΠΌ store, Π·Π°ΡΠ΅ΠΌ ΡΠΊΠΎΠΏΠΈΡΡΠΉΡΠ΅ Π΅Π³ΠΎ ID ΡΠ°ΠΉΡΠ° (UUID Π² URL Π°Π΄ΠΌΠΈΠ½ΠΊΠΈ) ΠΈ API-ΠΊΠ»ΡΡ ΡΡΠΎΠ²Π½Ρ ΡΡΠ΅Π½ΠΈΡ (Deployments β Create API key). ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΈΡΠ°Π΅Ρ; Π½Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π° ΠΏΠΎΠ·ΠΆΠ΅ ΠΈΠ΄ΡΡ ΡΠ΅ΡΠ΅Π· MCP, ΠΊΠΎΡΠΎΡΡΠΉ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΡΠΈΡΡΠ΅ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ.
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 Π½Π΅ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ.
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.
bun run generate-schemas
ΠΠΎΠΌΠ°Π½Π΄Π° Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅Ρ Zod-ΡΡ
Π΅ΠΌΡ ΠΈ ΡΠΈΠΏΡ Π² generated/cms-schemas.ts (categorySchema/Category, itemSchema/Item). ΠΠ°ΠΎΠ΄Π½ΠΎ ΡΡΠΎ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ β ΠΏΡΠΈ Π½Π΅Π²Π΅ΡΠ½ΡΡ
ΡΡΡΡΠ½ΡΡ
Π΄Π°Π½Π½ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄Π° Π·Π°Π²Π΅ΡΡΠΈΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ.
Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΠ΅ ΠΈ ΠΎΠ΄ΠΈΠ½ ΡΠ°Π· Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΡΠΈΡΡΠΉΡΠ΅ 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.
ΠΠΎΡΠ΅ΠΌΡ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½ΡΡ ΡΠΎΠ²Π°ΡΠΎΠ², ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ²ΡΠ·Π°Π½ Ρ ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΠ΅ΠΉ.
ΠΠ°ΡΠ°Π»ΠΎΠ³ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ Π² CMS; ΡΠ΅ΠΏΠ΅ΡΡ Π΄Π°ΠΉΡΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ ΡΠΎΠ²Π°ΡΠ°ΠΌ ΡΠ΅Π°Π»ΡΠ½ΡΡ ΡΠ΅Π½Ρ Π² Stripe β Π·Π°Π΄Π°ΡΠ° Π΄Π»Ρ ΡΠΎΡΠ³ΠΎΠ²ΡΠ°, Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Π² Π΄Π²ΡΡ Π°Π΄ΠΌΠΈΠ½ΠΊΠ°Ρ , Π±Π΅Π· ΠΊΠΎΠ΄Π°:
price_...).stripePriceId, ΡΠΎΡ
ΡΠ°Π½ΠΈΡΠ΅.CMS Ρ ΡΠ°Π½ΠΈΡ ΠΊΠ°ΡΠ°Π»ΠΎΠ³; Stripe β ΠΈΡΡΠΎΡΠ½ΠΈΠΊ ΠΈΡΡΠΈΠ½Ρ Π΄Π»Ρ ΡΠ΅Π½Ρ; ΡΠ²ΡΠ·Ρ β ΠΎΠ΄Π½Π° ΡΡΡΠΎΠΊΠ°, ΠΊΠΎΡΠΎΡΡΡ ΡΠΎΡΠ³ΠΎΠ²Π΅Ρ Π²ΡΡΠ°Π²Π»ΡΠ΅Ρ. (Π₯ΠΎΡΠΈΡΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ? ΠΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠΉ Stripe MCP ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ·Π΄Π°ΡΡ Products/Prices Π·Π° Π²Π°Ρ β Π²ΡΡΠ°Π²ΡΡΠ΅ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠ΅ ID ΡΠ΅ΠΌ ΠΆΠ΅ ΡΠΏΠΎΡΠΎΠ±ΠΎΠΌ.)
ΠΠ°ΡΠΊΠ°Ρ ΠΏΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π±Π΅Π· ΡΡΠΈΠ»Π΅ΠΉ. ΠΠΎΠΌΠ΅ΡΡΠΈΡΠ΅ DESIGN.md (Π±Π»ΠΎΠΊ @theme Tailwind v4 + ΡΠΎΠΊΠ΅Π½Ρ) Π² ΠΊΠΎΡΠ΅Π½Ρ ΠΏΡΠΎΠ΅ΠΊΡΠ° β ΡΠ²ΠΎΠΉ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΈΠ»ΠΈ ΡΠΊΠ°ΡΠ°Π½Π½ΡΠΉ Ρ refero.design. ΠΠ°ΡΠ΅ΠΌ Π΄Π°ΠΉΡΠ΅ Claude Π·Π°ΠΏΡΠΎΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΎ ΡΡΠΈΠ»ΠΈ:
ΠΡΠΎΡΠΈΡΠ°ΠΉ Π΄ΠΈΠ·Π°ΠΉΠ½-ΡΠ°ΠΉΠ», ΠΊΠΎΡΠΎΡΡΠΉ Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠ». ΠΠ°ΡΡΡΠΎΠΉ Tailwind ΠΏΡΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ, Π·Π°ΡΠ΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈ ΡΠ΅ΠΌΡ ΠΈ ΡΡΠΈΡΡΡ, ΡΡΠΎΠ±Ρ ΡΡΠΈΠ»ΠΈ Π·Π°ΡΠ°Π±ΠΎΡΠ°Π»ΠΈ. ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉ
next/fontΠ΄Π»Ρ ΡΡΠΈΡΡΠΎΠ² β Π½Π΅ Π·Π°Π³ΡΡΠΆΠ°ΠΉ ΠΈΡ ΠΈΠ· Google Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ. Π’ΠΎΠ»ΡΠΊΠΎ ΡΡΠΈΠ»ΠΈ β Π½Π΅ ΡΠΎΠ·Π΄Π°Π²Π°ΠΉ ΡΡΡΠ°Π½ΠΈΡΡ ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ.
Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ Π² src/app/globals.css Π΅ΡΡΡ @import "tailwindcss"; + Π±Π»ΠΎΠΊ @theme, ΠΈ ΡΡΠΎ localhost:3000 Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΠ΅Ρ ΡΠΎΠΊΠ΅Π½Ρ. ΠΠ΅ΡΠΆΠΈΡΠ΅ Π·Π°ΠΏΡΠΎΡ ΡΡΡΠΊΠΈΠΌ (Π΅ΡΠ»ΠΈ ΠΎΠ½ ΠΎΡΠΊΡΡΡ, Π°Π³Π΅Π½Ρ ΠΌΠΎΠΆΠ΅Ρ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ΅Π»ΡΡ Π³Π»Π°Π²Π½ΡΡ ΡΡΡΠ°Π½ΠΈΡΡ) ΠΈ Π·Π°Π³ΡΡΠΆΠ°ΠΉΡΠ΅ ΡΡΠΈΡΡΡ ΡΠ΅ΡΠ΅Π· next/font, Π½ΠΈΠΊΠΎΠ³Π΄Π° β ΡΠ΅ΡΠ΅Π· ΠΈΠΌΠΏΠΎΡΡ Google Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.
ΠΠ΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ β ΡΠ°Π±ΠΎΡΠ΅Π΅ ΠΎΡΠΎΡΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π±Π΅Π· ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ. Π§ΡΠΎΠ±Ρ ΠΈΡ
Π΄ΠΎΠ±Π°Π²ΠΈΡΡ: ΡΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΠΏΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΡ product_image Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ (Π·Π°Π³ΡΡΠ·ΠΈΡΠ΅ ΡΠ°ΠΉΠ» Π² ΠΏΠΎΠ»Π΅ image), Π·Π°ΡΠ΅ΠΌ ΡΠ²ΡΠΆΠΈΡΠ΅ ΠΈΡ
ΠΈΠ· ΠΌΠ°ΡΡΠΈΠ²Π° images ΡΠΎΠ²Π°ΡΠ°. ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΠΈ ΡΠΎΠ²Π°ΡΠΎΠ² ΠΈΠ»ΠΈ ΡΠ³Π΅Π½Π΅ΡΠΈΡΡΠΉΡΠ΅ ΡΠΎΠ³Π»Π°ΡΠΎΠ²Π°Π½Π½ΡΠΉ Π½Π°Π±ΠΎΡ ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ (ΠΏΠΎΠΏΡΠΎΡΠΈΡΠ΅ Claude Π²ΡΠ²Π΅ΡΡΠΈ ΡΠΈΡΠΌΠ΅Π½Π½ΡΠ΅ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠΈ ΠΈΠ· DESIGN.md ΠΈ Π·Π°ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ΄ΠΈΠ½ --sref Π² Midjourney, ΡΡΠΎΠ±Ρ Π²ΡΠ΅ ΡΠ½ΠΈΠΌΠΊΠΈ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΎΠ²Π°Π»ΠΈ ΡΡΠΈΠ»Ρ).
ΠΡΠ΄Π΅Π»ΡΠ½Π°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°
cms-rendererΠ½Π΅ ΠΈΠΌΠ΅Π΅Ρ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ° Π΄Π»Ρ URL ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ, ΠΏΠΎΡΡΠΎΠΌΡ Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ ΡΡΠ½ΠΊΡΠΈΡbuildAssetUrlΠ²src/lib/image.ts(~40 ΡΡΡΠΎΠΊ) β ΠΎΠ½Π° Π΄ΠΎΠ±Π°Π²ΠΈΡ ΠΏΡΠ΅ΡΠΈΠΊΡNEXT_PUBLIC_BUNNY_CDN_URLΠΈ ΡΠ°ΡΡΠΈΡΠ΅Π½ΠΈΠ΅. ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΠΈΠ· ΡΠ°Π³Π° 3 ΡΠ°ΡΡΠΈ Β«Π‘Π±ΠΎΡΠΊΠ°Β» ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ Π΅Ρ.
Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ»ΠΎΠΉ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΈ ΠΎΡΠΎΡΠΌΠ»Π΅Π½ΠΈΠ΅ Π·Π°ΠΊΠ°Π·Π°, Π·Π°Π²Π΅ΡΡΠΈΠ² Π²ΡΡ ΡΠ΅Π°Π»ΡΠ½ΠΎΠΉ ΠΏΠΎΠΊΡΠΏΠΊΠΎΠΉ Π² ΡΠ΅ΡΡΠΎΠ²ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅.
ΠΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ², ΠΊΠ°ΠΆΠ΄ΡΠΉ Active ΠΈ ΠΏΠΎΠΌΠ΅ΡΠ΅Π½ ΡΠ΅Π³ΠΎΠΌ UI Element (Settings β Tags), Π±Π΅Π· Route Slug:
nav β brandproduct_grid β headingproduct_detail β headingcart_summary β headingfooter β textΠΡΠ΅ ΠΏΠΎΠ»Ρ β Text. Π’Π΅Π³ UI Element Π΄Π΅Π»Π°Π΅Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄ΠΎΡΡΡΠΏΠ½ΡΠΌ Π² ΡΠΏΠΈΡΠΊΠ΅ Add UI Element Π² Page Builder β ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΡΠΈΠ·Π½Π°ΠΊΠ° Active Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ. ΠΠ°ΠΆΠ΄ΠΎΠ΅ ΠΏΠΎΠ»Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠΊΠ°Π»ΡΡΠΎΠΌ (ΡΠΎΡ ΡΠΈΠΏ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ ΡΠ΅ΡΠ΅Π· CEL); ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ Π΄Π°Π½Π½ΡΠ΅ ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π° Π½Π΅ ΠΏΠΎΠ»Π΅ Π·Π΄Π΅ΡΡ β ProductGrid/ProductDetail ΠΈΠ·Π²Π»Π΅ΠΊΠ°ΡΡ ΠΈΡ
ΠΏΠΎ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΌΠ°ΡΡΡΡΡΠ° (ΡΠ°Π³ 3).
bun run generate-schemas
ΠΠ΄ΠΈΠ½ Π·Π°ΠΏΡΠΎΡ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊ ΡΡΠ΅Π½ΠΈΡ, ΠΏΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ², ΠΊΠΎΡΠ·ΠΈΠ½Ρ ΠΈ ΡΠ΅Π΅ΡΡΡ:
ΠΠΎΡΡΡΠΎΠΉ Π½Π°ΡΡ Π²ΠΈΡΡΠΈΠ½Ρ Π²
src/, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ Profound SDKcms-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.Π’ΡΠΈ ΠΊΠΎΡΠΎΡΠΊΠΈΡ
ΡΠ΅ΡΠ²Π΅ΡΠ½ΡΡ
ΡΠ°ΠΉΠ»Π° β Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΏΠ»Π°ΡΡΠΆΠ½ΡΠΉ ΠΊΠΎΠ΄ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. ΠΠ½ΠΈ ΠΏΠ΅ΡΠ΅ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ 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 (ΠΏΠΎΠ΄Π΄Π΅Π»ΡΠ½Π°Ρ ΠΊΠΎΡΠ·ΠΈΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΠΈΡ
ΠΏΠΎΠΌΠ΅Π½ΡΡΡ), Π° Π²Π΅Π±Ρ
ΡΠΊ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΡ ΠΏΠΎ ΡΡΡΠΎΠΌΡ ΡΠ΅Π»Ρ Π·Π°ΠΏΡΠΎΡΠ°.
ΠΠ΄ΠΌΠΈΠ½ΠΊΠ° β Pages β Create page, ΡΡΠΈ ΡΠ°Π·Π°. Π‘ΠΎΠΏΠΎΡΡΠ°Π²ΡΡΠ΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡ ΡΠ²ΠΎΠ΅ΠΌΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ (ΠΏΠΎΠ»Π΅ slug β code):
/products/{item_code} β item/categories/{category_code} β category/cart β ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΡΡΡΠ°Π½ΠΈΡΠ° (Π²Π²Π΅Π΄ΠΈΡΠ΅ Π±ΡΠΊΠ²Π°Π»ΡΠ½ΡΠΉ /cart, Π½Π΅ /{cart})ΠΠ»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΌΠ°ΡΡΡΡΡΠ°: 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 MCPupdate_page, Π·Π°ΡΠ΅ΠΌ ΠΏΡΠ±Π»ΠΈΠΊΡΠΉΡΠ΅. (Π‘ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ/cartΠΏΡΠΈΠΊΡΠ΅ΠΏΠ»ΡΠ΅ΡΡΡ ΡΡΠ°ΡΠ½ΠΎ.) ΠΠΎ ΡΠΎΠΉ ΠΆΠ΅ ΠΏΡΠΈΡΠΈΠ½Π΅ProductGridΠ±Π΅ΡΡΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΈΠ· Π½Π°ΠΉΠ΄Π΅Π½Π½ΠΎΠΉ ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΠΈ, Π° Π½Π΅ ΡΠ΅ΡΠ΅Π· CEL.
/categories/lighting β ΡΠ΅ΡΠΊΠ°. ΠΠ°ΠΆΠΌΠΈΡΠ΅ Π½Π° ΡΠΎΠ²Π°Ρ β ΡΡΡΠ°Π½ΠΈΡΠ° Ρ Π΄Π΅ΡΠ°Π»ΡΠΌΠΈ ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΎΠΉ Β«ΠΠΎΠ±Π°Π²ΠΈΡΡ Π² ΠΊΠΎΡΠ·ΠΈΠ½ΡΒ». /cart β ΠΊΠ½ΠΎΠΏΠΊΠ° Β«ΠΠΏΠ»Π°ΡΠΈΡΡΒ»./cart?status=success, Π° stripe listen ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ checkout.session.completed.Π‘ΡΡΠ°Π½ΠΈΡΠ° ΡΠΎΠ²Π°ΡΠ° β Π³Π°Π»Π΅ΡΠ΅Ρ, ΡΠ΅Π½Π° ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠ° Β«ΠΠΎΠ±Π°Π²ΠΈΡΡ Π² ΠΊΠΎΡΠ·ΠΈΠ½ΡΒ».
ΠΠΎΡΠ·ΠΈΠ½Π° β ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΠΈ ΠΎΠ΄Π½Π° ΠΊΠ½ΠΎΠΏΠΊΠ° Β«ΠΠΏΠ»Π°ΡΠΈΡΡ ΡΠ΅ΡΠ΅Π· StripeΒ».
ΠΠΏΠ»Π°ΡΠΈΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΎΠ²Π°ΡΡ Ρ ΠΏΡΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠΉ ΡΠ΅Π½ΠΎΠΉ β Π²ΡΠ±Π΅ΡΠΈΡΠ΅ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ~3, ΠΊΠΎΡΠΎΡΡΠ΅ Π²Ρ Π½Π°ΡΡΡΠΎΠΈΠ»ΠΈ Π½Π° ΡΠ°Π³Π΅ 6.
ΠΠ΅ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ β ΠΈΠ½ΡΠ΅ΡΠ½Π°ΡΠΈΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡΡΠΉΡΠ΅. ΠΠ΅ΡΠ΅Π²Π΅Π΄ΠΈΡΠ΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ (Π²ΡΠ΅ 35 ΡΠ·ΡΠΊΠΎΠ² ΡΡΠ°Π·Ρ), Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ ΡΠ΅Π³ΠΌΠ΅Π½Ρ
/{language}/..., ΡΠΎΠΏΠΎΡΡΠ°Π²Π»Π΅Π½Π½ΡΠΉ ΡΠΎ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΌ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠΌlanguage, ΠΈ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠΈΡΠ΅ ΠΏΠΎΠ»Ρ, ΠΏΡΠΈΠ²ΡΠ·Π°Π½Π½ΡΠ΅ ΡΠ΅ΡΠ΅Π· CEL, Π½Π°documents.translated. Π‘ΠΌ. ΡΡΠΎΠΊ ΠΏΡΠΎ ΡΠΏΡΠ°Π²ΠΎΡΠ½ΠΈΠΊ Π°ΡΡΠΎΠΏΠΎΡΡΠΎΠ², ΡΠ°ΡΡΡ 2, ΡΠ°Π³ 7.
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 ΠΈ ΡΠ΅ΠΊΡΠ΅Ρ Π²Π΅Π±Ρ
ΡΠΊΠ° Π½Π° Π±ΠΎΠ΅Π²ΡΠ΅, ΠΊΠΎΠ³Π΄Π° Π±ΡΠ΄Π΅ΡΠ΅ Π³ΠΎΡΠΎΠ²Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡ ΡΠ΅Π°Π»ΡΠ½ΡΠ΅ ΠΏΠ»Π°ΡΠ΅ΠΆΠΈ.
ΠΠ±Π° ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠ° ΠΈΠ΄ΡΡ Π² ΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡΠ΅ Ρ ΠΊΠ°ΡΠΊΠ°ΡΠΎΠΌ.
<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.