profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Tutorials

Build & Ship an Airport DirectoryDeploymentsBuild & 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

En praktisk genomgång: bygg en innehållsdriven Stripe-butik på Profound CMS — en katalog som en handlare redigerar utan kod, två parametriska rutter, en headless-varukorg och Stripe-hosterad checkout.

Den färdiga butiken i rörelse — bläddra i en kategori, öppna en produkt, lägg i varukorg, checka ut.

En praktisk genomgång som bygger en innehållsdriven butik på Profound CMS: en produktkatalog (kategorier + artiklar) modellerad i CMS:et, list- och detaljsidor från ett och samma ruttnät, och en Stripe-hosterad kassa levererad som en headless-komponent.

Ryggraden är handskriven Next.js plus Profound-admin. Claude Code (via Profounds MCP) gör det tunga arbetet i tre uppgifter – sår in katalogen, kopplar in designsystemet och skriver butiksfrontskomponenterna (inklusive den headless-varukorgen). Tre delar: Setup, Build, Production.

Betalningar på en rad. Vi använder Stripe-hosterad Checkout: kunden betalar på Stripes sida, inte din. Din app gör bara två saker på serversidan – skapar en Checkout Session och verifierar en webhook. Inga kortfält, inga Stripe Elements, ingen PCI-börda.

Vad du kommer att bygga

  • En liten publicerad katalog i CMS:et – tre kategorier och åtta produkter (demot "Edison's Inventions") – alla redigerbara av en handlare utan kod.
  • Två parametriska rutter (/products/{item_code}, /categories/{category_code}) plus en statisk /cart, allt från en uppsättning komponenter.
  • En headless-varukorg (useCart) och Stripe-hosterad Checkout, där priset alltid löses på serversidan från ett Stripe Price ID.
  • Butiken distribuerad till Vercel med liveförhandsvisning och redigering på plats för teamet.

Förutsättningar

  • Bun ≥ 1.3 — curl -fsSL https://bun.sh/install | bash
  • Claude Code med Profound MCP (del 1 installerar den).
  • Ett Profound CMS-konto.
  • Ett Stripe-konto. Den här handledningen körs i testläge så inget drar verkliga pengar medan du bygger – men flödet är identiskt med live-nycklar, så använd gärna dina riktiga kontonycklar om du föredrar det. (Testläge kräver inga företags- eller bankuppgifter.)
  • Stripe CLI (stripe login) för lokala webhooks.
  • För distribution: GitHub CLI (gh) och ett Vercel-konto kopplat till GitHub.

Hur delarna passar ihop

Profound separerar innehåll från rendering:

  • Komponenter definierar innehållets form. En Custom Component med ett fält för Route Slug är routbar (category, item); en taggad UI Element går att placera på en sida (nav, product_grid, …).
  • Dokument är innehållet (en produkt, en kategori).
  • UI-element är sidosektioner; varje skalärt fält tar ett statiskt värde eller ett CEL-uttryck som utvärderas vid rendering.
  • Parametriska rutter mappar en URL till ett dokument + UI-element och skickar vidare ruttparametrar (meta.params.* i CEL, routeParams i React).
  • Din Next.js-app läser den via cms-renderer; Stripe läggs till som vanliga API-rutter.

Den enda regeln som formar bygget: CEL bindar endast string/number-fält. Så skalär krom (nav-varumärke, sidfot, rubriker) binds med CEL, medan allt som är rikt eller en samling (ett produktgalleri, en bildkarusell, rich text) hämtas inne i React-komponenten via ruttparam. Och Stripe är prisets sanning – CMS-fältet price är endast för visning; debiteringen löses alltid på serversidan från ett Stripe Price ID.

Del 1 — Setup

Slutläge: en liten publicerad katalog, appen kopplad för att läsa den, Stripe installerat, design på plats – inget renderat ännu.

1. Registrera dig och skapa webbplatsen

Registrera dig hos Profound (WorkOS-auth). Skapa en webbplats med namnet store, kopiera sedan dess webbplats-ID (UUID:t i admin-URL:en) och en API-nyckel på read-nivå (Deployments → Create API key). Appen läser bara; katalogseedningen sker senare via MCP:n, som autentiserar separat.

2. Skapa appens skelett, koppla den och lägg till Stripe

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

Skelettet är ett Next.js App Router-projekt förkopplat för Profound (cms-renderer-SDK:n, en catch-all-rutt, ett generate-schemas-skript, en <Refresher>). Det levereras utan styling. bun add stripe hämtar server-SDK:n – det enda betalningsberoende som hosted checkout behöver.

