Skip to main content

Overview

In this tutorial, you’ll create a checkout extension that displays estimated delivery dates based on the customer’s shipping address.

What You’ll Build

A checkout extension that:
  • Shows a delivery estimate banner
  • Updates based on shipping address
  • Uses Shopify UI components
  • Follows best practices

Step 1: Write Your Prompt

Go to your Synapse dashboard and enter this prompt:
Create a checkout extension that displays estimated delivery dates 
based on the customer's shipping address. Show a banner with:
- An icon for visual appeal
- The delivery date range (5-7 business days)
- Different messaging for US vs international addresses
- Professional styling that matches Shopify's checkout

Step 2: Review Generated Code

Synapse will generate TypeScript/React code like this:
import {
  Banner,
  useShippingAddress,
  useApi,
} from '@shopify/ui-extensions-react/checkout';

export default function DeliveryEstimate() {
  const address = useShippingAddress();
  const { i18n } = useApi();
  
  // Calculate delivery window
  const getDeliveryEstimate = () => {
    if (!address?.countryCode) {
      return null;
    }
    
    const isDomestic = address.countryCode === 'US';
    const days = isDomestic ? '5-7' : '10-14';
    const deliveryDate = new Date();
    deliveryDate.setDate(deliveryDate.getDate() + (isDomestic ? 7 : 14));
    
    return {
      days,
      date: i18n.formatDate(deliveryDate, { dateStyle: 'long' })
    };
  };
  
  const estimate = getDeliveryEstimate();
  
  if (!estimate) return null;
  
  return (
    <Banner title="Estimated Delivery">
      Your order will arrive in {estimate.days} business days 
      (by {estimate.date})
    </Banner>
  );
}

Step 3: Validation

Synapse automatically validates your code:
✅ All Shopify UI components exist and are imported correctly
✅ React hooks are used properly (no conditional calls)
✅ Any GraphQL queries match Shopify’s schema
✅ Type safety and proper imports

Step 4: Self-Correction

If validation finds issues, Synapse automatically fixes them: Example Issue Found:
- import { Banner } from '@shopify/ui-extensions-react';
+ import { Banner } from '@shopify/ui-extensions-react/checkout';
Correction Applied:
  • ✅ Fixed in attempt 1
  • Validation score: 95/100

Step 5: Deployment

Click “Deploy” and Synapse will:
  1. Push to GitHub: Code is committed to your repository
  2. Create Fly.io Service: Container is built automatically
  3. Run Shopify CLI: Extension is deployed to your dev store
  4. Auto-Release: Latest version is released
🚀 Deploying delivery-estimate to Shopify...
🔗 Linking to Shopify app...
📦 Installing dependencies...
 Extension deployed successfully!
📦 Version: 2024.10.30.1
🔗 View in Partner Dashboard

Step 6: Test in Checkout

  1. Go to your Shopify dev store admin
  2. Navigate to Settings → Checkout
  3. Click Customize
  4. Add your “Delivery Estimate” extension from the sidebar
  5. Click Save
Now test the checkout:
  • Add a product to cart
  • Go to checkout
  • Enter different shipping addresses (US vs international)
  • See the delivery estimate update automatically

Next Steps

Common Variations

Add a Countdown Timer

const [timeLeft, setTimeLeft] = useState('');

useEffect(() => {
  const timer = setInterval(() => {
    const cutoff = new Date();
    cutoff.setHours(15, 0, 0, 0); // 3 PM cutoff
    
    const diff = cutoff - new Date();
    if (diff > 0) {
      const hours = Math.floor(diff / (1000 * 60 * 60));
      const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
      setTimeLeft(`${hours}h ${minutes}m`);
    }
  }, 1000);
  
  return () => clearInterval(timer);
}, []);

Show Shipping Method Impact

import { useShippingLine } from '@shopify/ui-extensions-react/checkout';

const shippingLine = useShippingLine();
const isExpedited = shippingLine?.code.includes('express');

return (
  <Banner>
    {isExpedited 
      ? 'Express delivery: 2-3 business days'
      : 'Standard delivery: 5-7 business days'
    }
  </Banner>
);

Troubleshooting

Make sure you’ve added it in the checkout editor at Settings → Checkout → Customize
Check that useShippingAddress() is imported from the correct package and the address object has a countryCode