Skip to main content

Documentation Index

Fetch the complete documentation index at: https://kardow.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

The CMS becomes a marketplace primitive when you wire it to a payment plan with purpose: 'cms_item'. The fulfillment pipeline runs automatically: once the buyer pays, the item is created (or queued for review) without any custom webhook code.

1. Create the plan

From the dashboard, create a payment_plan and set:
FieldValue
purposecms_item
fulfillment{ "collection": "sponsors", "duration_days": 30, "moderation": "auto" }
providerstripe (embedded checkout) or invoice (custom redirect link)

2. Show a checkout button on your site

import { platform } from '@/lib/platform';

async function buy() {
  const result = await platform.cms.submit('sponsors', {
    data: form.values,
    payment_plan_id: 42,
    return_url: window.location.href,
  });

  if (result.status === 'checkout' && result.mode === 'embedded') {
    // mount Stripe embedded checkout with result.clientSecret
  } else if (result.status === 'checkout' && result.mode === 'redirect') {
    window.location.href = result.redirectUrl;
  }
}

3. What happens behind the scenes

  1. The buyerโ€™s form data is stashed in cms_pending_submissions.
  2. They are sent to checkout (Stripe embedded or custom redirect).
  3. On payment success, the Stripe webhook calls the unified fulfillment dispatcher, which:
    • reads the pending submission,
    • validates it against the collection schema,
    • inserts a cms_item with source = 'payment' and expires_at based on duration_days,
    • emits a purchase.fulfilled event.
If moderation is set to manual, the new item is created with status = 'pending_review' and a dashboard notification fires. Otherwise it goes live immediately.