diff --git a/.github/workflows/docs-deploy-main.yml b/.github/workflows/docs-deploy-main.yml
index 268dd23c..7b8ccacc 100644
--- a/.github/workflows/docs-deploy-main.yml
+++ b/.github/workflows/docs-deploy-main.yml
@@ -111,7 +111,7 @@ jobs:
run: |
set -e
bun run build
- bunx opennextjs-cloudflare build --config wrangler.jsonc -- --skipNextBuild
+ ./node_modules/.bin/opennextjs-cloudflare build --config wrangler.jsonc -- --skipNextBuild
- name: Create GitHub Deployment
id: create_deployment
@@ -125,7 +125,7 @@ jobs:
id: deploy
run: |
set -e
- OUTPUT=$(bunx opennextjs-cloudflare deploy --config wrangler.jsonc)
+ OUTPUT=$(./node_modules/.bin/opennextjs-cloudflare deploy --config wrangler.jsonc)
echo "$OUTPUT"
# Extract deployment URL if available
DEPLOYMENT_URL=$(echo "$OUTPUT" | grep -oE 'https://[^ ]+' | head -1)
diff --git a/.github/workflows/docs-deploy-pr.yml b/.github/workflows/docs-deploy-pr.yml
index 66b11c50..c95acb22 100644
--- a/.github/workflows/docs-deploy-pr.yml
+++ b/.github/workflows/docs-deploy-pr.yml
@@ -432,7 +432,7 @@ jobs:
run: |
set -e
bun run build
- bunx opennextjs-cloudflare build --config wrangler.jsonc -- --skipNextBuild
+ ./node_modules/.bin/opennextjs-cloudflare build --config wrangler.jsonc -- --skipNextBuild
OUTPUT=$(npx wrangler@4.34.0 --config wrangler.jsonc versions upload --name ${CF_STAGING_WORKER_NAME} --preview-alias pr-$PR)
echo "$OUTPUT"
# Extract deployment URL
diff --git a/content/docs/web-checkout/meta.json b/content/docs/web-checkout/meta.json
index 22118f3a..5e16c61a 100644
--- a/content/docs/web-checkout/meta.json
+++ b/content/docs/web-checkout/meta.json
@@ -12,6 +12,7 @@
"web-checkout-creating-campaigns-to-show-paywalls",
"---Implementation---",
+ "web-checkout-sdk-setup",
"web-checkout-direct-stripe-checkout",
"web-checkout-testing-purchases",
"web-checkout-managing-memberships",
diff --git a/content/docs/web-checkout/web-checkout-sdk-setup.mdx b/content/docs/web-checkout/web-checkout-sdk-setup.mdx
new file mode 100644
index 00000000..bb19606e
--- /dev/null
+++ b/content/docs/web-checkout/web-checkout-sdk-setup.mdx
@@ -0,0 +1,39 @@
+---
+title: "SDK Setup"
+description: "Platform-specific setup guides for Web Checkout implementation"
+---
+
+Choose your platform below to get started with Web Checkout in your app:
+
+
+
+ Setup Web Checkout for iOS apps with Swift
+
+
+ Setup Web Checkout for Android apps with Kotlin/Java
+
+
+ Setup Web Checkout for Flutter apps
+
+
+ Setup Web Checkout for Expo apps
+
+
+
+## What's Next?
+
+After setting up Web Checkout for your platform:
+
+1. **Configure Deep Links**: Each platform requires deep link setup to redirect users back to your app after purchase
+2. **Handle Redemption**: Implement delegate methods to handle purchase redemption
+3. **Test Your Integration**: Use test mode to verify your implementation before going live
+
+## Platform-Specific Features
+
+Each SDK provides platform-specific features for Web Checkout:
+
+- **Post-Checkout Redirecting**: Handle users returning to your app after purchase
+- **Using RevenueCat**: Integrate Web Checkout with RevenueCat for subscription management
+- **Linking Membership**: Connect web purchases to in-app subscriptions
+
+Visit your platform's guide above to learn more about these features and implementation details.
diff --git a/src/mdx-components.tsx b/src/mdx-components.tsx
index 6f1f9043..38f73abb 100644
--- a/src/mdx-components.tsx
+++ b/src/mdx-components.tsx
@@ -123,6 +123,48 @@ const Check = ({ children }: { children: React.ReactNode }) => {
)
}
+const ApplePlatformIcon = (props: React.SVGProps) => (
+
+)
+
+const AndroidPlatformIcon = (props: React.SVGProps) => (
+
+)
+
+const FlutterPlatformIcon = (props: React.SVGProps) => (
+
+)
+
+const ExpoPlatformIcon = (props: React.SVGProps) => (
+
+)
+
+const PLATFORM_ICONS = {
+ apple: ApplePlatformIcon,
+ android: AndroidPlatformIcon,
+ flutter: FlutterPlatformIcon,
+ expo: ExpoPlatformIcon,
+} as const
+
+const toPascalCase = (value: string) =>
+ value
+ .split(/[-_\s]+/)
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
+ .join('')
+
const Card = ({
title,
icon,
@@ -141,18 +183,27 @@ const Card = ({
if (icon) {
if (typeof icon === 'string') {
- const LucideIcon =
- (Lucide as Record)[
- icon.charAt(0).toUpperCase() + icon.slice(1)
- ];
- if (LucideIcon) {
- RenderedIcon = (
-
- );
+ const normalized = icon.trim().toLowerCase()
+ const PlatformIcon = PLATFORM_ICONS[normalized as keyof typeof PLATFORM_ICONS]
+
+ if (PlatformIcon) {
+ RenderedIcon =
+ } else {
+ const lucideIcons = Lucide as Record
+ const LucideIcon =
+ lucideIcons[icon] ??
+ lucideIcons[icon.charAt(0).toUpperCase() + icon.slice(1)] ??
+ lucideIcons[toPascalCase(icon)]
+
+ if (LucideIcon) {
+ RenderedIcon = (
+
+ )
+ }
}
} else if (React.isValidElement(icon)) {
RenderedIcon = React.cloneElement(icon as any, {