Lägg till dina värden i .env.local:

# CMS
PROFOUND_API_KEY=<din read-nyckel>
NEXT_PUBLIC_PROFOUND_WEBSITE_ID=<ditt webbplats-id>
NEXT_PUBLIC_CMS_API_URL=https://cms.dev.tryprofound.com
NEXT_PUBLIC_BUNNY_CDN_URL=https://cms-profound.b-cdn.net   # serverar CMS-hostade bilder

# Stripe
STRIPE_SECRET_KEY=sk_test_...            # testnyckel här; byt till din live-nyckel när du går live
STRIPE_WEBHOOK_SECRET=whsec_...          # fylls i i Build-steg 4
NEXT_PUBLIC_SITE_URL=http://localhost:3000

Hämta STRIPE_SECRET_KEY från Stripe → Developers → API keys. Vi använder en testnyckel (sk_test_…) så bygget aldrig flyttar riktiga pengar; växla till din live-nyckel när du är redo att ta emot verkliga betalningar. Kör bun dev och öppna localhost:3000 – startern renderas.

Hosted checkout omdirigerar webbläsaren till en Stripe-URL, så serverns hemliga nyckel är allt Stripe behöver – ingen publishable key, inget klient-SDK för Stripe.

3. Definiera komponenterna category, product_image och item

Skapa tre Custom Components (Components → Create new component) – datakällan, så ingen UI Element-tag. Sätt var och en till Active.

CMS:et har inget fält för "array av bild", så ett galleri är en array av referenser till en liten product_image-komponent. Skapa category och product_image (och sätt dem till Active) innan item – ett referensfält kan bara peka mot Active-komponenter.

  • 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 av referenser → product_image), price (Number, cent – endast visning), currency (Select, usd), stripePriceId (Text), category (Reference → category), active (Boolean)

Lämna alla fält valfria. Adminen gör fältnamn i lower_snake_case ("Stripe Price Id" → stripe_price_id) – det är det din kod använder, så läs tillbaka de riktiga namnen via generate-schemas senare. Vi kallar det routbara handtaget code (inte slug): det är Route Slug och nyckeln för en ren documents.getByCode-uppslagning senare.

Komponenten item – code som Route Slug, images som referenser till product_image, plus stripePriceId och en category-referens.

4. Hämta ner komponenterna till lokala typer

bun run generate-schemas

Skriver Zod-scheman + typer till generated/cms-schemas.ts (categorySchema/Category, itemSchema/Item). Dubbel funktion som anslutningskontroll – felaktiga referenser misslyckas här.

5. Så katalogen via Profound MCP

Installera och autentisera MCP:n en gång:

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

Kör mcp__Profound__authenticate, slutför WorkOS-flödet och instruera sedan Claude:

Generera en liten e-handelskatalog för en butik som heter Edison's Inventions — tre kategorier och dessa produkter, med en kort tidskorrekt description för var och en, ett price i cent, currency: "usd" och active: true:

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

Varje kategori behöver ett name och den gemena code; varje artikel behöver ett name, den gemena code, description, price (i cent), currency och active. Spara det till data/catalog.json och validera mot våra category- och item-komponenter. Använd sedan Profound MCP för att skapa varje som ett publicerat dokument: skapa kategorierna först, fånga deras ID:n och skapa sedan artiklarna med category satt till en referens — { "_type": "reference", "_ref": "<category-id>", "_schema": "category" }. Lämna stripePriceId tomt än så länge. Kör artiklarna parallellt.

Claude skriver data/catalog.json, validerar den och fläktar ut parallella create_document-anrop (status: "published"). Så in kategorier innan artiklar så referenserna pekar på ID:n som redan finns.

De tre seedade kategorierna, publicerade och Live.

De åtta seedade produkterna, var och en kopplad till en kategori.

6. Skapa Stripe-priser och koppla några produkter

Katalogen ligger i CMS:et; ge nu några produkter ett riktigt Stripe-pris – handlarens uppgift, gjord i två adminpaneler, utan kod:

  1. Stripe Dashboard → Products → + Add product, sätt ett engångspris, kopiera Price ID (price_…).
  2. Gör detta för cirka tre huvudprodukter (t.ex. Lightbulb, Phonograph, Kinetoscope).
  3. Profound-admin → item → Documents → klistra in varje Price ID i stripePriceId, spara.

