profound-logoProfound CMS
⌘K
Admin
Theme
BelgelerTutorialBlogPhilosophy
BelgelerTutorialBlogPhilosophy

Tutorials

Build & Ship an Airport DirectoryDağıtımlarBuild & Ship a Stripe Storefront

Feature

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

Uygulamalı bir rehber: Profound CMS üzerinde içerik odaklı bir Stripe mağazası inşa edin — kod yazmadan tüccarın düzenlediği bir katalog, iki parametrik rota, başsız bir sepet ve Stripe barındırmalı checkout.

Hareket halindeki tamamlanmış mağaza — bir kategoride gezin, bir ürünü açın, sepete ekleyin, ödeme yapın.

Profound CMS üzerinde içerik odaklı bir mağaza kuran uygulamalı bir rehber: CMS’de modellenmiş bir ürün kataloğu (kategoriler + öğeler), tek bir rota setinden liste ve detay sayfaları ve başsız bir bileşen olarak sunulan Stripe barındırmalı ödeme.

Omurga, elle yazılmış Next.js ve Profound yönetim panelidir. Claude Code (Profound MCP aracılığıyla) üç işte ağır yükü üstlenir — kataloğu tohumlama, tasarım sistemini bağlama ve mağaza bileşenlerini yazma (başsız sepet dahil). Üç bölüm: Kurulum, İnşa, Üretim.

Tek satırda ödemeler. Stripe barındırmalı Checkout kullanıyoruz: alışveriş yapan kişi sizin sayfanızda değil, Stripe'ın sayfasında ödeme yapar. Uygulamanız sunucu tarafında yalnızca iki şey yapar — bir Checkout Session oluşturur ve bir webhook doğrular. Kart alanı yok, Stripe Elements yok, PCI yükü yok.

Neler inşa edeceksiniz

  • CMS’de yayınlanmış küçük bir katalog — üç kategori ve sekiz ürün ("Edison'un Buluşları" demosu) — kod yazmadan bir tüccar tarafından düzenlenebilir.
  • İki parametrik rota (/products/{item_code}, /categories/{category_code}) artı statik /cart, hepsi tek bir bileşen setinden.
  • Başsız bir sepet (useCart) ve Stripe barındırmalı ödeme, fiyat her zaman sunucu tarafında bir Stripe Fiyat Kimliği’nden çözülür.
  • Mağaza Vercel’e canlı önizleme ve ekip için yerinde düzenleme ile dağıtılır.

Önkoşullar

  • Bun ≥ 1.3 — curl -fsSL https://bun.sh/install | bash
  • Profound MCP ile Claude Code (1. bölüm kuruyor).
  • Bir Profound CMS hesabı.
  • Bir Stripe hesabı. Bu eğitim test modunda çalışır, böylece siz inşa ederken gerçek para çekilmez — ancak akış canlı anahtarlarla birebirdir, isterseniz gerçek hesap anahtarlarınızı kullanın. (Test modu işletme veya banka bilgisi gerektirmez.)
  • Yerel webhook’lar için Stripe CLI (stripe login).
  • Dağıtım için: GitHub CLI (gh) ve GitHub’a bağlı bir Vercel hesabı.

Parçalar nasıl bir araya gelir

Profound içeriği render’dan ayırır:

  • Bileşenler içeriğin şeklini tanımlar. Rota Slug alanına sahip bir Özel Bileşen yönlendirilebilir (category, item); UI Element etiketi olan bir bileşen bir sayfaya yerleştirilebilir (nav, product_grid, …).
  • Dokümanlar içeriktir (bir ürün, bir kategori).
  • UI öğeleri sayfa bölümleridir; her skaler alan statik bir değer veya render sırasında değerlendirilen bir CEL ifadesi alır.
  • Parametrik rotalar, bir URL’yi bir dokümana + UI öğelerine eşleyerek rota parametrelerini (meta.params.* CEL’de, routeParams React’te) geçirir.
  • Next.js uygulamanız bunu cms-renderer aracılığıyla okur; Stripe sıradan API rotaları olarak eklenir.

