HStack, VStack, Grid), relative positioning (position: { below, rightOf, inside }), variables ($varName), and named styles. The hand-computed x/y values in the steps below still work, but the same diagram can be expressed more concisely. See the v2 power features reference, and the modernized version at the bottom of this tutorial.
What You'll Build
In this tutorial, you'll create a comprehensive e-commerce checkout flow diagram that covers the entire purchase journey from cart to confirmation. This diagram is perfect for:
- Product documentation for payment systems
- Developer onboarding for checkout integrations
- Stakeholder presentations on payment flows
- UX documentation for checkout optimization
Understanding the Flow
Our checkout flow has several key stages and decision points:
| Stage | Color | Purpose |
|---|---|---|
| Start | Green | Cart ready - user initiates checkout |
| Inventory Check | Blue | Validate stock availability |
| Decision Points | Amber | Branch logic (in stock? 3D Secure?) |
| Shipping Info | Purple | Collect and validate address |
| Payment Gateway | Cyan | Stripe, PayPal, or Razorpay |
| Success/Error | Green/Red | Order confirmation or failure |
Design Pattern: Decision Diamonds
Use diamond shapes for all Yes/No decision points. Color the "Yes" arrows green and "No" arrows red for instant visual clarity.
Step 1: Create the Start Node
Checkout flows traditionally start with an ellipse (oval) shape. This signals to readers that this is an entry point.
Add the Cart Ready Ellipse
{
"id": "start",
"type": "ellipse",
"x": 80,
"y": 150,
"w": 120,
"h": 60,
"options": {
"stroke": "green.500",
"fill": "green.100",
"fillStyle": "solid"
}
},
{
"id": "start-label",
"type": "text",
"x": 80,
"y": 170,
"w": 120,
"h": 24,
"text": "๐๏ธ Cart Ready",
"fontSize": 14,
"fontWeight": "bold",
"align": "center",
"options": { "stroke": "green.800" }
}
Step 2: Add Decision Diamonds
Decision points use diamond shapes. The "In Stock?" check is critical for e-commerce flows.
Create the Inventory Check Diamond
{
"id": "diamond-stock",
"type": "diamond",
"x": 310,
"y": 260,
"w": 80,
"h": 60,
"options": {
"stroke": "amber.500",
"fill": "amber.100",
"fillStyle": "solid"
}
},
{
"id": "diamond-stock-label",
"type": "text",
"x": 310,
"y": 278,
"w": 80,
"h": 18,
"text": "In Stock?",
"fontSize": 11,
"align": "center",
"options": { "stroke": "amber.800" }
}
Step 3: Branch with Yes/No Arrows
Connect your decision diamond to the next steps. Use colors to show the happy path (green) vs error path (red).
Create Branching Arrows
// "Yes" arrow (green) - pointing right to continue flow { "id": "arrow-yes", "type": "arrow", "x": 389, "y": 290, "w": 66, "h": 0, "endArrowhead": "arrow", "options": { "stroke": "green.500" } } // "No" arrow (red) - pointing left to error state { "id": "arrow-no", "type": "arrow", "x": 313, "y": 290, "w": -97, // Negative = points left! "h": 39, "endArrowhead": "arrow", "options": { "stroke": "red.500" } }
Pro tip: Add small text labels ("Yes", "No") near each arrow to make the flow crystal clear.
Arrow Direction Reminder
Negative w values make arrows point left. Negative h values make arrows
point up. Combine both for diagonal arrows.
Step 4: Add Payment Gateway Options
E-commerce flows often offer multiple payment options. Create branching arrows to each gateway.
Create Payment Gateway Cards
// Stripe payment option { "id": "stripe", "type": "rectangle", "x": 330, "y": 520, "w": 120, "h": 60, "borderRadius": 10, "options": { "stroke": "indigo.500", "fill": "indigo.100", "fillStyle": "solid" } }, { "id": "stripe-label", "type": "text", "x": 330, "y": 540, "w": 120, "h": 20, "text": "๐ณ Stripe", "fontSize": 13, "fontWeight": "bold", "align": "center", "options": { "stroke": "indigo.700" } }
Repeat this pattern for PayPal (blue tones) and Razorpay (teal tones), positioning them horizontally or vertically based on your layout.
Step 5: Add Error and Success States
Every good flowchart shows both happy and unhappy paths. Add "Out of Stock" and "Payment Failed" error states in red.
Create Error State Box
{
"id": "error-out-of-stock",
"type": "rectangle",
"x": 74,
"y": 303,
"w": 140,
"h": 60,
"borderRadius": 10,
"options": {
"stroke": "red.500",
"fill": "red.100",
"fillStyle": "solid"
}
},
{
"id": "error-label",
"type": "text",
"x": 74,
"y": 323,
"w": 140,
"h": 20,
"text": "โ Out of Stock",
"fontSize": 13,
"fontWeight": "bold",
"align": "center",
"options": { "stroke": "red.700" }
}
Step 6: Add the Order Confirmation
End the flow with a green "Order Complete" ellipse, mirroring the start node's shape.
Create Success End Node
{
"id": "end-success",
"type": "ellipse",
"x": 990,
"y": 650,
"w": 140,
"h": 70,
"options": {
"stroke": "green.600",
"fill": "green.200",
"fillStyle": "solid"
}
},
{
"id": "end-label",
"type": "text",
"x": 990,
"y": 665,
"w": 140,
"h": 40,
"text": "โ
Order\\nComplete!",
"fontSize": 14,
"fontWeight": "bold",
"align": "center",
"options": { "stroke": "green.800" }
}
Note: Use \\n in your text string to create line breaks.
Key Takeaways
- Start/End nodes โ Use ellipses for entry and exit points
- Decision points โ Use diamonds with Yes/No branches
- Color coding โ Green for success, red for errors, amber for decisions
- Multiple paths โ Show all payment gateway options branching from a single point
- Labels โ Add "Yes"/"No" labels near decision arrows
v2 Modernized Version
Full checkout flow with multiple branches: 6-step happy path as a central VStack; payment branches into 3 gateways via HStack; validation forks to an error/retry path on the right; a parallel "conversion funnel" sidebar shows drop-off at each step. Uses diamond for decisions, ellipse for start/end, named status styles, and expression-driven branch arrows.
{
"version": "2.0",
"canvas": { "width": 1500, "height": 1080, "background": "cream", "padding": 0 },
"theme": { "roughness": 1.3, "bowing": 1.0, "fillStyle": "hachure", "fontFamily": "Comic Sans MS" },
"vars": { "stepW": 280, "stepH": 70, "gwW": 200, "gwH": 70, "funW": 340 },
"styles": {
"step": { "fill": "white", "fillStyle": "solid", "strokeWidth": 2 },
"start": { "extends": "step", "fill": "indigo.100", "stroke": "indigo.700", "strokeWidth": 3 },
"action": { "extends": "step", "stroke": "blue.600" },
"decision": { "extends": "step", "fill": "amber.100", "stroke": "amber.700" },
"gateway": { "extends": "step", "fill": "purple.50", "stroke": "purple.700" },
"success": { "extends": "step", "fill": "green.100", "stroke": "green.700", "strokeWidth": 3 },
"error": { "extends": "step", "fill": "red.100", "stroke": "red.700" },
"fun-step": { "extends": "step", "fill": "slate.50", "stroke": "slate.500" },
"fun-bar": { "fill": "indigo.300", "stroke": "indigo.700","strokeWidth": 2, "fillStyle": "solid" },
"edge": { "stroke": "slate.700","strokeWidth": 2 }
},
"elements": [
{ "id": "title", "type": "text", "x": 0, "y": 25, "w": 1500, "h": 36, "text": "Checkout Flow with Conversion Funnel", "fontSize": 26, "fontWeight": "bold", "align": "center" },
{ "id": "sub", "type": "text", "x": 0, "y": 64, "w": 1500, "h": 22, "text": "Happy path ยท 3 payment gateways ยท validation retry branch ยท per-step drop-off", "fontSize": 13, "align": "center" },
{ "type": "VStack", "x": 380, "y": 110, "gap": 30, "align": "start", "children": [
{ "id": "cart", "type": "ellipse", "style": "start", "w": "$stepW", "h": "$stepH" },
{ "id": "auth", "type": "rectangle", "style": "action", "w": "$stepW", "h": "$stepH", "borderRadius": 10 },
{ "id": "ship", "type": "rectangle", "style": "action", "w": "$stepW", "h": "$stepH", "borderRadius": 10 },
{ "id": "validate", "type": "diamond", "style": "decision", "w": "$stepW", "h": 90 },
{ "id": "pay", "type": "rectangle", "style": "action", "w": "$stepW", "h": "$stepH", "borderRadius": 10 }
]},
{ "id": "cart-t", "type": "text", "position": { "inside": "#cart", "align": "center", "padding": 18 }, "w": 280, "h": 32, "text": "๐ Cart Review\nstart", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "auth-t", "type": "text", "position": { "inside": "#auth", "align": "center", "padding": 18 }, "w": 280, "h": 32, "text": "๐ Auth ยท Sign-in or Guest", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "ship-t", "type": "text", "position": { "inside": "#ship", "align": "center", "padding": 18 }, "w": 280, "h": 32, "text": "๐ฆ Shipping address", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "validate-t", "type": "text", "position": { "inside": "#validate", "align": "center", "padding": 28 }, "w": 280, "h": 28, "text": "Address valid?", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "pay-t", "type": "text", "position": { "inside": "#pay", "align": "center", "padding": 18 }, "w": 280, "h": 32, "text": "๐ณ Choose payment method", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "a1", "type": "arrow", "style": "edge", "x": "=cart.centerX", "y": "=cart.bottom", "w": 0, "h": 30, "endArrowhead": "arrow" },
{ "id": "a2", "type": "arrow", "style": "edge", "x": "=auth.centerX", "y": "=auth.bottom", "w": 0, "h": 30, "endArrowhead": "arrow" },
{ "id": "a3", "type": "arrow", "style": "edge", "x": "=ship.centerX", "y": "=ship.bottom", "w": 0, "h": 30, "endArrowhead": "arrow" },
{ "id": "a4", "type": "arrow", "x": "=validate.centerX", "y": "=validate.bottom", "w": 0, "h": 30, "endArrowhead": "arrow", "options": { "stroke": "green.700", "strokeWidth": 2 } },
{ "id": "yes-l", "type": "text", "x": "=validate.centerX + 8", "y": "=validate.bottom + 4", "w": 50, "h": 18, "text": "Yes", "fontSize": 12, "fontWeight": "bold", "options": { "stroke": "green.700" } },
{ "id": "retry", "type": "rectangle", "style": "error", "position": { "rightOf": "#validate", "gap": 50 }, "w": 230, "h": 70, "borderRadius": 10 },
{ "id": "retry-t", "type": "text", "position": { "inside": "#retry", "align": "center", "padding": 14 }, "w": 230, "h": 32, "text": "โ Show address error\nretry input", "fontSize": 13, "fontWeight": "bold", "align": "center" },
{ "id": "noarrow", "type": "arrow", "x": "=validate.right", "y": "=validate.centerY", "w": "=retry.x - validate.right", "h": 0, "endArrowhead": "arrow", "options": { "stroke": "red.700", "strokeWidth": 2 } },
{ "id": "no-l", "type": "text", "x": "=validate.right + 4", "y": "=validate.centerY - 22", "w": 50, "h": 18, "text": "No", "fontSize": 12, "fontWeight": "bold", "options": { "stroke": "red.700" } },
{ "type": "HStack", "x": 200, "y": 600, "gap": 30, "children": [
{ "id": "gw-card", "type": "rectangle", "style": "gateway", "w": "$gwW", "h": "$gwH", "borderRadius": 10 },
{ "id": "gw-pp", "type": "rectangle", "style": "gateway", "w": "$gwW", "h": "$gwH", "borderRadius": 10 },
{ "id": "gw-apl", "type": "rectangle", "style": "gateway", "w": "$gwW", "h": "$gwH", "borderRadius": 10 },
{ "id": "gw-bnpl", "type": "rectangle", "style": "gateway", "w": "$gwW", "h": "$gwH", "borderRadius": 10 }
]},
{ "id": "gw-card-t", "type": "text", "position": { "inside": "#gw-card", "align": "center", "padding": 14 }, "w": 200, "h": 34, "text": "๐ณ Card\nStripe", "fontSize": 13, "fontWeight": "bold", "align": "center" },
{ "id": "gw-pp-t", "type": "text", "position": { "inside": "#gw-pp", "align": "center", "padding": 14 }, "w": 200, "h": 34, "text": "๐
ฟ๏ธ PayPal", "fontSize": 13, "fontWeight": "bold", "align": "center" },
{ "id": "gw-apl-t", "type": "text", "position": { "inside": "#gw-apl", "align": "center", "padding": 14 }, "w": 200, "h": 34, "text": "๐ Apple Pay", "fontSize": 13, "fontWeight": "bold", "align": "center" },
{ "id": "gw-bnpl-t", "type": "text", "position": { "inside": "#gw-bnpl", "align": "center", "padding": 14 }, "w": 200, "h": 34, "text": "๐ฐ Klarna BNPL", "fontSize": 13, "fontWeight": "bold", "align": "center" },
{ "id": "fan1", "type": "arrow", "x": "=pay.centerX", "y": "=pay.bottom", "w": "=gw-card.centerX - pay.centerX", "h": 40, "endArrowhead": "arrow", "options": { "stroke": "purple.700", "strokeWidth": 2 } },
{ "id": "fan2", "type": "arrow", "x": "=pay.centerX", "y": "=pay.bottom", "w": "=gw-pp.centerX - pay.centerX", "h": 40, "endArrowhead": "arrow", "options": { "stroke": "purple.700", "strokeWidth": 2 } },
{ "id": "fan3", "type": "arrow", "x": "=pay.centerX", "y": "=pay.bottom", "w": "=gw-apl.centerX - pay.centerX", "h": 40, "endArrowhead": "arrow", "options": { "stroke": "purple.700", "strokeWidth": 2 } },
{ "id": "fan4", "type": "arrow", "x": "=pay.centerX", "y": "=pay.bottom", "w": "=gw-bnpl.centerX - pay.centerX", "h": 40, "endArrowhead": "arrow", "options": { "stroke": "purple.700", "strokeWidth": 2 } },
{ "id": "confirm", "type": "ellipse", "style": "success", "position": { "centerIn": "#pay", "offset": { "x": 0, "y": 250 } }, "w": "$stepW", "h": "$stepH" },
{ "id": "confirm-t", "type": "text", "position": { "inside": "#confirm", "align": "center", "padding": 18 }, "w": 280, "h": 32, "text": "โ
Order Confirmation\nยท receipt email", "fontSize": 14, "fontWeight": "bold", "align": "center" },
{ "id": "merge1", "type": "arrow", "x": "=gw-card.centerX", "y": "=gw-card.bottom", "w": "=confirm.centerX - gw-card.centerX", "h": "=confirm.y - gw-card.bottom", "endArrowhead": "arrow", "options": { "stroke": "green.700", "strokeWidth": 2 } },
{ "id": "merge2", "type": "arrow", "x": "=gw-pp.centerX", "y": "=gw-pp.bottom", "w": "=confirm.centerX - gw-pp.centerX", "h": "=confirm.y - gw-pp.bottom", "endArrowhead": "arrow", "options": { "stroke": "green.700", "strokeWidth": 2 } },
{ "id": "merge3", "type": "arrow", "x": "=gw-apl.centerX", "y": "=gw-apl.bottom", "w": "=confirm.centerX - gw-apl.centerX", "h": "=confirm.y - gw-apl.bottom", "endArrowhead": "arrow", "options": { "stroke": "green.700", "strokeWidth": 2 } },
{ "id": "merge4", "type": "arrow", "x": "=gw-bnpl.centerX", "y": "=gw-bnpl.bottom", "w": "=confirm.centerX - gw-bnpl.centerX", "h": "=confirm.y - gw-bnpl.bottom", "endArrowhead": "arrow", "options": { "stroke": "green.700", "strokeWidth": 2 } },
{ "id": "fun-h", "type": "text", "x": 1080, "y": 100, "w": 380, "h": 26, "text": "Conversion Funnel", "fontSize": 17, "fontWeight": "bold" },
{ "id": "fun-s", "type": "text", "x": 1080, "y": 124, "w": 380, "h": 18, "text": "% of sessions reaching each step (last 30d)", "fontSize": 12 },
{ "id": "f1", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 160, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f1-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 160, "w": "=$funW * 1.00", "h": 44, "borderRadius": 8 },
{ "id": "f1-t", "type": "text", "position": { "inside": "#f1", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Cart ยท 100% (12,400 sessions)", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "f2", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 215, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f2-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 215, "w": "=$funW * 0.78", "h": 44, "borderRadius": 8 },
{ "id": "f2-t", "type": "text", "position": { "inside": "#f2", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Auth ยท 78%", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "f3", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 270, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f3-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 270, "w": "=$funW * 0.71", "h": 44, "borderRadius": 8 },
{ "id": "f3-t", "type": "text", "position": { "inside": "#f3", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Shipping ยท 71%", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "f4", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 325, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f4-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 325, "w": "=$funW * 0.65", "h": 44, "borderRadius": 8 },
{ "id": "f4-t", "type": "text", "position": { "inside": "#f4", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Validate ยท 65%", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "f5", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 380, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f5-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 380, "w": "=$funW * 0.58", "h": 44, "borderRadius": 8 },
{ "id": "f5-t", "type": "text", "position": { "inside": "#f5", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Payment ยท 58%", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "f6", "type": "rectangle", "style": "fun-step", "x": 1080, "y": 435, "w": "$funW", "h": 44, "borderRadius": 8 },
{ "id": "f6-b", "type": "rectangle", "style": "fun-bar", "x": 1080, "y": 435, "w": "=$funW * 0.52", "h": 44, "borderRadius": 8 },
{ "id": "f6-t", "type": "text", "position": { "inside": "#f6", "align": "center", "padding": 8 }, "w": 340, "h": 26, "text": "Confirmed ยท 52%", "fontSize": 12, "fontWeight": "bold", "align": "center" },
{ "id": "fun-note", "type": "text", "x": 1080, "y": 510, "w": 380, "h": 60, "text": "Biggest drop-off: cart โ auth (22 pp). Test guest checkout above the fold next sprint.", "fontSize": 12, "fontStyle": "italic", "align": "left" }
]
}
Showcase: 6-step main flow as VStack; payment branches via HStack of 4 gateways with computed-width fan arrows; error path via position: { rightOf }; parallel funnel sidebar with bar widths driven by =$funW * 0.78; uses ellipse + diamond + rectangle + arrow.
๐ Build Your Checkout Flow
Open Privacy Sketch and start creating your e-commerce checkout diagram. Use the example JSON as your starting point.
Open Privacy SketchNext Steps
- CI/CD Pipeline Tutorial โ Build DevOps diagrams
- Org Chart Tutorial โ Create team structures
- LLM Reference โ Technical JSON documentation