CMS:et håller katalogen; Stripe håller referenspriset; länken är en sträng som handlaren klistrar in. (Föredrar du att automatisera det? Den officiella Stripe MCP kan skapa Products/Prices åt dig – klistra in de returnerade ID:n på samma sätt.)

7. Lägg in designsystemet och koppla det med AI

Skelettet levereras utan styling. Lägg en DESIGN.md (ett Tailwind v4-@theme-block + tokens) i projektroten – ditt eget, eller hämta ett från refero.design. Ge sedan Claude en prompt, begränsad till styling:

Läs designfilen jag just lade till. Sätt upp Tailwind om det behövs, koppla in temat och typsnitten så att stylingen fungerar. Använd next/font för typsnitt – hämta dem inte från Google vid körning. Endast styling – bygg inga sidor eller komponenter ännu.

Kontrollera att src/app/globals.css innehåller @import "tailwindcss"; + @theme-blocket och att localhost:3000 visar tokenserna. Håll prompten snäv (är den öppen bygger en agent en hel hemsida), och läs in typsnitt via next/font, aldrig en runtime-import från Google.

8. Lägg till produktbilder (valfritt)

Valfritt – du kan nå en fungerande checkout utan bilder. För att lägga till dem: skapa ett product_image-dokument per bild (ladda upp i dess image-fält), referera sedan dem från produktens images-array. Ta med egna produktfoton eller generera en sammanhängande uppsättning med en bildmodell (låt Claude ta fram varumärkesanpassade prompts från DESIGN.md och lås en Midjourney---sref så varje bild matchar).

Det fristående cms-renderer har ingen hjälpfunktion för bild-URL:er, så leverera buildAssetUrl i src/lib/image.ts (~40 rader) – den prefixar NEXT_PUBLIC_BUNNY_CDN_URL och lägger till filändelsen. Komponenterna i Build-steg 3 använder den.

Del 2 — Build

Bygg renderingslagret och checkouten så att det slutar i ett riktigt testläge-köp.

1. Definiera de fem UI-elementkomponenterna

Fem komponenter, alla Active och taggade som UI Element (Settings → Tags), inga Route Slugs:

  • nav → brand · product_grid → heading · product_detail → heading · cart_summary → heading · footer → text (alla Text)

Taggen UI Element gör att en komponent visas i Page Builders lista Add UI Element – Active räcker inte. Varje fält är ett skalärt (den typ CEL binder); själva katalogdatan är inte ett fält här – ProductGrid/ProductDetail hämtar den via ruttparam (steg 3).

2. Generera typerna igen

bun run generate-schemas

3. Generera katalogläsaren, komponenterna och headless-varukorgen

En prompt bygger läshjälpen, de fem komponenterna, varukorgen och registret:

Bygg vår butiksfront i src/, med Profounds cms-renderer-SDK.

src/lib/catalog.ts — en serverside-läsare för CMS. Skapa en klient med getCmsClient({ cmsUrl: process.env.NEXT_PUBLIC_CMS_API_URL!, apiKey: process.env.PROFOUND_API_KEY, websiteId: process.env.NEXT_PUBLIC_PROFOUND_WEBSITE_ID! }) från cms-renderer/lib/cms-api. Exportera getItemByCode(code) → cms.documents.getByCode.query({ websiteId, schemaName: "item", code }) som returnerar res.document.published_content. Exportera listItems(categoryCode?) → cms.documents.list.query({ websiteId, schemaName: "item", status: "published", limit: 100 }), mappa res.documents till .published_content, filtrera active !== false och, om categoryCode ges, behåll artiklar vars category._ref matchar kategorins document.id. Exportera resolveImages(refs) som löser varje item.images-referens via cms.documents.get.query({ websiteId, id: ref._ref }) och gör om dess bildfält till en URL med den levererade buildAssetUrl (del 1 steg 8).

src/components/ — fem UI-elementkomponenter registrerade i catch-all-ruttens register efter komponentnamn, snake_case för att matcha admin: { nav, product_grid, product_detail, cart_summary, footer }. Nav och Footer läser sina skalfält från prop:en content (typad BlockComponentProps<T> från cms-renderer/lib/types). ProductGrid och ProductDetail är asynkrona serverkomponenter som läser routeParams och hämtar från catalog.ts: routeParams.<param> är { value, … } — läs .value, så ProductGrid anropar listItems(routeParams.category_code?.value) (kort länkar till /products/{code}) och ProductDetail anropar getItemByCode(routeParams.item_code?.value) (galleri via resolveImages, rich text-beskrivning, pris, Lägg i varukorg). CartSummary renderar varukorgen från useCart med en Pay-knapp. Behåll formatPrice i ett rent src/lib/format.ts så klientkomponenter inte importerar serverendast catalog.ts.