İnşayı şekillendiren tek kural: CEL yalnızca string/number alanlarını bağlar. Bu nedenle skaler krom (navigasyon markası, alt bilgi, başlıklar) CEL ile bağlanır, ancak zengin veya koleksiyon niteliğindeki herhangi bir şey (bir ürün grid’i, görüntü galerisi, zengin metin) rota parametresiyle React bileşeni içinde fetch edilir. Ve Stripe fiyatlandırma için tek gerçek kaynaktır — CMS price alanı sadece gösterim içindir; ücret her zaman sunucu tarafında bir Stripe Fiyat ID’sinden çözülür.

Bölüm 1 — Kurulum

Nihai durum: küçük bir yayınlanmış katalog, onu okumak üzere kablolanmış uygulama, Stripe kurulmuş, tasarım yerinde — henüz hiçbir şey render edilmedi.

1. Kaydolun ve web sitesini oluşturun

Profound’a kaydolun (WorkOS kimlik doğrulaması). store adlı bir web sitesi oluşturun, ardından web sitesi kimliğini (yönetici URL’sindeki UUID) ve bir okuma katmanı API anahtarını (Deployments → Create API key) kopyalayın. Uygulama yalnızca okur; katalog tohumu daha sonra MCP üzerinden gider ve ayrı şekilde kimlik doğrulaması yapar.

2. Uygulamayı iskeletleyin, bağlayın ve Stripe ekleyin

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

İskele, Profound için önceden kablolanmış bir Next.js App Router projesidir (cms-renderer SDK’sı, catch-all rota, generate-schemas betiği, <Refresher>). Stil içermez. bun add stripe, barındırmalı Checkout’un ihtiyaç duyduğu tek ödeme bağımlılığı olan sunucu SDK’sını çeker.

Değerlerinizi .env.local dosyasına ekleyin:

# CMS
PROFOUND_API_KEY=<okuma anahtarınız>
NEXT_PUBLIC_PROFOUND_WEBSITE_ID=<web sitesi kimliğiniz>
NEXT_PUBLIC_CMS_API_URL=https://cms.dev.tryprofound.com
NEXT_PUBLIC_BUNNY_CDN_URL=https://cms-profound.b-cdn.net   # CMS barındırmalı görselleri sunar

# Stripe
STRIPE_SECRET_KEY=sk_test_...            # burada test anahtarı; canlıya çıktığınızda gerçek anahtarınızla değiştirin
STRIPE_WEBHOOK_SECRET=whsec_...          # Üretim adımı 4’te doldurulacak
NEXT_PUBLIC_SITE_URL=http://localhost:3000

STRIPE_SECRET_KEY anahtarını Stripe → Developers → API keys bölümünden alın. İnşa sırasında gerçek para hareket etmesin diye test anahtarı (sk_test_…) kullanıyoruz; gerçek ödemeleri kabul etmeye hazır olduğunuzda canlı anahtarınıza geçin. bun dev çalıştırın ve localhost:3000'i açın — başlangıç sayfası render edilir.

Barındırmalı Checkout tarayıcıyı bir Stripe URL’sine yönlendirir, bu nedenle Stripe’ın ihtiyaç duyduğu tek şey sunucu gizli anahtarıdır — yayınlanabilir anahtar yok, istemci Stripe SDK’sı yok.

3. category, product_image ve item bileşenlerini tanımlayın

Üç Özel Bileşen oluşturun (Components → Create new component) — veri kaynağıdır, bu yüzden UI Element etiketi yok. Her birini Active olarak ayarlayın.

CMS’de “görsel dizisi” alanı olmadığından, galeri küçük bir product_image bileşenine yapılan referansların dizisidir. category ve product_image bileşenlerini item’dan önce oluşturun ve Active yapın — bir referans alanı yalnızca Active bileşenleri hedefler.

  • category — name (Metin), code (Metin, Route Slug), description (Zengin metin), heroImage (Görsel)
  • product_image — image (Görsel)
  • item — name (Metin), code (Metin, Route Slug), description (Zengin metin), images (referans dizisi → product_image), price (Sayı, sent — yalnızca gösterim), currency (Seçim, usd), stripePriceId (Metin), category (Referans → category), active (Boolean)

