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.
/products/{item_code}, /categories/{category_code}) artı statik /cart, hepsi tek bir bileşen setinden.useCart) ve Stripe barındırmalı ödeme, fiyat her zaman sunucu tarafında bir Stripe Fiyat Kimliği’nden çözülür.curl -fsSL https://bun.sh/install | bashstripe login).gh) ve GitHub’a bağlı bir Vercel hesabı.Profound içeriği render’dan ayırır:
category, item); UI Element etiketi olan bir bileşen bir sayfaya yerleştirilebilir (nav, product_grid, …).meta.params.* CEL’de, routeParams React’te) geçirir.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.
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.
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.
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.
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ı.
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.
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 cinsindenprice,currency: "usd"veactive: 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
nameve bu küçük harfcode’a ihtiyaç duyar; her itemname, bu küçük harfcode,description, (sent cinsinden)price,currencyveactivealanlarına sahip olmalıdır. Bunudata/catalog.jsondosyasına kaydet vecategoryileitembileş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 öğelericategoryalanı{ "_type": "reference", "_ref": "<category-id>", "_schema": "category" }olacak şekilde oluştur.stripePriceIdalanı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ı.
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:
price_…) kopyalayın.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.)
İ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/fontkullan — ç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.
İ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-rendererbir görsel URL yardımcı fonksiyonuna sahip değildir, bu yüzdenbuildAssetUrlfonksiyonunusrc/lib/image.tsdosyasına ekleyin (~40 satır) —NEXT_PUBLIC_BUNNY_CDN_URLile öne ekler ve uzantıyı ekler. 2. bölüm 3. adımdaki bileşenler bunu kullanır.
Renderer katmanını ve checkout’u inşa edin, test modunda gerçek bir satın alma ile bitirin.
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).
bun run generate-schemas
Tek bir prompt, okuma yardımcısını, beş bileşeni, sepeti ve registry’i oluşturur:
Profound
cms-rendererSDK’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-apiiçerisindekigetCmsClient({ 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önenres.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.documentsdeğerini.published_content'e eşle,active !== falseolanları filtrele vecategoryCodeverilmişse,category._refdeğeri kategorinindocument.id'sine eşit olan öğeleri tut.resolveImages(refs)fonksiyonunu dışa aktar; heritem.imagesreferansınıcms.documents.get.query({ websiteId, id: ref._ref })ile çözer ve görsel alanını vendoredbuildAssetUrl(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 }.NavveFooter, skaler alanlarınıcontentprop’undan okur (cms-renderer/lib/typesiçindekiBlockComponentProps<T>tipinde).ProductGridveProductDetailasync sunucu bileşenleri oluprouteParams’ı okur vecatalog.tsdosyasından fetch eder:routeParams.<param>değeri{ value, … }—.value’ı oku, böyleceProductGridlistItems(routeParams.category_code?.value)çağırır (kartlar/products/{code}bağlantısı verir) veProductDetailgetItemByCode(routeParams.item_code?.value)çağırır (galeriresolveImagesaracılığıyla, zengin metin açıklaması, fiyat, Sepete ekle).CartSummary,useCart’tan gelen sepeti Ödeme butonuyla render eder.formatPricefonksiyonunu saltsrc/lib/format.tsdosyasında tut ki istemci bileşenleri sunucuya özelcatalog.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. BunuProductDetailiç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/subtotalve/api/stripe/checkoutrotasına{ lines: [{ code, quantity }] }(yalnızca kodlar ve adetler — asla fiyatlar değil) POST eden ve dönenurl'ye yönlendirencheckout()sunar.Her şeyi tasarım sistemimizle stillendir, kendi bileşenlerimiz gibi — kaynak sitenin düzenini kopyalama.
Çalıştıktan sonra bilmeniz gereken üç şey:
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.Üç 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.tsdosyası 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ştirmeyinDoğrulayın:
curl -X POST localhost:3000/api/stripe/webhook -d xBad signaturedö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.
Yönetici → Pages → Üç kez Create page. Her parametreyi bileşenine eşleyin (slug alanı code):
/products/{item_code} → item/categories/{category_code} → category/cart — statik bir sayfa (kelimesi kelimesine /cart yazın, /{cart} değil)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, footernav.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_idsdeğerlerini Profound MCPupdate_pagearacılığıyla doğrudan bağlayın, ardından yayınlayın. (Statik/cartnormal şekilde bağlanır.) Aynı nedenle,ProductGridbaşlığını CEL yerine fetch ettiği kategoriden türetir.
/categories/lighting → grid. Bir ürüne tıklayın → detay + Sepete ekle. /cart → Öde./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
languageSistem bileşenine eşlenen bir/{language}/…segmenti ekleyin ve CEL ile bağlı alanlarıdocuments.translatedolarak değiştirin. Bkz. Havalimanı dizini rehberi, Bölüm 2 adım 7.
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.tsgit tarafından izlenmez, bu yüzden build’in yeniden üretmesini sağlayın —vercel.jsonekleyin:{ "$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.
Her ikisi de iskeletle birlikte gelir.
<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.)?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.tsxdosyasını da ekleyin (aynı,slug: []).
İç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.