src/components/AddToCartButton.tsx — en "use client"-knapp som tar { code, name, priceLabel } och anropar useCart().addItem({ code, name, priceLabel, quantity: 1 }). Använd den i ProductDetail.

src/lib/useCart.ts — en headless-varukorg: rader { code, name, priceLabel, quantity } i state, persisterade till localStorage, som exponerar addItem/removeItem/updateQty/subtotal och en checkout() som POST:ar { lines: [{ code, quantity }] } (endast koder och kvantiteter — aldrig priser) till /api/stripe/checkout, och omdirigerar sedan till den returnerade url.

Styla allt med vårt designsystem, som våra egna komponenter — kopiera inte källsajtens layout.

Tre saker att känna till när det är klart:

  • Skalärkrom kommer in via content ({ content }: BlockComponentProps<T>) – destrukturera fält som topplistan props och blocket renderas tomt. Katalogdata kommer från routeParams + en catalog.ts-hämtning, eftersom CEL inte kan binda listor eller gallerier. Varukorgen bär artikelkoder, aldrig priser.
  • routeParams.<param> är { value, schemaName, document } – läs .value. Läsningar returnerar published_content, inte .content. Registernycklar är snake_case för att matcha admin.
  • Uppgradera @types/react/@types/react-dom till v19 – skelettet levereras med v18, vilket bryter asynkrona serverkomponentblock mot React 19.

4. Skriv Stripe-serverkoden (ryggraden)

Tre korta serverfiler – den enda betalningskoden i appen. De återanvänder getItemByCode, så debiteringen löses på serversidan.

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 — lös varje artikel från CMS:et, debitera Stripes pris:

import { NextResponse } from "next/server";
import { stripe } from "@/lib/stripe";
import { getItemByCode } from "@/lib/catalog"; // server-side, read-tier-nyckel

export async function POST(req: Request) {
  const { lines } = await req.json();                // [{ code, quantity }] — inga priser från klienten
  const line_items = await Promise.all(
    lines.map(async ({ code, quantity }: { code: string; quantity: number }) => {
      const item = await getItemByCode(code);          // servern löser från CMS:et
      return { price: item!.stripe_price_id, quantity }; // pris från CMS, aldrig klient
    })
  );
  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 });     // klienten omdirigerar hit
}

src/app/api/stripe/webhook/route.ts — den betrodda uppfyllnadssignalen:

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

export async function POST(req: Request) {
  const body = await req.text();                      // RÅ-kropp — krävs för signaturverifiering
  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") {
    // uppfyll: registrera ordern / skicka kvitto.
  }
  return new Response(null, { status: 200 });
}