Tüm alanları isteğe bağlı bırakın. Yönetici, alan adlarını küçük harfle yılan biçimine çevirir (“Stripe Price Id” → stripe_price_id) — kodunuz bu gerçek adlara göre çalışır, bu yüzden sonraki adımda generate-schemas çıktısından okuyun. Rota tarafından çağrılabilir tutamağa code adını veriyoruz ( slug değil): Rota Slug ve daha sonra temiz bir documents.getByCode araması için anahtar.

item bileşeni — Route Slug olarak code, product_image referanslarına bağlanan images, ayrıca stripePriceId ve bir category referansı.

4. Bileşenleri yerel tiplere çekin

bun run generate-schemas

generated/cms-schemas.ts dosyasına Zod şemaları + tipleri yazar (categorySchema/Category, itemSchema/Item). Aynı zamanda bir bağlantı kontrolüdür — yanlış kimlik bilgileri burada hata verir.

5. Profound MCP ile kataloğu tohumlayın

MCP’yi bir kez kurun ve kimlik doğrulaması yapın:

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

mcp__Profound__authenticate komutunu çalıştırın, WorkOS akışını tamamlayın, ardından Claude’a şu istemi verin:

Edison'un Buluşları adlı bir mağaza için küçük bir e-ticaret kataloğu oluştur — üç kategori ve şu ürünler, her biri için döneme uygun kısa bir description, sent cinsinden price, currency: "usd" ve active: true:

  • Aydınlatma & Güç (code: lighting): Akkor Ampul (incandescent-lightbulb, 24$), Elektrik Dinamosu (electric-dynamo, 890$), Elektrikli Kalem (electric-pen, 49$)
  • Ses Kaydı (code: sound): Folyo Fonograf (tinfoil-phonograph, 249$), Karbon Mikrofon (carbon-microphone, 59$), Diktafon (dictaphone, 179$)
  • Hareketli Resimler (code: motion): Kinetoskop (kinetoscope, 399$), Kinetograf Kamera (kinetograph, 549$)

Her kategori name ve bu küçük harf code’a ihtiyaç duyar; her item name, bu küçük harf code, description, (sent cinsinden) price, currency ve active alanlarına sahip olmalıdır. Bunu data/catalog.json dosyasına kaydet ve category ile item bileşenlerimize göre doğrula. Ardından Profound MCP’yi kullanarak her birini yayınlanmış doküman olarak oluştur: önce kategorileri oluştur, kimliklerini yakala, ardından öğeleri category alanı { "_type": "reference", "_ref": "<category-id>", "_schema": "category" } olacak şekilde oluştur. stripePriceId alanını şimdilik boş bırak. Öğeleri paralelde oluştur.

Claude data/catalog.json dosyasını yazar, doğrular ve paralel create_document çağrılarını gerçekleştirir (status: "published"). Referansların halihazırda var olan kimliklere işaret etmesi için öğelerden önce kategorileri tohumlayın.

Üç tohumlanmış kategori, yayınlanmış ve Live.

Sekiz tohumlanmış ürün, her biri bir kategoriye bağlı.

6. Stripe fiyatları oluşturun ve birkaç ürünü bağlayın

Katalog CMS’de; şimdi birkaç ürüne gerçek bir Stripe fiyatı verin — tüccarın işi, iki yönetici panelinde yapılır, kod yok:

  1. Stripe Dashboard → Products → + Add product, tek seferlik bir fiyat ayarlayın, Price ID (price_…) kopyalayın.
  2. Bunu yaklaşık 3 öne çıkan ürün için yapın (örn. Ampul, Fonograf, Kinetoskop).
  3. Profound yönetimi → item → Documents → her Price ID’yi stripePriceId alanına yapıştırın, kaydedin.

Katalog CMS’de durur; Stripe gerçek fiyat kaynağıdır; bağlantı tüccarın yapıştırdığı tek bir stringtir. (Otomatikleştirmeyi mi tercih edersiniz? Resmi Stripe MCP, Products/Prices oluşturabilir — dönen kimlikleri aynı şekilde yapıştırın.)

7. Tasarım sistemini ekleyin ve yapay zekâ ile bağlayın

İskelet projesi stillendirilmemiş gelir. Proje köküne bir DESIGN.md (Tailwind v4 @theme bloğu + token’lar) koyun — kendi dosyanız olabilir veya refero.design üzerinden indirin. Ardından Claude’a, yalnızca stil kapsamına alınmış şekilde şu promptu verin:

Az önce eklediğim tasarım dosyasını oku. Gerekirse Tailwind’i kur, ardından temayı ve fontları bağla, böylece stiller çalışsın. Fontlar için next/font kullan — çalışma zamanında Google’dan yükleme. Sadece stil — henüz sayfa veya bileşen oluşturma.

src/app/globals.css dosyasında @import "tailwindcss"; ve @theme bloğu olduğundan emin olun ve localhost:3000 token’ları gösterdiğini doğrulayın. Prompt’u dar tutun (açık uçlu olursa, bir ajan tüm ana sayfayı iskeletleyebilir) ve fontları next/font ile yükleyin, çalışma zamanında Google import’u yapmayın.

8. Ürün görselleri ekleyin (isteğe bağlı)

İsteğe bağlı — görseller olmadan da çalışan bir checkout’a ulaşabilirsiniz. Eklemek için: her görsel için bir product_image dokümanı oluşturun (görselini image alanına yükleyin), ardından bu dokümanlara ürünün images dizisinden referans verin. Kendi ürün fotoğraflarınızı getirin veya bir görsel modeliyle tutarlı bir set üretin (Claude’a DESIGN.md’den markaya uygun prompt’lar türetmesini söyleyin ve her kare aynı görünsün diye tek bir Midjourney --sref kilitleyin).

Bağımsız cms-renderer bir görsel URL yardımcı fonksiyonuna sahip değildir, bu yüzden buildAssetUrl fonksiyonunu src/lib/image.ts dosyasına ekleyin (~40 satır) — NEXT_PUBLIC_BUNNY_CDN_URL ile öne ekler ve uzantıyı ekler. 2. bölüm 3. adımdaki bileşenler bunu kullanır.

Bölüm 2 — İnşa

Renderer katmanını ve checkout’u inşa edin, test modunda gerçek bir satın alma ile bitirin.

1. Beş UI element bileşenini tanımlayın

Beş bileşen, her biri Active ve UI Element etiketi (Ayarlar → Etiketler), Route Slug yok:

  • nav → brand · product_grid → heading · product_detail → heading · cart_summary → heading · footer → text (hepsi Metin)

UI Element etiketi, bir bileşenin Sayfa Oluşturucu’nun Add UI Element listesinde görünmesini sağlar — yalnızca Active olmak yetmez. Her alan skaler (CEL’in bağladığı tür); gerçek katalog verisi burada bir alan değildir — ProductGrid/ProductDetail rota parametresiyle fetch eder (adım 3).

2. Tipleri yeniden üretin

bun run generate-schemas

3. Katalog okuyucusunu, bileşenleri ve başsız sepeti oluşturun

Tek bir prompt, okuma yardımcısını, beş bileşeni, sepeti ve registry’i oluşturur:

Profound cms-renderer SDK’sını kullanarak mağazamızı src/ klasöründe oluştur.