Obligatorisk skelettfix: skelettets src/proxy.ts vidarebefordrar varje /api/* till CMS:et, så dina Stripe-rutter körs aldrig. Låt dem passera först:

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();                       // hantera lokalt
  }
  return cmsProxy(request as unknown as Parameters<typeof cmsProxy>[0]);
};
// behåll skelettets `export const config = { matcher: [...] }` oförändrat

Kontrollera: curl -X POST localhost:3000/api/stripe/webhook -d x returnerar Bad signature.

Kör Stripe CLI för lokala webhooks:

stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhook
# kopiera whsec_... till STRIPE_WEBHOOK_SECRET, starta om bun dev

whsec_… är per session. Två regler bär säkerheten: checkout härleder priset från CMS:et med code (en manipulerad varukorg kan inte ändra det), och webhooken verifierar signaturen mot den råa kroppen.

5. Skapa rutterna

Admin → Pages → Create page, tre gånger. Mappa varje parametrar till sin komponent (slug-fält code):

  1. /products/{item_code} → item
  2. /categories/{category_code} → category
  3. /cart — en statisk sida (skriv in bokstavligen /cart, inte /{cart})

6. Lägg till UI-element, koppla CEL, publicera

För varje rutt: Page Builder → Add UI Element → Custom → lägg till komponenter i ordning, fyll i skalära fält (statiskt värde eller CEL), Publiser.

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

Ställ in nav.brand och footer.text på statiska strängar; rubrikerna på statiska etiketter.

Page Builder på kategorirutten – elementet product_grid markerat, dess heading bunden via CEL.

Page Builder på produktrutten – elementet product_detail på en produktbinding.

Parametrisk Page Builder-fallgrop: på de två parametriska rutterna sparas inte tillagda UI-element (blocken blir föräldralösa och sidan renderas tom). Tills det är fixat, koppla de sidornas block_ids direkt via Profound MCP update_page, publicera sedan. (Den statiska /cart kopplas normalt.) Av samma anledning hämtar ProductGrid sin heading från kategorin den hämtar istället för via CEL.

7. Rendera och köp

  • /categories/lighting → gallret. Klicka på en produkt → detaljvy + Lägg i varukorg. /cart → Betala.
  • Betala omdirigerar till Stripe-hosterad checkout. Använd testkortet 4242 4242 4242 4242, valfri framtida utgång/CVC. Du återvänder till /cart?status=success, och stripe listen visar checkout.session.completed.

En renderad produktsida – galleri, pris och Lägg i varukorg.

Varukorgen – orderrader och en enda Betala med Stripe-knapp.

Endast prissatta produkter går att köpa – köp en av de cirka tre du prissatte i steg 6.

Valfritt – internationalisera. Översätt varje komponent (alla 35 språk på en gång), lägg till ett /{language}/…-segment mappat till den inbyggda systemkomponenten language, och byt CEL-bindda fält till documents.translated. Se handledningen för flygplatskatalogen, del 2 steg 7.

Del 3 — Production

1. Skicka ut den: GitHub, sedan Vercel

git init && git add -A && git commit -m "Stripe storefront"
gh repo create store --private --source=. --push   # --public går också bra

Byggkommando: generated/cms-schemas.ts är gitignored, så lås byggprocessen till att återskapa den – lägg till vercel.json:

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

I Vercel: Add New → Project, importera store och lägg till miljövariablerna – PROFOUND_API_KEY, NEXT_PUBLIC_PROFOUND_WEBSITE_ID, NEXT_PUBLIC_CMS_API_URL, NEXT_PUBLIC_BUNNY_CDN_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (värdet för den distribuerade slutpunkten, nedan) och NEXT_PUBLIC_SITE_URL (din prod-URL). Distribuera.

Koppla sedan den distribuerade webhooken (det lokala stripe listen-sekretet var bara för lokalt bruk): Stripe → Developers → Webhooks → + Add endpoint → https://<prod>/api/stripe/webhook, event checkout.session.completed. Kopiera dess whsec_… till Vercel och distribuera om.

Saknade miljövariabler = "fungerar lokalt, tomt i produktion" – vanligaste distributionsfällan. Vi distribuerar med testnycklar här; byt STRIPE_SECRET_KEY och webhooksekretet till dina live-värden när du är redo att ta emot riktiga betalningar.

2. Liveförhandsvisning och redigering på plats

Båda levereras med skelettet.

  • Liveförhandsvisning: <Refresher> uppdaterar sidan du förhandsgranskar när en redaktör sparar i admin – ingen omdistribution. (Det är en förhandsvisning för redaktören; besökare ser publicerat innehåll på normal revalidering.)
  • Redigering på plats: lägg till ?edit_mode=true i valfri URL för redigeringsöverlagringar. Offentliga besökare får den rena sidan.

Lägg till förhandsgranskningsrutten som skelettet utelämnar. Adminen laddar sin förhandsgransknings-iframe på /cms-preview_<path>; utan den rutten får varje förhandsgranskning 404. Lägg till den:

// src/app/cms-preview_/[...slug]/page.tsx
import { ParametricRoutePreviewPage } from "cms-renderer/lib/renderer";
import { registry } from "../../registry";   // extrahera ditt register till en delad modul
export default async function Page({ params, searchParams }) {
  const { slug } = await params;
  const PreviewPage = ParametricRoutePreviewPage as any; // async RSC; React 19-typer
  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} />;
}

Lägg till src/app/cms-preview_/page.tsx också (samma, slug: []) för segmentroten.

Det var bygget

En innehållsdriven Stripe-butik: en CMS-katalog, list- + detaljsidor från ett ruttnät och en fungerande hosted checkout. AI seedade katalogen, kopplade designen och skrev katalogläsaren + komponenterna + headless-varukorgen; du gjorde komponenterna, Stripe-prisernas länkar, de tre rutterna, CEL-kromen och tre korta Stripe-filer. CEL binder kromet; komponenterna hämtar katalogen. Och Stripe hölls liten – ett anrop till sessions.create och en signerad webhook, med kunden som betalar på Stripes egen sida.

Continue Reading
Previous‹Deployments