src/lib/catalog.ts — sunucu tarafı bir CMS okuyucusu. cms-renderer/lib/cms-api içerisindeki getCmsClient({ cmsUrl: process.env.NEXT_PUBLIC_CMS_API_URL!, apiKey: process.env.PROFOUND_API_KEY, websiteId: process.env.NEXT_PUBLIC_PROFOUND_WEBSITE_ID! }) ile bir istemci oluştur. getItemByCode(code) fonksiyonunu dışa aktar → cms.documents.getByCode.query({ websiteId, schemaName: "item", code }) sonucunda dönen res.document.published_content'ı geri döndürür. listItems(categoryCode?) fonksiyonunu dışa aktar → cms.documents.list.query({ websiteId, schemaName: "item", status: "published", limit: 100 }), res.documents değerini .published_content'e eşle, active !== false olanları filtrele ve categoryCode verilmişse, category._ref değeri kategorinin document.id'sine eşit olan öğeleri tut. resolveImages(refs) fonksiyonunu dışa aktar; her item.images referansını cms.documents.get.query({ websiteId, id: ref._ref }) ile çözer ve görsel alanını vendored buildAssetUrl (Bölüm 1 adım 8) ile bir URL’ye dönüştürür.

src/components/ — catch-all rotasının registry’sine yöneticiyle eşleşen snake_case bileşen adlarıyla kaydedilmiş beş UI element bileşeni: { nav, product_grid, product_detail, cart_summary, footer }. Nav ve Footer, skaler alanlarını content prop’undan okur (cms-renderer/lib/types içindeki BlockComponentProps<T> tipinde). ProductGrid ve ProductDetail async sunucu bileşenleri olup routeParams’ı okur ve catalog.ts dosyasından fetch eder: routeParams.<param> değeri { value, … } — .value’ı oku, böylece ProductGrid listItems(routeParams.category_code?.value) çağırır (kartlar /products/{code} bağlantısı verir) ve ProductDetail getItemByCode(routeParams.item_code?.value) çağırır (galeri resolveImages aracılığıyla, zengin metin açıklaması, fiyat, Sepete ekle). CartSummary, useCart’tan gelen sepeti Ödeme butonuyla render eder. formatPrice fonksiyonunu salt src/lib/format.ts dosyasında tut ki istemci bileşenleri sunucuya özel catalog.ts'i import etmesin.

src/components/AddToCartButton.tsx — { code, name, priceLabel } alanlarını alan "use client" bir buton, useCart().addItem({ code, name, priceLabel, quantity: 1 }) çağırır. Bunu ProductDetail içinde kullan.

src/lib/useCart.ts — başsız bir sepet: durum içinde { code, name, priceLabel, quantity } satır öğeleri, localStorage’a kalıcı, addItem/removeItem/updateQty/subtotal ve /api/stripe/checkout rotasına { lines: [{ code, quantity }] } (yalnızca kodlar ve adetler — asla fiyatlar değil) POST eden ve dönen url'ye yönlendiren checkout() sunar.

Her şeyi tasarım sistemimizle stillendir, kendi bileşenlerimiz gibi — kaynak sitenin düzenini kopyalama.

Çalıştıktan sonra bilmeniz gereken üç şey:

  • Skaler krom content üzerinden gelir ({ content }: BlockComponentProps<T>) — alanları üst düzey prop olarak destructure ederseniz blok boş render olur. Katalog verisi routeParams + catalog.ts fetch’inden gelir, çünkü CEL listeleri veya galerileri bağlayamaz. Sepet öğe kodlarını taşır, fiyatları asla.
  • routeParams.<param> değeri { value, schemaName, document } — .value okuyun. Okumalar published_content döndürür, .content değil. Registry anahtarları yöneticiyle eşleşen snake_case'dir.
  • @types/react/@types/react-dom paketlerini v19’a yükseltin — iskelet proje v18 ile gelir, bu da React 19’a karşı async sunucu bileşeni bloklarını bozar.

4. Stripe sunucu kodunu yazın (omurga)

Üç kısa sunucu dosyası — uygulamadaki tek ödeme kodu. getItemByCode fonksiyonunu yeniden kullanırlar, böylece ücret sunucu tarafında çözülür.

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 — her öğeyi CMS’den çöz, ücreti Stripe fiyatına göre al:

import { NextResponse } from "next/server";
import { stripe } from "@/lib/stripe";
import { getItemByCode } from "@/lib/catalog"; // sunucu tarafı, okuma katmanı anahtarı

export async function POST(req: Request) {
  const { lines } = await req.json();                // [{ code, quantity }] — istemciden fiyat yok
  const line_items = await Promise.all(
    lines.map(async ({ code, quantity }: { code: string; quantity: number }) => {
      const item = await getItemByCode(code);          // sunucu CMS’den çözer
      return { price: item!.stripe_price_id, quantity }; // fiyat CMS’den, asla istemciden değil
    })
  );
  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 });     // istemci buraya yönlendirir
}

src/app/api/stripe/webhook/route.ts — güvenilir tamamlanma sinyali:

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

export async function POST(req: Request) {
  const body = await req.text();                      // RAW gövde — imza doğrulaması için gerekli
  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") {
    // siparişi yerine getirin: siparişi kaydedin / makbuz gönderin.
  }
  return new Response(null, { status: 200 });
}

Gereken iskelet düzeltmesi: iskeletin src/proxy.ts dosyası her /api/* isteğini CMS’ye yönlendirir, bu da Stripe rotalarınızın çalışmasını engeller. Önce bunların geçmesine izin verin:

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();                       // yerelde işle
  }
  return cmsProxy(request as unknown as Parameters<typeof cmsProxy>[0]);
};
// iskeletin `export const config = { matcher: [...] }` kısmını değiştirmeyin

Doğrulayın: curl -X POST localhost:3000/api/stripe/webhook -d x Bad signature döndürür.

Yerel webhook’lar için Stripe CLI’ı çalıştırın:

stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhook
# whsec_... değerini STRIPE_WEBHOOK_SECRET alanına kopyalayın, bun dev’i yeniden başlatın

whsec_… her oturum için geçerlidir. Güvenliği sağlayan iki kural: checkout fiyatı CMS’den code ile tekrar türetir (kurcalanmış bir sepet bunu değiştiremez) ve webhook ham gövdeye karşı imzayı doğrular.

5. Rotaları oluşturun

Yönetici → Pages → Üç kez Create page. Her parametreyi bileşenine eşleyin (slug alanı code):

  1. /products/{item_code} → item
  2. /categories/{category_code} → category
  3. /cart — statik bir sayfa (kelimesi kelimesine /cart yazın, /{cart} değil)

6. UI elementleri ekleyin, CEL’i bağlayın, yayınlayın

Her rota için: Page Builder → Add UI Element → Custom → bileşenleri sırayla ekleyin, skaler alanları doldurun (statik değer veya CEL), Publish.

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

nav.brand ve footer.text alanlarını statik string’e ayarlayın; başlıkları statik etiketlere.

Kategori rotasında Page Builder — product_grid öğesi seçili, heading’i CEL ile bağlanmış.

Ürün rotasında Page Builder — product_detail öğesi bir ürün bağlamında.

Parametrik Page Builder hatası: iki parametrik rotada UI öğeleri eklemek kalıcı olmaz (bloklar yetim kalır ve sayfa boş render edilir). Düzeltme gelene kadar, bu sayfaların block_ids değerlerini Profound MCP update_page aracılığıyla doğrudan bağlayın, ardından yayınlayın. (Statik /cart normal şekilde bağlanır.) Aynı nedenle, ProductGrid başlığını CEL yerine fetch ettiği kategoriden türetir.

7. Render edin ve satın alın

  • /categories/lighting → grid. Bir ürüne tıklayın → detay + Sepete ekle. /cart → Öde.
  • Ödeme Stripe barındırmalı checkout’a yönlendirir. Test kartı 4242 4242 4242 4242, herhangi bir gelecek tarihli son kullanma/CVC kullanın. /cart?status=success adresine dönersiniz ve stripe listen çıktısında checkout.session.completed görürsünüz.

Render edilmiş bir ürün sayfası — galeri, fiyat ve Sepete ekle butonu.

Sepet — satır öğeleri ve tek bir Stripe ile Öde butonu.

Yalnızca fiyatı eklenmiş öğeler satın alınabilir — 6. adımda fiyatladığınız ~3 üründen birini satın alın.

İsteğe bağlı — uluslararasılaştırma. Her bileşeni çevirin (aynı anda 35 dil), dahili language Sistem bileşenine eşlenen bir /{language}/… segmenti ekleyin ve CEL ile bağlı alanları documents.translated olarak değiştirin. Bkz. Havalimanı dizini rehberi, Bölüm 2 adım 7.

Bölüm 3 — Üretim

1. Yayınlayın: GitHub, ardından Vercel

git init && git add -A && git commit -m "Stripe storefront"
gh repo create store --private --source=. --push   # --public da olabilir

Build komutu: generated/cms-schemas.ts git tarafından izlenmez, bu yüzden build’in yeniden üretmesini sağlayın — vercel.json ekleyin:

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

Vercel’de: Add New → Project, store repo’sunu içe aktarın ve çevre değişkenlerini ekleyin — PROFOUND_API_KEY, NEXT_PUBLIC_PROFOUND_WEBSITE_ID, NEXT_PUBLIC_CMS_API_URL, NEXT_PUBLIC_BUNNY_CDN_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (aşağıdaki dağıtılmış endpoint değeri) ve NEXT_PUBLIC_SITE_URL (prod URL’niz). Deploy edin.

Ardından dağıtımdaki webhook’u kablolayın (yerel stripe listen sırrı yalnızca yereldi): Stripe → Developers → Webhooks → + Add endpoint → https://<prod>/api/stripe/webhook, etkinlik checkout.session.completed. whsec_… değerini Vercel’e kopyalayın ve yeniden dağıtın.

Eksik env değişkenleri = “yerelde çalışıyor, prod’da boş” — 1 numaralı dağıtım tuzağı. Burada test anahtarlarıyla dağıtıyoruz; gerçek ödemeleri kabul etmeye hazır olduğunuzda STRIPE_SECRET_KEY ve webhook sırrını canlı değerlerinizle değiştirin.

2. Canlı önizleme ve yerinde düzenleme

Her ikisi de iskeletle birlikte gelir.

  • Canlı önizleme: <Refresher>, bir editör yönetici panelinde kaydettiğinde önizlediğiniz sayfayı günceller — yeniden dağıtıma gerek yok. (Editör için önizleme; ziyaretçiler normal yeniden doğrulamada yayınlanmış içeriği görür.)
  • Yerinde düzenleme: herhangi bir URL’ye ?edit_mode=true ekleyin; düzenleme katmanları görünür. Genel ziyaretçiler temiz sayfayı görür.

İskeletin atladığı önizleme rotasını ekleyin. Yönetici önizleme iframe’ini /cms-preview_<path> adresinden yükler; bu rota olmadan her önizleme 404 verir. Ekleyin:

// src/app/cms-preview_/[...slug]/page.tsx
import { ParametricRoutePreviewPage } from "cms-renderer/lib/renderer";
import { registry } from "../../registry";   // registry’nizi paylaşılan bir modüle çıkarın
export default async function Page({ params, searchParams }) {
  const { slug } = await params;
  const PreviewPage = ParametricRoutePreviewPage as any; // async RSC; React 19 tipleri
  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} />;
}

Segment kökü için src/app/cms-preview_/page.tsx dosyasını da ekleyin (aynı, slug: []).

İnşa bu kadar

İçerik odaklı bir Stripe mağazası: bir CMS kataloğu, tek bir rota setinden liste + detay sayfaları ve çalışan bir barındırmalı checkout. Yapay zekâ kataloğu tohumladı, tasarımı bağladı ve katalog okuyucusu + bileşenleri + başsız sepeti yazdı; siz bileşenleri, Stripe fiyat bağlantılarını, üç rotayı, CEL kromunu ve üç kısa Stripe dosyasını yaptınız. CEL kromu bağlar; bileşenler kataloğu fetch eder. Ve Stripe küçük kaldı — bir sessions.create çağrısı ve bir imzalı webhook, alışveriş yapan kişi Stripe’ın kendi sayfasında ödedi.

Continue Reading
Previous‹Dağıtımlar